eval.c revision c00c0b323fd46385faaa75395553247ed089eaba
1/* $Id: eval.c,v 1.6 1999/11/08 15:30:05 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.1
6 *
7 * Copyright (C) 1999  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * eval.c was written by
30 * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
31 * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
32 *
33 * My original implementation of evaluators was simplistic and didn't
34 * compute surface normal vectors properly.  Bernd and Volker applied
35 * used more sophisticated methods to get better results.
36 *
37 * Thanks guys!
38 */
39
40
41#ifdef PC_HEADER
42#include "all.h"
43#else
44#ifndef XFree86Server
45#include <math.h>
46#include <stdlib.h>
47#include <string.h>
48#else
49#include "GL/xf86glx.h"
50#endif
51#include "context.h"
52#include "eval.h"
53#include "macros.h"
54#include "mmath.h"
55#include "types.h"
56#include "vbcull.h"
57#include "vbfill.h"
58#include "vbxform.h"
59#endif
60
61
62static GLfloat inv_tab[MAX_EVAL_ORDER];
63
64/*
65 * Do one-time initialization for evaluators.
66 */
67void gl_init_eval( void )
68{
69  static int init_flag = 0;
70  GLuint i;
71
72  /* Compute a table of nCr (combination) values used by the
73   * Bernstein polynomial generator.
74   */
75
76  /* KW: precompute 1/x for useful x.
77   */
78  if (init_flag==0)
79  {
80     for (i = 1 ; i < MAX_EVAL_ORDER ; i++)
81	inv_tab[i] = 1.0 / i;
82  }
83
84  init_flag = 1;
85}
86
87
88
89/*
90 * Horner scheme for Bezier curves
91 *
92 * Bezier curves can be computed via a Horner scheme.
93 * Horner is numerically less stable than the de Casteljau
94 * algorithm, but it is faster. For curves of degree n
95 * the complexity of Horner is O(n) and de Casteljau is O(n^2).
96 * Since stability is not important for displaying curve
97 * points I decided to use the Horner scheme.
98 *
99 * A cubic Bezier curve with control points b0, b1, b2, b3 can be
100 * written as
101 *
102 *        (([3]        [3]     )     [3]       )     [3]
103 * c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
104 *
105 *                                           [n]
106 * where s=1-t and the binomial coefficients [i]. These can
107 * be computed iteratively using the identity:
108 *
109 * [n]               [n  ]             [n]
110 * [i] = (n-i+1)/i * [i-1]     and     [0] = 1
111 */
112
113
114static void
115horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t,
116                    GLuint dim, GLuint order)
117{
118  GLfloat s, powert;
119  GLuint i, k, bincoeff;
120
121  if(order >= 2)
122  {
123    bincoeff = order-1;
124    s = 1.0-t;
125
126    for(k=0; k<dim; k++)
127      out[k] = s*cp[k] + bincoeff*t*cp[dim+k];
128
129    for(i=2, cp+=2*dim, powert=t*t; i<order; i++, powert*=t, cp +=dim)
130    {
131      bincoeff *= order-i;
132      bincoeff *= inv_tab[i];
133
134      for(k=0; k<dim; k++)
135        out[k] = s*out[k] + bincoeff*powert*cp[k];
136    }
137  }
138  else /* order=1 -> constant curve */
139  {
140    for(k=0; k<dim; k++)
141      out[k] = cp[k];
142  }
143}
144
145/*
146 * Tensor product Bezier surfaces
147 *
148 * Again the Horner scheme is used to compute a point on a
149 * TP Bezier surface. First a control polygon for a curve
150 * on the surface in one parameter direction is computed,
151 * then the point on the curve for the other parameter
152 * direction is evaluated.
153 *
154 * To store the curve control polygon additional storage
155 * for max(uorder,vorder) points is needed in the
156 * control net cn.
157 */
158
159static void
160horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v,
161                   GLuint dim, GLuint uorder, GLuint vorder)
162{
163  GLfloat *cp = cn + uorder*vorder*dim;
164  GLuint i, uinc = vorder*dim;
165
166  if(vorder > uorder)
167  {
168    if(uorder >= 2)
169    {
170      GLfloat s, poweru;
171      GLuint j, k, bincoeff;
172
173      /* Compute the control polygon for the surface-curve in u-direction */
174      for(j=0; j<vorder; j++)
175      {
176        GLfloat *ucp = &cn[j*dim];
177
178        /* Each control point is the point for parameter u on a */
179        /* curve defined by the control polygons in u-direction */
180	bincoeff = uorder-1;
181	s = 1.0-u;
182
183	for(k=0; k<dim; k++)
184	  cp[j*dim+k] = s*ucp[k] + bincoeff*u*ucp[uinc+k];
185
186	for(i=2, ucp+=2*uinc, poweru=u*u; i<uorder;
187            i++, poweru*=u, ucp +=uinc)
188	{
189	  bincoeff *= uorder-i;
190          bincoeff *= inv_tab[i];
191
192	  for(k=0; k<dim; k++)
193	    cp[j*dim+k] = s*cp[j*dim+k] + bincoeff*poweru*ucp[k];
194	}
195      }
196
197      /* Evaluate curve point in v */
198      horner_bezier_curve(cp, out, v, dim, vorder);
199    }
200    else /* uorder=1 -> cn defines a curve in v */
201      horner_bezier_curve(cn, out, v, dim, vorder);
202  }
203  else /* vorder <= uorder */
204  {
205    if(vorder > 1)
206    {
207      GLuint i;
208
209      /* Compute the control polygon for the surface-curve in u-direction */
210      for(i=0; i<uorder; i++, cn += uinc)
211      {
212	/* For constant i all cn[i][j] (j=0..vorder) are located */
213	/* on consecutive memory locations, so we can use        */
214	/* horner_bezier_curve to compute the control points     */
215
216	horner_bezier_curve(cn, &cp[i*dim], v, dim, vorder);
217      }
218
219      /* Evaluate curve point in u */
220      horner_bezier_curve(cp, out, u, dim, uorder);
221    }
222    else  /* vorder=1 -> cn defines a curve in u */
223      horner_bezier_curve(cn, out, u, dim, uorder);
224  }
225}
226
227/*
228 * The direct de Casteljau algorithm is used when a point on the
229 * surface and the tangent directions spanning the tangent plane
230 * should be computed (this is needed to compute normals to the
231 * surface). In this case the de Casteljau algorithm approach is
232 * nicer because a point and the partial derivatives can be computed
233 * at the same time. To get the correct tangent length du and dv
234 * must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
235 * Since only the directions are needed, this scaling step is omitted.
236 *
237 * De Casteljau needs additional storage for uorder*vorder
238 * values in the control net cn.
239 */
240
241static void
242de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv,
243                  GLfloat u, GLfloat v, GLuint dim,
244                  GLuint uorder, GLuint vorder)
245{
246  GLfloat *dcn = cn + uorder*vorder*dim;
247  GLfloat us = 1.0-u, vs = 1.0-v;
248  GLuint h, i, j, k;
249  GLuint minorder = uorder < vorder ? uorder : vorder;
250  GLuint uinc = vorder*dim;
251  GLuint dcuinc = vorder;
252
253  /* Each component is evaluated separately to save buffer space  */
254  /* This does not drasticaly decrease the performance of the     */
255  /* algorithm. If additional storage for (uorder-1)*(vorder-1)   */
256  /* points would be available, the components could be accessed  */
257  /* in the innermost loop which could lead to less cache misses. */
258
259#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)]
260#define DCN(I, J) dcn[(I)*dcuinc+(J)]
261  if(minorder < 3)
262  {
263    if(uorder==vorder)
264    {
265      for(k=0; k<dim; k++)
266      {
267	/* Derivative direction in u */
268	du[k] = vs*(CN(1,0,k) - CN(0,0,k)) +
269	         v*(CN(1,1,k) - CN(0,1,k));
270
271	/* Derivative direction in v */
272	dv[k] = us*(CN(0,1,k) - CN(0,0,k)) +
273	         u*(CN(1,1,k) - CN(1,0,k));
274
275	/* bilinear de Casteljau step */
276        out[k] =  us*(vs*CN(0,0,k) + v*CN(0,1,k)) +
277	           u*(vs*CN(1,0,k) + v*CN(1,1,k));
278      }
279    }
280    else if(minorder == uorder)
281    {
282      for(k=0; k<dim; k++)
283      {
284	/* bilinear de Casteljau step */
285	DCN(1,0) =    CN(1,0,k) -   CN(0,0,k);
286	DCN(0,0) = us*CN(0,0,k) + u*CN(1,0,k);
287
288	for(j=0; j<vorder-1; j++)
289	{
290	  /* for the derivative in u */
291	  DCN(1,j+1) =    CN(1,j+1,k) -   CN(0,j+1,k);
292	  DCN(1,j)   = vs*DCN(1,j)    + v*DCN(1,j+1);
293
294	  /* for the `point' */
295	  DCN(0,j+1) = us*CN(0,j+1,k) + u*CN(1,j+1,k);
296	  DCN(0,j)   = vs*DCN(0,j)    + v*DCN(0,j+1);
297	}
298
299	/* remaining linear de Casteljau steps until the second last step */
300	for(h=minorder; h<vorder-1; h++)
301	  for(j=0; j<vorder-h; j++)
302	  {
303	    /* for the derivative in u */
304	    DCN(1,j) = vs*DCN(1,j) + v*DCN(1,j+1);
305
306	    /* for the `point' */
307	    DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1);
308	  }
309
310	/* derivative direction in v */
311	dv[k] = DCN(0,1) - DCN(0,0);
312
313	/* derivative direction in u */
314	du[k] =   vs*DCN(1,0) + v*DCN(1,1);
315
316	/* last linear de Casteljau step */
317	out[k] =  vs*DCN(0,0) + v*DCN(0,1);
318      }
319    }
320    else /* minorder == vorder */
321    {
322      for(k=0; k<dim; k++)
323      {
324	/* bilinear de Casteljau step */
325	DCN(0,1) =    CN(0,1,k) -   CN(0,0,k);
326	DCN(0,0) = vs*CN(0,0,k) + v*CN(0,1,k);
327	for(i=0; i<uorder-1; i++)
328	{
329	  /* for the derivative in v */
330	  DCN(i+1,1) =    CN(i+1,1,k) -   CN(i+1,0,k);
331	  DCN(i,1)   = us*DCN(i,1)    + u*DCN(i+1,1);
332
333	  /* for the `point' */
334	  DCN(i+1,0) = vs*CN(i+1,0,k) + v*CN(i+1,1,k);
335	  DCN(i,0)   = us*DCN(i,0)    + u*DCN(i+1,0);
336	}
337
338	/* remaining linear de Casteljau steps until the second last step */
339	for(h=minorder; h<uorder-1; h++)
340	  for(i=0; i<uorder-h; i++)
341	  {
342	    /* for the derivative in v */
343	    DCN(i,1) = us*DCN(i,1) + u*DCN(i+1,1);
344
345	    /* for the `point' */
346	    DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
347	  }
348
349	/* derivative direction in u */
350	du[k] = DCN(1,0) - DCN(0,0);
351
352	/* derivative direction in v */
353	dv[k] =   us*DCN(0,1) + u*DCN(1,1);
354
355	/* last linear de Casteljau step */
356	out[k] =  us*DCN(0,0) + u*DCN(1,0);
357      }
358    }
359  }
360  else if(uorder == vorder)
361  {
362    for(k=0; k<dim; k++)
363    {
364      /* first bilinear de Casteljau step */
365      for(i=0; i<uorder-1; i++)
366      {
367	DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k);
368	for(j=0; j<vorder-1; j++)
369	{
370	  DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k);
371	  DCN(i,j)   = vs*DCN(i,j)    + v*DCN(i,j+1);
372	}
373      }
374
375      /* remaining bilinear de Casteljau steps until the second last step */
376      for(h=2; h<minorder-1; h++)
377	for(i=0; i<uorder-h; i++)
378	{
379	  DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
380	  for(j=0; j<vorder-h; j++)
381	  {
382	    DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1);
383	    DCN(i,j)   = vs*DCN(i,j)   + v*DCN(i,j+1);
384	  }
385	}
386
387      /* derivative direction in u */
388      du[k] = vs*(DCN(1,0) - DCN(0,0)) +
389	       v*(DCN(1,1) - DCN(0,1));
390
391      /* derivative direction in v */
392      dv[k] = us*(DCN(0,1) - DCN(0,0)) +
393	       u*(DCN(1,1) - DCN(1,0));
394
395      /* last bilinear de Casteljau step */
396      out[k] =  us*(vs*DCN(0,0) + v*DCN(0,1)) +
397	         u*(vs*DCN(1,0) + v*DCN(1,1));
398    }
399  }
400  else if(minorder == uorder)
401  {
402    for(k=0; k<dim; k++)
403    {
404      /* first bilinear de Casteljau step */
405      for(i=0; i<uorder-1; i++)
406      {
407	DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k);
408	for(j=0; j<vorder-1; j++)
409	{
410	  DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k);
411	  DCN(i,j)   = vs*DCN(i,j)    + v*DCN(i,j+1);
412	}
413      }
414
415      /* remaining bilinear de Casteljau steps until the second last step */
416      for(h=2; h<minorder-1; h++)
417	for(i=0; i<uorder-h; i++)
418	{
419	  DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
420	  for(j=0; j<vorder-h; j++)
421	  {
422	    DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1);
423	    DCN(i,j)   = vs*DCN(i,j)   + v*DCN(i,j+1);
424	  }
425	}
426
427      /* last bilinear de Casteljau step */
428      DCN(2,0) =    DCN(1,0) -   DCN(0,0);
429      DCN(0,0) = us*DCN(0,0) + u*DCN(1,0);
430      for(j=0; j<vorder-1; j++)
431      {
432	/* for the derivative in u */
433	DCN(2,j+1) =    DCN(1,j+1) -    DCN(0,j+1);
434	DCN(2,j)   = vs*DCN(2,j)    + v*DCN(2,j+1);
435
436	/* for the `point' */
437	DCN(0,j+1) = us*DCN(0,j+1 ) + u*DCN(1,j+1);
438	DCN(0,j)   = vs*DCN(0,j)    + v*DCN(0,j+1);
439      }
440
441      /* remaining linear de Casteljau steps until the second last step */
442      for(h=minorder; h<vorder-1; h++)
443	for(j=0; j<vorder-h; j++)
444	{
445	  /* for the derivative in u */
446	  DCN(2,j) = vs*DCN(2,j) + v*DCN(2,j+1);
447
448	  /* for the `point' */
449	  DCN(0,j) = vs*DCN(0,j) + v*DCN(0,j+1);
450	}
451
452      /* derivative direction in v */
453      dv[k] = DCN(0,1) - DCN(0,0);
454
455      /* derivative direction in u */
456      du[k] =   vs*DCN(2,0) + v*DCN(2,1);
457
458      /* last linear de Casteljau step */
459      out[k] =  vs*DCN(0,0) + v*DCN(0,1);
460    }
461  }
462  else /* minorder == vorder */
463  {
464    for(k=0; k<dim; k++)
465    {
466      /* first bilinear de Casteljau step */
467      for(i=0; i<uorder-1; i++)
468      {
469	DCN(i,0) = us*CN(i,0,k) + u*CN(i+1,0,k);
470	for(j=0; j<vorder-1; j++)
471	{
472	  DCN(i,j+1) = us*CN(i,j+1,k) + u*CN(i+1,j+1,k);
473	  DCN(i,j)   = vs*DCN(i,j)    + v*DCN(i,j+1);
474	}
475      }
476
477      /* remaining bilinear de Casteljau steps until the second last step */
478      for(h=2; h<minorder-1; h++)
479	for(i=0; i<uorder-h; i++)
480	{
481	  DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
482	  for(j=0; j<vorder-h; j++)
483	  {
484	    DCN(i,j+1) = us*DCN(i,j+1) + u*DCN(i+1,j+1);
485	    DCN(i,j)   = vs*DCN(i,j)   + v*DCN(i,j+1);
486	  }
487	}
488
489      /* last bilinear de Casteljau step */
490      DCN(0,2) =    DCN(0,1) -   DCN(0,0);
491      DCN(0,0) = vs*DCN(0,0) + v*DCN(0,1);
492      for(i=0; i<uorder-1; i++)
493      {
494	/* for the derivative in v */
495	DCN(i+1,2) =    DCN(i+1,1)  -   DCN(i+1,0);
496	DCN(i,2)   = us*DCN(i,2)    + u*DCN(i+1,2);
497
498	/* for the `point' */
499	DCN(i+1,0) = vs*DCN(i+1,0)  + v*DCN(i+1,1);
500	DCN(i,0)   = us*DCN(i,0)    + u*DCN(i+1,0);
501      }
502
503      /* remaining linear de Casteljau steps until the second last step */
504      for(h=minorder; h<uorder-1; h++)
505	for(i=0; i<uorder-h; i++)
506	{
507	  /* for the derivative in v */
508	  DCN(i,2) = us*DCN(i,2) + u*DCN(i+1,2);
509
510	  /* for the `point' */
511	  DCN(i,0) = us*DCN(i,0) + u*DCN(i+1,0);
512	}
513
514      /* derivative direction in u */
515      du[k] = DCN(1,0) - DCN(0,0);
516
517      /* derivative direction in v */
518      dv[k] =   us*DCN(0,2) + u*DCN(1,2);
519
520      /* last linear de Casteljau step */
521      out[k] =  us*DCN(0,0) + u*DCN(1,0);
522    }
523  }
524#undef DCN
525#undef CN
526}
527
528/*
529 * Return the number of components per control point for any type of
530 * evaluator.  Return 0 if bad target.
531 */
532
533static GLint components( GLenum target )
534{
535   switch (target) {
536      case GL_MAP1_VERTEX_3:		return 3;
537      case GL_MAP1_VERTEX_4:		return 4;
538      case GL_MAP1_INDEX:		return 1;
539      case GL_MAP1_COLOR_4:		return 4;
540      case GL_MAP1_NORMAL:		return 3;
541      case GL_MAP1_TEXTURE_COORD_1:	return 1;
542      case GL_MAP1_TEXTURE_COORD_2:	return 2;
543      case GL_MAP1_TEXTURE_COORD_3:	return 3;
544      case GL_MAP1_TEXTURE_COORD_4:	return 4;
545      case GL_MAP2_VERTEX_3:		return 3;
546      case GL_MAP2_VERTEX_4:		return 4;
547      case GL_MAP2_INDEX:		return 1;
548      case GL_MAP2_COLOR_4:		return 4;
549      case GL_MAP2_NORMAL:		return 3;
550      case GL_MAP2_TEXTURE_COORD_1:	return 1;
551      case GL_MAP2_TEXTURE_COORD_2:	return 2;
552      case GL_MAP2_TEXTURE_COORD_3:	return 3;
553      case GL_MAP2_TEXTURE_COORD_4:	return 4;
554      default:				return 0;
555   }
556}
557
558
559/**********************************************************************/
560/***            Copy and deallocate control points                  ***/
561/**********************************************************************/
562
563
564/*
565 * Copy 1-parametric evaluator control points from user-specified
566 * memory space to a buffer of contiguous control points.
567 * Input:  see glMap1f for details
568 * Return:  pointer to buffer of contiguous control points or NULL if out
569 *          of memory.
570 */
571GLfloat *gl_copy_map_points1f( GLenum target,
572                               GLint ustride, GLint uorder,
573                               const GLfloat *points )
574{
575   GLfloat *buffer, *p;
576   GLint i, k, size = components(target);
577
578   if (!points || size==0) {
579      return NULL;
580   }
581
582   buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat));
583
584   if(buffer)
585      for(i=0, p=buffer; i<uorder; i++, points+=ustride)
586	for(k=0; k<size; k++)
587	  *p++ = points[k];
588
589   return buffer;
590}
591
592
593
594/*
595 * Same as above but convert doubles to floats.
596 */
597GLfloat *gl_copy_map_points1d( GLenum target,
598			        GLint ustride, GLint uorder,
599			        const GLdouble *points )
600{
601   GLfloat *buffer, *p;
602   GLint i, k, size = components(target);
603
604   if (!points || size==0) {
605      return NULL;
606   }
607
608   buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat));
609
610   if(buffer)
611      for(i=0, p=buffer; i<uorder; i++, points+=ustride)
612	for(k=0; k<size; k++)
613	  *p++ = (GLfloat) points[k];
614
615   return buffer;
616}
617
618
619
620/*
621 * Copy 2-parametric evaluator control points from user-specified
622 * memory space to a buffer of contiguous control points.
623 * Additional memory is allocated to be used by the horner and
624 * de Casteljau evaluation schemes.
625 *
626 * Input:  see glMap2f for details
627 * Return:  pointer to buffer of contiguous control points or NULL if out
628 *          of memory.
629 */
630GLfloat *gl_copy_map_points2f( GLenum target,
631			        GLint ustride, GLint uorder,
632			        GLint vstride, GLint vorder,
633			        const GLfloat *points )
634{
635   GLfloat *buffer, *p;
636   GLint i, j, k, size, dsize, hsize;
637   GLint uinc;
638
639   size = components(target);
640
641   if (!points || size==0) {
642      return NULL;
643   }
644
645   /* max(uorder, vorder) additional points are used in      */
646   /* horner evaluation and uorder*vorder additional */
647   /* values are needed for de Casteljau                     */
648   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
649   hsize = (uorder > vorder ? uorder : vorder)*size;
650
651   if(hsize>dsize)
652     buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat));
653   else
654     buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat));
655
656   /* compute the increment value for the u-loop */
657   uinc = ustride - vorder*vstride;
658
659   if (buffer)
660      for (i=0, p=buffer; i<uorder; i++, points += uinc)
661	 for (j=0; j<vorder; j++, points += vstride)
662	    for (k=0; k<size; k++)
663	       *p++ = points[k];
664
665   return buffer;
666}
667
668
669
670/*
671 * Same as above but convert doubles to floats.
672 */
673GLfloat *gl_copy_map_points2d(GLenum target,
674                              GLint ustride, GLint uorder,
675                              GLint vstride, GLint vorder,
676                              const GLdouble *points )
677{
678   GLfloat *buffer, *p;
679   GLint i, j, k, size, hsize, dsize;
680   GLint uinc;
681
682   size = components(target);
683
684   if (!points || size==0) {
685      return NULL;
686   }
687
688   /* max(uorder, vorder) additional points are used in      */
689   /* horner evaluation and uorder*vorder additional */
690   /* values are needed for de Casteljau                     */
691   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
692   hsize = (uorder > vorder ? uorder : vorder)*size;
693
694   if(hsize>dsize)
695     buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat));
696   else
697     buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat));
698
699   /* compute the increment value for the u-loop */
700   uinc = ustride - vorder*vstride;
701
702   if (buffer)
703      for (i=0, p=buffer; i<uorder; i++, points += uinc)
704	 for (j=0; j<vorder; j++, points += vstride)
705	    for (k=0; k<size; k++)
706	       *p++ = (GLfloat) points[k];
707
708   return buffer;
709}
710
711
712/*
713 * This function is called by the display list deallocator function to
714 * specify that a given set of control points are no longer needed.
715 */
716void gl_free_control_points( GLcontext* ctx, GLenum target, GLfloat *data )
717{
718   struct gl_1d_map *map1 = NULL;
719   struct gl_2d_map *map2 = NULL;
720
721   switch (target) {
722      case GL_MAP1_VERTEX_3:
723         map1 = &ctx->EvalMap.Map1Vertex3;
724         break;
725      case GL_MAP1_VERTEX_4:
726         map1 = &ctx->EvalMap.Map1Vertex4;
727	 break;
728      case GL_MAP1_INDEX:
729         map1 = &ctx->EvalMap.Map1Index;
730         break;
731      case GL_MAP1_COLOR_4:
732         map1 = &ctx->EvalMap.Map1Color4;
733         break;
734      case GL_MAP1_NORMAL:
735         map1 = &ctx->EvalMap.Map1Normal;
736	 break;
737      case GL_MAP1_TEXTURE_COORD_1:
738         map1 = &ctx->EvalMap.Map1Texture1;
739	 break;
740      case GL_MAP1_TEXTURE_COORD_2:
741         map1 = &ctx->EvalMap.Map1Texture2;
742	 break;
743      case GL_MAP1_TEXTURE_COORD_3:
744         map1 = &ctx->EvalMap.Map1Texture3;
745	 break;
746      case GL_MAP1_TEXTURE_COORD_4:
747         map1 = &ctx->EvalMap.Map1Texture4;
748	 break;
749      case GL_MAP2_VERTEX_3:
750         map2 = &ctx->EvalMap.Map2Vertex3;
751	 break;
752      case GL_MAP2_VERTEX_4:
753         map2 = &ctx->EvalMap.Map2Vertex4;
754	 break;
755      case GL_MAP2_INDEX:
756         map2 = &ctx->EvalMap.Map2Index;
757	 break;
758      case GL_MAP2_COLOR_4:
759         map2 = &ctx->EvalMap.Map2Color4;
760         break;
761      case GL_MAP2_NORMAL:
762         map2 = &ctx->EvalMap.Map2Normal;
763	 break;
764      case GL_MAP2_TEXTURE_COORD_1:
765         map2 = &ctx->EvalMap.Map2Texture1;
766	 break;
767      case GL_MAP2_TEXTURE_COORD_2:
768         map2 = &ctx->EvalMap.Map2Texture2;
769	 break;
770      case GL_MAP2_TEXTURE_COORD_3:
771         map2 = &ctx->EvalMap.Map2Texture3;
772	 break;
773      case GL_MAP2_TEXTURE_COORD_4:
774         map2 = &ctx->EvalMap.Map2Texture4;
775	 break;
776      default:
777	 gl_error( ctx, GL_INVALID_ENUM, "gl_free_control_points" );
778         return;
779   }
780
781   if (map1) {
782      if (data==map1->Points) {
783         /* The control points in the display list are currently */
784         /* being used so we can mark them as discard-able. */
785         map1->Retain = GL_FALSE;
786      }
787      else {
788         /* The control points in the display list are not currently */
789         /* being used. */
790         FREE( data );
791      }
792   }
793   if (map2) {
794      if (data==map2->Points) {
795         /* The control points in the display list are currently */
796         /* being used so we can mark them as discard-able. */
797         map2->Retain = GL_FALSE;
798      }
799      else {
800         /* The control points in the display list are not currently */
801         /* being used. */
802         FREE( data );
803      }
804   }
805
806}
807
808
809
810/**********************************************************************/
811/***                      API entry points                          ***/
812/**********************************************************************/
813
814
815/*
816 * Note that the array of control points must be 'unpacked' at this time.
817 * Input:  retain - if TRUE, this control point data is also in a display
818 *                  list and can't be freed until the list is freed.
819 */
820void gl_Map1f( GLcontext* ctx, GLenum target,
821               GLfloat u1, GLfloat u2, GLint stride,
822               GLint order, const GLfloat *points, GLboolean retain )
823{
824   GLint k;
825
826   if (!points) {
827      gl_error( ctx, GL_OUT_OF_MEMORY, "glMap1f" );
828      return;
829   }
830
831   /* may be a new stride after copying control points */
832   stride = components( target );
833
834   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMap1");
835
836   if (u1==u2) {
837      gl_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
838      return;
839   }
840
841   if (order<1 || order>MAX_EVAL_ORDER) {
842      gl_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
843      return;
844   }
845
846   k = components( target );
847   if (k==0) {
848      gl_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
849   }
850
851   if (stride < k) {
852      gl_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
853      return;
854   }
855
856   switch (target) {
857      case GL_MAP1_VERTEX_3:
858         ctx->EvalMap.Map1Vertex3.Order = order;
859	 ctx->EvalMap.Map1Vertex3.u1 = u1;
860	 ctx->EvalMap.Map1Vertex3.u2 = u2;
861	 ctx->EvalMap.Map1Vertex3.du = 1.0 / (u2 - u1);
862	 if (ctx->EvalMap.Map1Vertex3.Points
863             && !ctx->EvalMap.Map1Vertex3.Retain) {
864	    FREE( ctx->EvalMap.Map1Vertex3.Points );
865	 }
866	 ctx->EvalMap.Map1Vertex3.Points = (GLfloat *) points;
867         ctx->EvalMap.Map1Vertex3.Retain = retain;
868	 break;
869      case GL_MAP1_VERTEX_4:
870         ctx->EvalMap.Map1Vertex4.Order = order;
871	 ctx->EvalMap.Map1Vertex4.u1 = u1;
872	 ctx->EvalMap.Map1Vertex4.u2 = u2;
873	 ctx->EvalMap.Map1Vertex4.du = 1.0 / (u2 - u1);
874	 if (ctx->EvalMap.Map1Vertex4.Points
875             && !ctx->EvalMap.Map1Vertex4.Retain) {
876	    FREE( ctx->EvalMap.Map1Vertex4.Points );
877	 }
878	 ctx->EvalMap.Map1Vertex4.Points = (GLfloat *) points;
879	 ctx->EvalMap.Map1Vertex4.Retain = retain;
880	 break;
881      case GL_MAP1_INDEX:
882         ctx->EvalMap.Map1Index.Order = order;
883	 ctx->EvalMap.Map1Index.u1 = u1;
884	 ctx->EvalMap.Map1Index.u2 = u2;
885	 ctx->EvalMap.Map1Index.du = 1.0 / (u2 - u1);
886	 if (ctx->EvalMap.Map1Index.Points
887             && !ctx->EvalMap.Map1Index.Retain) {
888	    FREE( ctx->EvalMap.Map1Index.Points );
889	 }
890	 ctx->EvalMap.Map1Index.Points = (GLfloat *) points;
891	 ctx->EvalMap.Map1Index.Retain = retain;
892	 break;
893      case GL_MAP1_COLOR_4:
894         ctx->EvalMap.Map1Color4.Order = order;
895	 ctx->EvalMap.Map1Color4.u1 = u1;
896	 ctx->EvalMap.Map1Color4.u2 = u2;
897	 ctx->EvalMap.Map1Color4.du = 1.0 / (u2 - u1);
898	 if (ctx->EvalMap.Map1Color4.Points
899             && !ctx->EvalMap.Map1Color4.Retain) {
900	    FREE( ctx->EvalMap.Map1Color4.Points );
901	 }
902	 ctx->EvalMap.Map1Color4.Points = (GLfloat *) points;
903	 ctx->EvalMap.Map1Color4.Retain = retain;
904	 break;
905      case GL_MAP1_NORMAL:
906         ctx->EvalMap.Map1Normal.Order = order;
907	 ctx->EvalMap.Map1Normal.u1 = u1;
908	 ctx->EvalMap.Map1Normal.u2 = u2;
909	 ctx->EvalMap.Map1Normal.du = 1.0 / (u2 - u1);
910	 if (ctx->EvalMap.Map1Normal.Points
911             && !ctx->EvalMap.Map1Normal.Retain) {
912	    FREE( ctx->EvalMap.Map1Normal.Points );
913	 }
914	 ctx->EvalMap.Map1Normal.Points = (GLfloat *) points;
915	 ctx->EvalMap.Map1Normal.Retain = retain;
916	 break;
917      case GL_MAP1_TEXTURE_COORD_1:
918         ctx->EvalMap.Map1Texture1.Order = order;
919	 ctx->EvalMap.Map1Texture1.u1 = u1;
920	 ctx->EvalMap.Map1Texture1.u2 = u2;
921	 ctx->EvalMap.Map1Texture1.du = 1.0 / (u2 - u1);
922	 if (ctx->EvalMap.Map1Texture1.Points
923             && !ctx->EvalMap.Map1Texture1.Retain) {
924	    FREE( ctx->EvalMap.Map1Texture1.Points );
925	 }
926	 ctx->EvalMap.Map1Texture1.Points = (GLfloat *) points;
927	 ctx->EvalMap.Map1Texture1.Retain = retain;
928	 break;
929      case GL_MAP1_TEXTURE_COORD_2:
930         ctx->EvalMap.Map1Texture2.Order = order;
931	 ctx->EvalMap.Map1Texture2.u1 = u1;
932	 ctx->EvalMap.Map1Texture2.u2 = u2;
933	 ctx->EvalMap.Map1Texture2.du = 1.0 / (u2 - u1);
934	 if (ctx->EvalMap.Map1Texture2.Points
935             && !ctx->EvalMap.Map1Texture2.Retain) {
936	    FREE( ctx->EvalMap.Map1Texture2.Points );
937	 }
938	 ctx->EvalMap.Map1Texture2.Points = (GLfloat *) points;
939	 ctx->EvalMap.Map1Texture2.Retain = retain;
940	 break;
941      case GL_MAP1_TEXTURE_COORD_3:
942         ctx->EvalMap.Map1Texture3.Order = order;
943	 ctx->EvalMap.Map1Texture3.u1 = u1;
944	 ctx->EvalMap.Map1Texture3.u2 = u2;
945	 ctx->EvalMap.Map1Texture3.du = 1.0 / (u2 - u1);
946	 if (ctx->EvalMap.Map1Texture3.Points
947             && !ctx->EvalMap.Map1Texture3.Retain) {
948	    FREE( ctx->EvalMap.Map1Texture3.Points );
949	 }
950	 ctx->EvalMap.Map1Texture3.Points = (GLfloat *) points;
951	 ctx->EvalMap.Map1Texture3.Retain = retain;
952	 break;
953      case GL_MAP1_TEXTURE_COORD_4:
954         ctx->EvalMap.Map1Texture4.Order = order;
955	 ctx->EvalMap.Map1Texture4.u1 = u1;
956	 ctx->EvalMap.Map1Texture4.u2 = u2;
957	 ctx->EvalMap.Map1Texture4.du = 1.0 / (u2 - u1);
958	 if (ctx->EvalMap.Map1Texture4.Points
959             && !ctx->EvalMap.Map1Texture4.Retain) {
960	    FREE( ctx->EvalMap.Map1Texture4.Points );
961	 }
962	 ctx->EvalMap.Map1Texture4.Points = (GLfloat *) points;
963	 ctx->EvalMap.Map1Texture4.Retain = retain;
964	 break;
965      default:
966         gl_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
967   }
968}
969
970
971
972
973/*
974 * Note that the array of control points must be 'unpacked' at this time.
975 * Input:  retain - if TRUE, this control point data is also in a display
976 *                  list and can't be freed until the list is freed.
977 */
978void gl_Map2f( GLcontext* ctx, GLenum target,
979	      GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
980	      GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
981	      const GLfloat *points, GLboolean retain )
982{
983   GLint k;
984
985   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMap2");
986
987   if (u1==u2) {
988      gl_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
989      return;
990   }
991
992   if (v1==v2) {
993      gl_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
994      return;
995   }
996
997   if (uorder<1 || uorder>MAX_EVAL_ORDER) {
998      gl_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
999      return;
1000   }
1001
1002   if (vorder<1 || vorder>MAX_EVAL_ORDER) {
1003      gl_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
1004      return;
1005   }
1006
1007   k = components( target );
1008   if (k==0) {
1009      gl_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
1010   }
1011
1012   if (ustride < k) {
1013      gl_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
1014      return;
1015   }
1016   if (vstride < k) {
1017      gl_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
1018      return;
1019   }
1020
1021   switch (target) {
1022      case GL_MAP2_VERTEX_3:
1023         ctx->EvalMap.Map2Vertex3.Uorder = uorder;
1024	 ctx->EvalMap.Map2Vertex3.u1 = u1;
1025	 ctx->EvalMap.Map2Vertex3.u2 = u2;
1026	 ctx->EvalMap.Map2Vertex3.du = 1.0 / (u2 - u1);
1027         ctx->EvalMap.Map2Vertex3.Vorder = vorder;
1028	 ctx->EvalMap.Map2Vertex3.v1 = v1;
1029	 ctx->EvalMap.Map2Vertex3.v2 = v2;
1030	 ctx->EvalMap.Map2Vertex3.dv = 1.0 / (v2 - v1);
1031	 if (ctx->EvalMap.Map2Vertex3.Points
1032             && !ctx->EvalMap.Map2Vertex3.Retain) {
1033	    FREE( ctx->EvalMap.Map2Vertex3.Points );
1034	 }
1035	 ctx->EvalMap.Map2Vertex3.Retain = retain;
1036	 ctx->EvalMap.Map2Vertex3.Points = (GLfloat *) points;
1037	 break;
1038      case GL_MAP2_VERTEX_4:
1039         ctx->EvalMap.Map2Vertex4.Uorder = uorder;
1040	 ctx->EvalMap.Map2Vertex4.u1 = u1;
1041	 ctx->EvalMap.Map2Vertex4.u2 = u2;
1042	 ctx->EvalMap.Map2Vertex4.du = 1.0 / (u2 - u1);
1043         ctx->EvalMap.Map2Vertex4.Vorder = vorder;
1044	 ctx->EvalMap.Map2Vertex4.v1 = v1;
1045	 ctx->EvalMap.Map2Vertex4.v2 = v2;
1046	 ctx->EvalMap.Map2Vertex4.dv = 1.0 / (v2 - v1);
1047	 if (ctx->EvalMap.Map2Vertex4.Points
1048             && !ctx->EvalMap.Map2Vertex4.Retain) {
1049	    FREE( ctx->EvalMap.Map2Vertex4.Points );
1050	 }
1051	 ctx->EvalMap.Map2Vertex4.Points = (GLfloat *) points;
1052	 ctx->EvalMap.Map2Vertex4.Retain = retain;
1053	 break;
1054      case GL_MAP2_INDEX:
1055         ctx->EvalMap.Map2Index.Uorder = uorder;
1056	 ctx->EvalMap.Map2Index.u1 = u1;
1057	 ctx->EvalMap.Map2Index.u2 = u2;
1058	 ctx->EvalMap.Map2Index.du = 1.0 / (u2 - u1);
1059         ctx->EvalMap.Map2Index.Vorder = vorder;
1060	 ctx->EvalMap.Map2Index.v1 = v1;
1061	 ctx->EvalMap.Map2Index.v2 = v2;
1062	 ctx->EvalMap.Map2Index.dv = 1.0 / (v2 - v1);
1063	 if (ctx->EvalMap.Map2Index.Points
1064             && !ctx->EvalMap.Map2Index.Retain) {
1065	    FREE( ctx->EvalMap.Map2Index.Points );
1066	 }
1067	 ctx->EvalMap.Map2Index.Retain = retain;
1068	 ctx->EvalMap.Map2Index.Points = (GLfloat *) points;
1069	 break;
1070      case GL_MAP2_COLOR_4:
1071         ctx->EvalMap.Map2Color4.Uorder = uorder;
1072	 ctx->EvalMap.Map2Color4.u1 = u1;
1073	 ctx->EvalMap.Map2Color4.u2 = u2;
1074	 ctx->EvalMap.Map2Color4.du = 1.0 / (u2 - u1);
1075         ctx->EvalMap.Map2Color4.Vorder = vorder;
1076	 ctx->EvalMap.Map2Color4.v1 = v1;
1077	 ctx->EvalMap.Map2Color4.v2 = v2;
1078	 ctx->EvalMap.Map2Color4.dv = 1.0 / (v2 - v1);
1079	 if (ctx->EvalMap.Map2Color4.Points
1080             && !ctx->EvalMap.Map2Color4.Retain) {
1081	    FREE( ctx->EvalMap.Map2Color4.Points );
1082	 }
1083	 ctx->EvalMap.Map2Color4.Retain = retain;
1084	 ctx->EvalMap.Map2Color4.Points = (GLfloat *) points;
1085	 break;
1086      case GL_MAP2_NORMAL:
1087         ctx->EvalMap.Map2Normal.Uorder = uorder;
1088	 ctx->EvalMap.Map2Normal.u1 = u1;
1089	 ctx->EvalMap.Map2Normal.u2 = u2;
1090	 ctx->EvalMap.Map2Normal.du = 1.0 / (u2 - u1);
1091         ctx->EvalMap.Map2Normal.Vorder = vorder;
1092	 ctx->EvalMap.Map2Normal.v1 = v1;
1093	 ctx->EvalMap.Map2Normal.v2 = v2;
1094	 ctx->EvalMap.Map2Normal.dv = 1.0 / (v2 - v1);
1095	 if (ctx->EvalMap.Map2Normal.Points
1096             && !ctx->EvalMap.Map2Normal.Retain) {
1097	    FREE( ctx->EvalMap.Map2Normal.Points );
1098	 }
1099	 ctx->EvalMap.Map2Normal.Retain = retain;
1100	 ctx->EvalMap.Map2Normal.Points = (GLfloat *) points;
1101	 break;
1102      case GL_MAP2_TEXTURE_COORD_1:
1103         ctx->EvalMap.Map2Texture1.Uorder = uorder;
1104	 ctx->EvalMap.Map2Texture1.u1 = u1;
1105	 ctx->EvalMap.Map2Texture1.u2 = u2;
1106	 ctx->EvalMap.Map2Texture1.du = 1.0 / (u2 - u1);
1107         ctx->EvalMap.Map2Texture1.Vorder = vorder;
1108	 ctx->EvalMap.Map2Texture1.v1 = v1;
1109	 ctx->EvalMap.Map2Texture1.v2 = v2;
1110	 ctx->EvalMap.Map2Texture1.dv = 1.0 / (v2 - v1);
1111	 if (ctx->EvalMap.Map2Texture1.Points
1112             && !ctx->EvalMap.Map2Texture1.Retain) {
1113	    FREE( ctx->EvalMap.Map2Texture1.Points );
1114	 }
1115	 ctx->EvalMap.Map2Texture1.Retain = retain;
1116	 ctx->EvalMap.Map2Texture1.Points = (GLfloat *) points;
1117	 break;
1118      case GL_MAP2_TEXTURE_COORD_2:
1119         ctx->EvalMap.Map2Texture2.Uorder = uorder;
1120	 ctx->EvalMap.Map2Texture2.u1 = u1;
1121	 ctx->EvalMap.Map2Texture2.u2 = u2;
1122	 ctx->EvalMap.Map2Texture2.du = 1.0 / (u2 - u1);
1123         ctx->EvalMap.Map2Texture2.Vorder = vorder;
1124	 ctx->EvalMap.Map2Texture2.v1 = v1;
1125	 ctx->EvalMap.Map2Texture2.v2 = v2;
1126	 ctx->EvalMap.Map2Texture2.dv = 1.0 / (v2 - v1);
1127	 if (ctx->EvalMap.Map2Texture2.Points
1128             && !ctx->EvalMap.Map2Texture2.Retain) {
1129	    FREE( ctx->EvalMap.Map2Texture2.Points );
1130	 }
1131	 ctx->EvalMap.Map2Texture2.Retain = retain;
1132	 ctx->EvalMap.Map2Texture2.Points = (GLfloat *) points;
1133	 break;
1134      case GL_MAP2_TEXTURE_COORD_3:
1135         ctx->EvalMap.Map2Texture3.Uorder = uorder;
1136	 ctx->EvalMap.Map2Texture3.u1 = u1;
1137	 ctx->EvalMap.Map2Texture3.u2 = u2;
1138	 ctx->EvalMap.Map2Texture3.du = 1.0 / (u2 - u1);
1139         ctx->EvalMap.Map2Texture3.Vorder = vorder;
1140	 ctx->EvalMap.Map2Texture3.v1 = v1;
1141	 ctx->EvalMap.Map2Texture3.v2 = v2;
1142	 ctx->EvalMap.Map2Texture3.dv = 1.0 / (v2 - v1);
1143	 if (ctx->EvalMap.Map2Texture3.Points
1144             && !ctx->EvalMap.Map2Texture3.Retain) {
1145	    FREE( ctx->EvalMap.Map2Texture3.Points );
1146	 }
1147	 ctx->EvalMap.Map2Texture3.Retain = retain;
1148	 ctx->EvalMap.Map2Texture3.Points = (GLfloat *) points;
1149	 break;
1150      case GL_MAP2_TEXTURE_COORD_4:
1151         ctx->EvalMap.Map2Texture4.Uorder = uorder;
1152	 ctx->EvalMap.Map2Texture4.u1 = u1;
1153	 ctx->EvalMap.Map2Texture4.u2 = u2;
1154	 ctx->EvalMap.Map2Texture4.du = 1.0 / (u2 - u1);
1155         ctx->EvalMap.Map2Texture4.Vorder = vorder;
1156	 ctx->EvalMap.Map2Texture4.v1 = v1;
1157	 ctx->EvalMap.Map2Texture4.v2 = v2;
1158	 ctx->EvalMap.Map2Texture4.dv = 1.0 / (v2 - v1);
1159	 if (ctx->EvalMap.Map2Texture4.Points
1160             && !ctx->EvalMap.Map2Texture4.Retain) {
1161	    FREE( ctx->EvalMap.Map2Texture4.Points );
1162	 }
1163	 ctx->EvalMap.Map2Texture4.Retain = retain;
1164	 ctx->EvalMap.Map2Texture4.Points = (GLfloat *) points;
1165	 break;
1166      default:
1167         gl_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
1168   }
1169}
1170
1171
1172
1173
1174
1175void gl_GetMapdv( GLcontext* ctx, GLenum target, GLenum query, GLdouble *v )
1176{
1177   GLint i, n;
1178   GLfloat *data;
1179
1180   switch (query) {
1181      case GL_COEFF:
1182	 switch (target) {
1183	    case GL_MAP1_COLOR_4:
1184	       data = ctx->EvalMap.Map1Color4.Points;
1185	       n = ctx->EvalMap.Map1Color4.Order * 4;
1186	       break;
1187	    case GL_MAP1_INDEX:
1188	       data = ctx->EvalMap.Map1Index.Points;
1189	       n = ctx->EvalMap.Map1Index.Order;
1190	       break;
1191	    case GL_MAP1_NORMAL:
1192	       data = ctx->EvalMap.Map1Normal.Points;
1193	       n = ctx->EvalMap.Map1Normal.Order * 3;
1194	       break;
1195	    case GL_MAP1_TEXTURE_COORD_1:
1196	       data = ctx->EvalMap.Map1Texture1.Points;
1197	       n = ctx->EvalMap.Map1Texture1.Order * 1;
1198	       break;
1199	    case GL_MAP1_TEXTURE_COORD_2:
1200	       data = ctx->EvalMap.Map1Texture2.Points;
1201	       n = ctx->EvalMap.Map1Texture2.Order * 2;
1202	       break;
1203	    case GL_MAP1_TEXTURE_COORD_3:
1204	       data = ctx->EvalMap.Map1Texture3.Points;
1205	       n = ctx->EvalMap.Map1Texture3.Order * 3;
1206	       break;
1207	    case GL_MAP1_TEXTURE_COORD_4:
1208	       data = ctx->EvalMap.Map1Texture4.Points;
1209	       n = ctx->EvalMap.Map1Texture4.Order * 4;
1210	       break;
1211	    case GL_MAP1_VERTEX_3:
1212	       data = ctx->EvalMap.Map1Vertex3.Points;
1213	       n = ctx->EvalMap.Map1Vertex3.Order * 3;
1214	       break;
1215	    case GL_MAP1_VERTEX_4:
1216	       data = ctx->EvalMap.Map1Vertex4.Points;
1217	       n = ctx->EvalMap.Map1Vertex4.Order * 4;
1218	       break;
1219	    case GL_MAP2_COLOR_4:
1220	       data = ctx->EvalMap.Map2Color4.Points;
1221	       n = ctx->EvalMap.Map2Color4.Uorder
1222                 * ctx->EvalMap.Map2Color4.Vorder * 4;
1223	       break;
1224	    case GL_MAP2_INDEX:
1225	       data = ctx->EvalMap.Map2Index.Points;
1226	       n = ctx->EvalMap.Map2Index.Uorder
1227                 * ctx->EvalMap.Map2Index.Vorder;
1228	       break;
1229	    case GL_MAP2_NORMAL:
1230	       data = ctx->EvalMap.Map2Normal.Points;
1231	       n = ctx->EvalMap.Map2Normal.Uorder
1232                 * ctx->EvalMap.Map2Normal.Vorder * 3;
1233	       break;
1234	    case GL_MAP2_TEXTURE_COORD_1:
1235	       data = ctx->EvalMap.Map2Texture1.Points;
1236	       n = ctx->EvalMap.Map2Texture1.Uorder
1237                 * ctx->EvalMap.Map2Texture1.Vorder * 1;
1238	       break;
1239	    case GL_MAP2_TEXTURE_COORD_2:
1240	       data = ctx->EvalMap.Map2Texture2.Points;
1241	       n = ctx->EvalMap.Map2Texture2.Uorder
1242                 * ctx->EvalMap.Map2Texture2.Vorder * 2;
1243	       break;
1244	    case GL_MAP2_TEXTURE_COORD_3:
1245	       data = ctx->EvalMap.Map2Texture3.Points;
1246	       n = ctx->EvalMap.Map2Texture3.Uorder
1247                 * ctx->EvalMap.Map2Texture3.Vorder * 3;
1248	       break;
1249	    case GL_MAP2_TEXTURE_COORD_4:
1250	       data = ctx->EvalMap.Map2Texture4.Points;
1251	       n = ctx->EvalMap.Map2Texture4.Uorder
1252                 * ctx->EvalMap.Map2Texture4.Vorder * 4;
1253	       break;
1254	    case GL_MAP2_VERTEX_3:
1255	       data = ctx->EvalMap.Map2Vertex3.Points;
1256	       n = ctx->EvalMap.Map2Vertex3.Uorder
1257                 * ctx->EvalMap.Map2Vertex3.Vorder * 3;
1258	       break;
1259	    case GL_MAP2_VERTEX_4:
1260	       data = ctx->EvalMap.Map2Vertex4.Points;
1261	       n = ctx->EvalMap.Map2Vertex4.Uorder
1262                 * ctx->EvalMap.Map2Vertex4.Vorder * 4;
1263	       break;
1264	    default:
1265	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
1266	       return;
1267	 }
1268	 if (data) {
1269	    for (i=0;i<n;i++) {
1270	       v[i] = data[i];
1271	    }
1272	 }
1273         break;
1274      case GL_ORDER:
1275	 switch (target) {
1276	    case GL_MAP1_COLOR_4:
1277	       *v = ctx->EvalMap.Map1Color4.Order;
1278	       break;
1279	    case GL_MAP1_INDEX:
1280	       *v = ctx->EvalMap.Map1Index.Order;
1281	       break;
1282	    case GL_MAP1_NORMAL:
1283	       *v = ctx->EvalMap.Map1Normal.Order;
1284	       break;
1285	    case GL_MAP1_TEXTURE_COORD_1:
1286	       *v = ctx->EvalMap.Map1Texture1.Order;
1287	       break;
1288	    case GL_MAP1_TEXTURE_COORD_2:
1289	       *v = ctx->EvalMap.Map1Texture2.Order;
1290	       break;
1291	    case GL_MAP1_TEXTURE_COORD_3:
1292	       *v = ctx->EvalMap.Map1Texture3.Order;
1293	       break;
1294	    case GL_MAP1_TEXTURE_COORD_4:
1295	       *v = ctx->EvalMap.Map1Texture4.Order;
1296	       break;
1297	    case GL_MAP1_VERTEX_3:
1298	       *v = ctx->EvalMap.Map1Vertex3.Order;
1299	       break;
1300	    case GL_MAP1_VERTEX_4:
1301	       *v = ctx->EvalMap.Map1Vertex4.Order;
1302	       break;
1303	    case GL_MAP2_COLOR_4:
1304	       v[0] = ctx->EvalMap.Map2Color4.Uorder;
1305	       v[1] = ctx->EvalMap.Map2Color4.Vorder;
1306	       break;
1307	    case GL_MAP2_INDEX:
1308	       v[0] = ctx->EvalMap.Map2Index.Uorder;
1309	       v[1] = ctx->EvalMap.Map2Index.Vorder;
1310	       break;
1311	    case GL_MAP2_NORMAL:
1312	       v[0] = ctx->EvalMap.Map2Normal.Uorder;
1313	       v[1] = ctx->EvalMap.Map2Normal.Vorder;
1314	       break;
1315	    case GL_MAP2_TEXTURE_COORD_1:
1316	       v[0] = ctx->EvalMap.Map2Texture1.Uorder;
1317	       v[1] = ctx->EvalMap.Map2Texture1.Vorder;
1318	       break;
1319	    case GL_MAP2_TEXTURE_COORD_2:
1320	       v[0] = ctx->EvalMap.Map2Texture2.Uorder;
1321	       v[1] = ctx->EvalMap.Map2Texture2.Vorder;
1322	       break;
1323	    case GL_MAP2_TEXTURE_COORD_3:
1324	       v[0] = ctx->EvalMap.Map2Texture3.Uorder;
1325	       v[1] = ctx->EvalMap.Map2Texture3.Vorder;
1326	       break;
1327	    case GL_MAP2_TEXTURE_COORD_4:
1328	       v[0] = ctx->EvalMap.Map2Texture4.Uorder;
1329	       v[1] = ctx->EvalMap.Map2Texture4.Vorder;
1330	       break;
1331	    case GL_MAP2_VERTEX_3:
1332	       v[0] = ctx->EvalMap.Map2Vertex3.Uorder;
1333	       v[1] = ctx->EvalMap.Map2Vertex3.Vorder;
1334	       break;
1335	    case GL_MAP2_VERTEX_4:
1336	       v[0] = ctx->EvalMap.Map2Vertex4.Uorder;
1337	       v[1] = ctx->EvalMap.Map2Vertex4.Vorder;
1338	       break;
1339	    default:
1340	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
1341	       return;
1342	 }
1343         break;
1344      case GL_DOMAIN:
1345	 switch (target) {
1346	    case GL_MAP1_COLOR_4:
1347	       v[0] = ctx->EvalMap.Map1Color4.u1;
1348	       v[1] = ctx->EvalMap.Map1Color4.u2;
1349	       break;
1350	    case GL_MAP1_INDEX:
1351	       v[0] = ctx->EvalMap.Map1Index.u1;
1352	       v[1] = ctx->EvalMap.Map1Index.u2;
1353	       break;
1354	    case GL_MAP1_NORMAL:
1355	       v[0] = ctx->EvalMap.Map1Normal.u1;
1356	       v[1] = ctx->EvalMap.Map1Normal.u2;
1357	       break;
1358	    case GL_MAP1_TEXTURE_COORD_1:
1359	       v[0] = ctx->EvalMap.Map1Texture1.u1;
1360	       v[1] = ctx->EvalMap.Map1Texture1.u2;
1361	       break;
1362	    case GL_MAP1_TEXTURE_COORD_2:
1363	       v[0] = ctx->EvalMap.Map1Texture2.u1;
1364	       v[1] = ctx->EvalMap.Map1Texture2.u2;
1365	       break;
1366	    case GL_MAP1_TEXTURE_COORD_3:
1367	       v[0] = ctx->EvalMap.Map1Texture3.u1;
1368	       v[1] = ctx->EvalMap.Map1Texture3.u2;
1369	       break;
1370	    case GL_MAP1_TEXTURE_COORD_4:
1371	       v[0] = ctx->EvalMap.Map1Texture4.u1;
1372	       v[1] = ctx->EvalMap.Map1Texture4.u2;
1373	       break;
1374	    case GL_MAP1_VERTEX_3:
1375	       v[0] = ctx->EvalMap.Map1Vertex3.u1;
1376	       v[1] = ctx->EvalMap.Map1Vertex3.u2;
1377	       break;
1378	    case GL_MAP1_VERTEX_4:
1379	       v[0] = ctx->EvalMap.Map1Vertex4.u1;
1380	       v[1] = ctx->EvalMap.Map1Vertex4.u2;
1381	       break;
1382	    case GL_MAP2_COLOR_4:
1383	       v[0] = ctx->EvalMap.Map2Color4.u1;
1384	       v[1] = ctx->EvalMap.Map2Color4.u2;
1385	       v[2] = ctx->EvalMap.Map2Color4.v1;
1386	       v[3] = ctx->EvalMap.Map2Color4.v2;
1387	       break;
1388	    case GL_MAP2_INDEX:
1389	       v[0] = ctx->EvalMap.Map2Index.u1;
1390	       v[1] = ctx->EvalMap.Map2Index.u2;
1391	       v[2] = ctx->EvalMap.Map2Index.v1;
1392	       v[3] = ctx->EvalMap.Map2Index.v2;
1393	       break;
1394	    case GL_MAP2_NORMAL:
1395	       v[0] = ctx->EvalMap.Map2Normal.u1;
1396	       v[1] = ctx->EvalMap.Map2Normal.u2;
1397	       v[2] = ctx->EvalMap.Map2Normal.v1;
1398	       v[3] = ctx->EvalMap.Map2Normal.v2;
1399	       break;
1400	    case GL_MAP2_TEXTURE_COORD_1:
1401	       v[0] = ctx->EvalMap.Map2Texture1.u1;
1402	       v[1] = ctx->EvalMap.Map2Texture1.u2;
1403	       v[2] = ctx->EvalMap.Map2Texture1.v1;
1404	       v[3] = ctx->EvalMap.Map2Texture1.v2;
1405	       break;
1406	    case GL_MAP2_TEXTURE_COORD_2:
1407	       v[0] = ctx->EvalMap.Map2Texture2.u1;
1408	       v[1] = ctx->EvalMap.Map2Texture2.u2;
1409	       v[2] = ctx->EvalMap.Map2Texture2.v1;
1410	       v[3] = ctx->EvalMap.Map2Texture2.v2;
1411	       break;
1412	    case GL_MAP2_TEXTURE_COORD_3:
1413	       v[0] = ctx->EvalMap.Map2Texture3.u1;
1414	       v[1] = ctx->EvalMap.Map2Texture3.u2;
1415	       v[2] = ctx->EvalMap.Map2Texture3.v1;
1416	       v[3] = ctx->EvalMap.Map2Texture3.v2;
1417	       break;
1418	    case GL_MAP2_TEXTURE_COORD_4:
1419	       v[0] = ctx->EvalMap.Map2Texture4.u1;
1420	       v[1] = ctx->EvalMap.Map2Texture4.u2;
1421	       v[2] = ctx->EvalMap.Map2Texture4.v1;
1422	       v[3] = ctx->EvalMap.Map2Texture4.v2;
1423	       break;
1424	    case GL_MAP2_VERTEX_3:
1425	       v[0] = ctx->EvalMap.Map2Vertex3.u1;
1426	       v[1] = ctx->EvalMap.Map2Vertex3.u2;
1427	       v[2] = ctx->EvalMap.Map2Vertex3.v1;
1428	       v[3] = ctx->EvalMap.Map2Vertex3.v2;
1429	       break;
1430	    case GL_MAP2_VERTEX_4:
1431	       v[0] = ctx->EvalMap.Map2Vertex4.u1;
1432	       v[1] = ctx->EvalMap.Map2Vertex4.u2;
1433	       v[2] = ctx->EvalMap.Map2Vertex4.v1;
1434	       v[3] = ctx->EvalMap.Map2Vertex4.v2;
1435	       break;
1436	    default:
1437	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
1438	 }
1439         break;
1440      default:
1441         gl_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
1442   }
1443}
1444
1445
1446void gl_GetMapfv( GLcontext* ctx, GLenum target, GLenum query, GLfloat *v )
1447{
1448   GLint i, n;
1449   GLfloat *data;
1450
1451   switch (query) {
1452      case GL_COEFF:
1453	 switch (target) {
1454	    case GL_MAP1_COLOR_4:
1455	       data = ctx->EvalMap.Map1Color4.Points;
1456	       n = ctx->EvalMap.Map1Color4.Order * 4;
1457	       break;
1458	    case GL_MAP1_INDEX:
1459	       data = ctx->EvalMap.Map1Index.Points;
1460	       n = ctx->EvalMap.Map1Index.Order;
1461	       break;
1462	    case GL_MAP1_NORMAL:
1463	       data = ctx->EvalMap.Map1Normal.Points;
1464	       n = ctx->EvalMap.Map1Normal.Order * 3;
1465	       break;
1466	    case GL_MAP1_TEXTURE_COORD_1:
1467	       data = ctx->EvalMap.Map1Texture1.Points;
1468	       n = ctx->EvalMap.Map1Texture1.Order * 1;
1469	       break;
1470	    case GL_MAP1_TEXTURE_COORD_2:
1471	       data = ctx->EvalMap.Map1Texture2.Points;
1472	       n = ctx->EvalMap.Map1Texture2.Order * 2;
1473	       break;
1474	    case GL_MAP1_TEXTURE_COORD_3:
1475	       data = ctx->EvalMap.Map1Texture3.Points;
1476	       n = ctx->EvalMap.Map1Texture3.Order * 3;
1477	       break;
1478	    case GL_MAP1_TEXTURE_COORD_4:
1479	       data = ctx->EvalMap.Map1Texture4.Points;
1480	       n = ctx->EvalMap.Map1Texture4.Order * 4;
1481	       break;
1482	    case GL_MAP1_VERTEX_3:
1483	       data = ctx->EvalMap.Map1Vertex3.Points;
1484	       n = ctx->EvalMap.Map1Vertex3.Order * 3;
1485	       break;
1486	    case GL_MAP1_VERTEX_4:
1487	       data = ctx->EvalMap.Map1Vertex4.Points;
1488	       n = ctx->EvalMap.Map1Vertex4.Order * 4;
1489	       break;
1490	    case GL_MAP2_COLOR_4:
1491	       data = ctx->EvalMap.Map2Color4.Points;
1492	       n = ctx->EvalMap.Map2Color4.Uorder
1493                 * ctx->EvalMap.Map2Color4.Vorder * 4;
1494	       break;
1495	    case GL_MAP2_INDEX:
1496	       data = ctx->EvalMap.Map2Index.Points;
1497	       n = ctx->EvalMap.Map2Index.Uorder
1498                 * ctx->EvalMap.Map2Index.Vorder;
1499	       break;
1500	    case GL_MAP2_NORMAL:
1501	       data = ctx->EvalMap.Map2Normal.Points;
1502	       n = ctx->EvalMap.Map2Normal.Uorder
1503                 * ctx->EvalMap.Map2Normal.Vorder * 3;
1504	       break;
1505	    case GL_MAP2_TEXTURE_COORD_1:
1506	       data = ctx->EvalMap.Map2Texture1.Points;
1507	       n = ctx->EvalMap.Map2Texture1.Uorder
1508                 * ctx->EvalMap.Map2Texture1.Vorder * 1;
1509	       break;
1510	    case GL_MAP2_TEXTURE_COORD_2:
1511	       data = ctx->EvalMap.Map2Texture2.Points;
1512	       n = ctx->EvalMap.Map2Texture2.Uorder
1513                 * ctx->EvalMap.Map2Texture2.Vorder * 2;
1514	       break;
1515	    case GL_MAP2_TEXTURE_COORD_3:
1516	       data = ctx->EvalMap.Map2Texture3.Points;
1517	       n = ctx->EvalMap.Map2Texture3.Uorder
1518                 * ctx->EvalMap.Map2Texture3.Vorder * 3;
1519	       break;
1520	    case GL_MAP2_TEXTURE_COORD_4:
1521	       data = ctx->EvalMap.Map2Texture4.Points;
1522	       n = ctx->EvalMap.Map2Texture4.Uorder
1523                 * ctx->EvalMap.Map2Texture4.Vorder * 4;
1524	       break;
1525	    case GL_MAP2_VERTEX_3:
1526	       data = ctx->EvalMap.Map2Vertex3.Points;
1527	       n = ctx->EvalMap.Map2Vertex3.Uorder
1528                 * ctx->EvalMap.Map2Vertex3.Vorder * 3;
1529	       break;
1530	    case GL_MAP2_VERTEX_4:
1531	       data = ctx->EvalMap.Map2Vertex4.Points;
1532	       n = ctx->EvalMap.Map2Vertex4.Uorder
1533                 * ctx->EvalMap.Map2Vertex4.Vorder * 4;
1534	       break;
1535	    default:
1536	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
1537	       return;
1538	 }
1539	 if (data) {
1540	    for (i=0;i<n;i++) {
1541	       v[i] = data[i];
1542	    }
1543	 }
1544         break;
1545      case GL_ORDER:
1546	 switch (target) {
1547	    case GL_MAP1_COLOR_4:
1548	       *v = ctx->EvalMap.Map1Color4.Order;
1549	       break;
1550	    case GL_MAP1_INDEX:
1551	       *v = ctx->EvalMap.Map1Index.Order;
1552	       break;
1553	    case GL_MAP1_NORMAL:
1554	       *v = ctx->EvalMap.Map1Normal.Order;
1555	       break;
1556	    case GL_MAP1_TEXTURE_COORD_1:
1557	       *v = ctx->EvalMap.Map1Texture1.Order;
1558	       break;
1559	    case GL_MAP1_TEXTURE_COORD_2:
1560	       *v = ctx->EvalMap.Map1Texture2.Order;
1561	       break;
1562	    case GL_MAP1_TEXTURE_COORD_3:
1563	       *v = ctx->EvalMap.Map1Texture3.Order;
1564	       break;
1565	    case GL_MAP1_TEXTURE_COORD_4:
1566	       *v = ctx->EvalMap.Map1Texture4.Order;
1567	       break;
1568	    case GL_MAP1_VERTEX_3:
1569	       *v = ctx->EvalMap.Map1Vertex3.Order;
1570	       break;
1571	    case GL_MAP1_VERTEX_4:
1572	       *v = ctx->EvalMap.Map1Vertex4.Order;
1573	       break;
1574	    case GL_MAP2_COLOR_4:
1575	       v[0] = ctx->EvalMap.Map2Color4.Uorder;
1576	       v[1] = ctx->EvalMap.Map2Color4.Vorder;
1577	       break;
1578	    case GL_MAP2_INDEX:
1579	       v[0] = ctx->EvalMap.Map2Index.Uorder;
1580	       v[1] = ctx->EvalMap.Map2Index.Vorder;
1581	       break;
1582	    case GL_MAP2_NORMAL:
1583	       v[0] = ctx->EvalMap.Map2Normal.Uorder;
1584	       v[1] = ctx->EvalMap.Map2Normal.Vorder;
1585	       break;
1586	    case GL_MAP2_TEXTURE_COORD_1:
1587	       v[0] = ctx->EvalMap.Map2Texture1.Uorder;
1588	       v[1] = ctx->EvalMap.Map2Texture1.Vorder;
1589	       break;
1590	    case GL_MAP2_TEXTURE_COORD_2:
1591	       v[0] = ctx->EvalMap.Map2Texture2.Uorder;
1592	       v[1] = ctx->EvalMap.Map2Texture2.Vorder;
1593	       break;
1594	    case GL_MAP2_TEXTURE_COORD_3:
1595	       v[0] = ctx->EvalMap.Map2Texture3.Uorder;
1596	       v[1] = ctx->EvalMap.Map2Texture3.Vorder;
1597	       break;
1598	    case GL_MAP2_TEXTURE_COORD_4:
1599	       v[0] = ctx->EvalMap.Map2Texture4.Uorder;
1600	       v[1] = ctx->EvalMap.Map2Texture4.Vorder;
1601	       break;
1602	    case GL_MAP2_VERTEX_3:
1603	       v[0] = ctx->EvalMap.Map2Vertex3.Uorder;
1604	       v[1] = ctx->EvalMap.Map2Vertex3.Vorder;
1605	       break;
1606	    case GL_MAP2_VERTEX_4:
1607	       v[0] = ctx->EvalMap.Map2Vertex4.Uorder;
1608	       v[1] = ctx->EvalMap.Map2Vertex4.Vorder;
1609	       break;
1610	    default:
1611	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
1612	       return;
1613	 }
1614         break;
1615      case GL_DOMAIN:
1616	 switch (target) {
1617	    case GL_MAP1_COLOR_4:
1618	       v[0] = ctx->EvalMap.Map1Color4.u1;
1619	       v[1] = ctx->EvalMap.Map1Color4.u2;
1620	       break;
1621	    case GL_MAP1_INDEX:
1622	       v[0] = ctx->EvalMap.Map1Index.u1;
1623	       v[1] = ctx->EvalMap.Map1Index.u2;
1624	       break;
1625	    case GL_MAP1_NORMAL:
1626	       v[0] = ctx->EvalMap.Map1Normal.u1;
1627	       v[1] = ctx->EvalMap.Map1Normal.u2;
1628	       break;
1629	    case GL_MAP1_TEXTURE_COORD_1:
1630	       v[0] = ctx->EvalMap.Map1Texture1.u1;
1631	       v[1] = ctx->EvalMap.Map1Texture1.u2;
1632	       break;
1633	    case GL_MAP1_TEXTURE_COORD_2:
1634	       v[0] = ctx->EvalMap.Map1Texture2.u1;
1635	       v[1] = ctx->EvalMap.Map1Texture2.u2;
1636	       break;
1637	    case GL_MAP1_TEXTURE_COORD_3:
1638	       v[0] = ctx->EvalMap.Map1Texture3.u1;
1639	       v[1] = ctx->EvalMap.Map1Texture3.u2;
1640	       break;
1641	    case GL_MAP1_TEXTURE_COORD_4:
1642	       v[0] = ctx->EvalMap.Map1Texture4.u1;
1643	       v[1] = ctx->EvalMap.Map1Texture4.u2;
1644	       break;
1645	    case GL_MAP1_VERTEX_3:
1646	       v[0] = ctx->EvalMap.Map1Vertex3.u1;
1647	       v[1] = ctx->EvalMap.Map1Vertex3.u2;
1648	       break;
1649	    case GL_MAP1_VERTEX_4:
1650	       v[0] = ctx->EvalMap.Map1Vertex4.u1;
1651	       v[1] = ctx->EvalMap.Map1Vertex4.u2;
1652	       break;
1653	    case GL_MAP2_COLOR_4:
1654	       v[0] = ctx->EvalMap.Map2Color4.u1;
1655	       v[1] = ctx->EvalMap.Map2Color4.u2;
1656	       v[2] = ctx->EvalMap.Map2Color4.v1;
1657	       v[3] = ctx->EvalMap.Map2Color4.v2;
1658	       break;
1659	    case GL_MAP2_INDEX:
1660	       v[0] = ctx->EvalMap.Map2Index.u1;
1661	       v[1] = ctx->EvalMap.Map2Index.u2;
1662	       v[2] = ctx->EvalMap.Map2Index.v1;
1663	       v[3] = ctx->EvalMap.Map2Index.v2;
1664	       break;
1665	    case GL_MAP2_NORMAL:
1666	       v[0] = ctx->EvalMap.Map2Normal.u1;
1667	       v[1] = ctx->EvalMap.Map2Normal.u2;
1668	       v[2] = ctx->EvalMap.Map2Normal.v1;
1669	       v[3] = ctx->EvalMap.Map2Normal.v2;
1670	       break;
1671	    case GL_MAP2_TEXTURE_COORD_1:
1672	       v[0] = ctx->EvalMap.Map2Texture1.u1;
1673	       v[1] = ctx->EvalMap.Map2Texture1.u2;
1674	       v[2] = ctx->EvalMap.Map2Texture1.v1;
1675	       v[3] = ctx->EvalMap.Map2Texture1.v2;
1676	       break;
1677	    case GL_MAP2_TEXTURE_COORD_2:
1678	       v[0] = ctx->EvalMap.Map2Texture2.u1;
1679	       v[1] = ctx->EvalMap.Map2Texture2.u2;
1680	       v[2] = ctx->EvalMap.Map2Texture2.v1;
1681	       v[3] = ctx->EvalMap.Map2Texture2.v2;
1682	       break;
1683	    case GL_MAP2_TEXTURE_COORD_3:
1684	       v[0] = ctx->EvalMap.Map2Texture3.u1;
1685	       v[1] = ctx->EvalMap.Map2Texture3.u2;
1686	       v[2] = ctx->EvalMap.Map2Texture3.v1;
1687	       v[3] = ctx->EvalMap.Map2Texture3.v2;
1688	       break;
1689	    case GL_MAP2_TEXTURE_COORD_4:
1690	       v[0] = ctx->EvalMap.Map2Texture4.u1;
1691	       v[1] = ctx->EvalMap.Map2Texture4.u2;
1692	       v[2] = ctx->EvalMap.Map2Texture4.v1;
1693	       v[3] = ctx->EvalMap.Map2Texture4.v2;
1694	       break;
1695	    case GL_MAP2_VERTEX_3:
1696	       v[0] = ctx->EvalMap.Map2Vertex3.u1;
1697	       v[1] = ctx->EvalMap.Map2Vertex3.u2;
1698	       v[2] = ctx->EvalMap.Map2Vertex3.v1;
1699	       v[3] = ctx->EvalMap.Map2Vertex3.v2;
1700	       break;
1701	    case GL_MAP2_VERTEX_4:
1702	       v[0] = ctx->EvalMap.Map2Vertex4.u1;
1703	       v[1] = ctx->EvalMap.Map2Vertex4.u2;
1704	       v[2] = ctx->EvalMap.Map2Vertex4.v1;
1705	       v[3] = ctx->EvalMap.Map2Vertex4.v2;
1706	       break;
1707	    default:
1708	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
1709	 }
1710         break;
1711      default:
1712         gl_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
1713   }
1714}
1715
1716
1717void gl_GetMapiv( GLcontext* ctx, GLenum target, GLenum query, GLint *v )
1718{
1719   GLuint i, n;
1720   GLfloat *data;
1721
1722   switch (query) {
1723      case GL_COEFF:
1724	 switch (target) {
1725	    case GL_MAP1_COLOR_4:
1726	       data = ctx->EvalMap.Map1Color4.Points;
1727	       n = ctx->EvalMap.Map1Color4.Order * 4;
1728	       break;
1729	    case GL_MAP1_INDEX:
1730	       data = ctx->EvalMap.Map1Index.Points;
1731	       n = ctx->EvalMap.Map1Index.Order;
1732	       break;
1733	    case GL_MAP1_NORMAL:
1734	       data = ctx->EvalMap.Map1Normal.Points;
1735	       n = ctx->EvalMap.Map1Normal.Order * 3;
1736	       break;
1737	    case GL_MAP1_TEXTURE_COORD_1:
1738	       data = ctx->EvalMap.Map1Texture1.Points;
1739	       n = ctx->EvalMap.Map1Texture1.Order * 1;
1740	       break;
1741	    case GL_MAP1_TEXTURE_COORD_2:
1742	       data = ctx->EvalMap.Map1Texture2.Points;
1743	       n = ctx->EvalMap.Map1Texture2.Order * 2;
1744	       break;
1745	    case GL_MAP1_TEXTURE_COORD_3:
1746	       data = ctx->EvalMap.Map1Texture3.Points;
1747	       n = ctx->EvalMap.Map1Texture3.Order * 3;
1748	       break;
1749	    case GL_MAP1_TEXTURE_COORD_4:
1750	       data = ctx->EvalMap.Map1Texture4.Points;
1751	       n = ctx->EvalMap.Map1Texture4.Order * 4;
1752	       break;
1753	    case GL_MAP1_VERTEX_3:
1754	       data = ctx->EvalMap.Map1Vertex3.Points;
1755	       n = ctx->EvalMap.Map1Vertex3.Order * 3;
1756	       break;
1757	    case GL_MAP1_VERTEX_4:
1758	       data = ctx->EvalMap.Map1Vertex4.Points;
1759	       n = ctx->EvalMap.Map1Vertex4.Order * 4;
1760	       break;
1761	    case GL_MAP2_COLOR_4:
1762	       data = ctx->EvalMap.Map2Color4.Points;
1763	       n = ctx->EvalMap.Map2Color4.Uorder
1764                 * ctx->EvalMap.Map2Color4.Vorder * 4;
1765	       break;
1766	    case GL_MAP2_INDEX:
1767	       data = ctx->EvalMap.Map2Index.Points;
1768	       n = ctx->EvalMap.Map2Index.Uorder
1769                 * ctx->EvalMap.Map2Index.Vorder;
1770	       break;
1771	    case GL_MAP2_NORMAL:
1772	       data = ctx->EvalMap.Map2Normal.Points;
1773	       n = ctx->EvalMap.Map2Normal.Uorder
1774                 * ctx->EvalMap.Map2Normal.Vorder * 3;
1775	       break;
1776	    case GL_MAP2_TEXTURE_COORD_1:
1777	       data = ctx->EvalMap.Map2Texture1.Points;
1778	       n = ctx->EvalMap.Map2Texture1.Uorder
1779                 * ctx->EvalMap.Map2Texture1.Vorder * 1;
1780	       break;
1781	    case GL_MAP2_TEXTURE_COORD_2:
1782	       data = ctx->EvalMap.Map2Texture2.Points;
1783	       n = ctx->EvalMap.Map2Texture2.Uorder
1784                 * ctx->EvalMap.Map2Texture2.Vorder * 2;
1785	       break;
1786	    case GL_MAP2_TEXTURE_COORD_3:
1787	       data = ctx->EvalMap.Map2Texture3.Points;
1788	       n = ctx->EvalMap.Map2Texture3.Uorder
1789                 * ctx->EvalMap.Map2Texture3.Vorder * 3;
1790	       break;
1791	    case GL_MAP2_TEXTURE_COORD_4:
1792	       data = ctx->EvalMap.Map2Texture4.Points;
1793	       n = ctx->EvalMap.Map2Texture4.Uorder
1794                 * ctx->EvalMap.Map2Texture4.Vorder * 4;
1795	       break;
1796	    case GL_MAP2_VERTEX_3:
1797	       data = ctx->EvalMap.Map2Vertex3.Points;
1798	       n = ctx->EvalMap.Map2Vertex3.Uorder
1799                 * ctx->EvalMap.Map2Vertex3.Vorder * 3;
1800	       break;
1801	    case GL_MAP2_VERTEX_4:
1802	       data = ctx->EvalMap.Map2Vertex4.Points;
1803	       n = ctx->EvalMap.Map2Vertex4.Uorder
1804                 * ctx->EvalMap.Map2Vertex4.Vorder * 4;
1805	       break;
1806	    default:
1807	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
1808	       return;
1809	 }
1810	 if (data) {
1811	    for (i=0;i<n;i++) {
1812	       v[i] = ROUNDF(data[i]);
1813	    }
1814	 }
1815         break;
1816      case GL_ORDER:
1817	 switch (target) {
1818	    case GL_MAP1_COLOR_4:
1819	       *v = ctx->EvalMap.Map1Color4.Order;
1820	       break;
1821	    case GL_MAP1_INDEX:
1822	       *v = ctx->EvalMap.Map1Index.Order;
1823	       break;
1824	    case GL_MAP1_NORMAL:
1825	       *v = ctx->EvalMap.Map1Normal.Order;
1826	       break;
1827	    case GL_MAP1_TEXTURE_COORD_1:
1828	       *v = ctx->EvalMap.Map1Texture1.Order;
1829	       break;
1830	    case GL_MAP1_TEXTURE_COORD_2:
1831	       *v = ctx->EvalMap.Map1Texture2.Order;
1832	       break;
1833	    case GL_MAP1_TEXTURE_COORD_3:
1834	       *v = ctx->EvalMap.Map1Texture3.Order;
1835	       break;
1836	    case GL_MAP1_TEXTURE_COORD_4:
1837	       *v = ctx->EvalMap.Map1Texture4.Order;
1838	       break;
1839	    case GL_MAP1_VERTEX_3:
1840	       *v = ctx->EvalMap.Map1Vertex3.Order;
1841	       break;
1842	    case GL_MAP1_VERTEX_4:
1843	       *v = ctx->EvalMap.Map1Vertex4.Order;
1844	       break;
1845	    case GL_MAP2_COLOR_4:
1846	       v[0] = ctx->EvalMap.Map2Color4.Uorder;
1847	       v[1] = ctx->EvalMap.Map2Color4.Vorder;
1848	       break;
1849	    case GL_MAP2_INDEX:
1850	       v[0] = ctx->EvalMap.Map2Index.Uorder;
1851	       v[1] = ctx->EvalMap.Map2Index.Vorder;
1852	       break;
1853	    case GL_MAP2_NORMAL:
1854	       v[0] = ctx->EvalMap.Map2Normal.Uorder;
1855	       v[1] = ctx->EvalMap.Map2Normal.Vorder;
1856	       break;
1857	    case GL_MAP2_TEXTURE_COORD_1:
1858	       v[0] = ctx->EvalMap.Map2Texture1.Uorder;
1859	       v[1] = ctx->EvalMap.Map2Texture1.Vorder;
1860	       break;
1861	    case GL_MAP2_TEXTURE_COORD_2:
1862	       v[0] = ctx->EvalMap.Map2Texture2.Uorder;
1863	       v[1] = ctx->EvalMap.Map2Texture2.Vorder;
1864	       break;
1865	    case GL_MAP2_TEXTURE_COORD_3:
1866	       v[0] = ctx->EvalMap.Map2Texture3.Uorder;
1867	       v[1] = ctx->EvalMap.Map2Texture3.Vorder;
1868	       break;
1869	    case GL_MAP2_TEXTURE_COORD_4:
1870	       v[0] = ctx->EvalMap.Map2Texture4.Uorder;
1871	       v[1] = ctx->EvalMap.Map2Texture4.Vorder;
1872	       break;
1873	    case GL_MAP2_VERTEX_3:
1874	       v[0] = ctx->EvalMap.Map2Vertex3.Uorder;
1875	       v[1] = ctx->EvalMap.Map2Vertex3.Vorder;
1876	       break;
1877	    case GL_MAP2_VERTEX_4:
1878	       v[0] = ctx->EvalMap.Map2Vertex4.Uorder;
1879	       v[1] = ctx->EvalMap.Map2Vertex4.Vorder;
1880	       break;
1881	    default:
1882	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
1883	       return;
1884	 }
1885         break;
1886      case GL_DOMAIN:
1887	 switch (target) {
1888	    case GL_MAP1_COLOR_4:
1889	       v[0] = ROUNDF(ctx->EvalMap.Map1Color4.u1);
1890	       v[1] = ROUNDF(ctx->EvalMap.Map1Color4.u2);
1891	       break;
1892	    case GL_MAP1_INDEX:
1893	       v[0] = ROUNDF(ctx->EvalMap.Map1Index.u1);
1894	       v[1] = ROUNDF(ctx->EvalMap.Map1Index.u2);
1895	       break;
1896	    case GL_MAP1_NORMAL:
1897	       v[0] = ROUNDF(ctx->EvalMap.Map1Normal.u1);
1898	       v[1] = ROUNDF(ctx->EvalMap.Map1Normal.u2);
1899	       break;
1900	    case GL_MAP1_TEXTURE_COORD_1:
1901	       v[0] = ROUNDF(ctx->EvalMap.Map1Texture1.u1);
1902	       v[1] = ROUNDF(ctx->EvalMap.Map1Texture1.u2);
1903	       break;
1904	    case GL_MAP1_TEXTURE_COORD_2:
1905	       v[0] = ROUNDF(ctx->EvalMap.Map1Texture2.u1);
1906	       v[1] = ROUNDF(ctx->EvalMap.Map1Texture2.u2);
1907	       break;
1908	    case GL_MAP1_TEXTURE_COORD_3:
1909	       v[0] = ROUNDF(ctx->EvalMap.Map1Texture3.u1);
1910	       v[1] = ROUNDF(ctx->EvalMap.Map1Texture3.u2);
1911	       break;
1912	    case GL_MAP1_TEXTURE_COORD_4:
1913	       v[0] = ROUNDF(ctx->EvalMap.Map1Texture4.u1);
1914	       v[1] = ROUNDF(ctx->EvalMap.Map1Texture4.u2);
1915	       break;
1916	    case GL_MAP1_VERTEX_3:
1917	       v[0] = ROUNDF(ctx->EvalMap.Map1Vertex3.u1);
1918	       v[1] = ROUNDF(ctx->EvalMap.Map1Vertex3.u2);
1919	       break;
1920	    case GL_MAP1_VERTEX_4:
1921	       v[0] = ROUNDF(ctx->EvalMap.Map1Vertex4.u1);
1922	       v[1] = ROUNDF(ctx->EvalMap.Map1Vertex4.u2);
1923	       break;
1924	    case GL_MAP2_COLOR_4:
1925	       v[0] = ROUNDF(ctx->EvalMap.Map2Color4.u1);
1926	       v[1] = ROUNDF(ctx->EvalMap.Map2Color4.u2);
1927	       v[2] = ROUNDF(ctx->EvalMap.Map2Color4.v1);
1928	       v[3] = ROUNDF(ctx->EvalMap.Map2Color4.v2);
1929	       break;
1930	    case GL_MAP2_INDEX:
1931	       v[0] = ROUNDF(ctx->EvalMap.Map2Index.u1);
1932	       v[1] = ROUNDF(ctx->EvalMap.Map2Index.u2);
1933	       v[2] = ROUNDF(ctx->EvalMap.Map2Index.v1);
1934	       v[3] = ROUNDF(ctx->EvalMap.Map2Index.v2);
1935	       break;
1936	    case GL_MAP2_NORMAL:
1937	       v[0] = ROUNDF(ctx->EvalMap.Map2Normal.u1);
1938	       v[1] = ROUNDF(ctx->EvalMap.Map2Normal.u2);
1939	       v[2] = ROUNDF(ctx->EvalMap.Map2Normal.v1);
1940	       v[3] = ROUNDF(ctx->EvalMap.Map2Normal.v2);
1941	       break;
1942	    case GL_MAP2_TEXTURE_COORD_1:
1943	       v[0] = ROUNDF(ctx->EvalMap.Map2Texture1.u1);
1944	       v[1] = ROUNDF(ctx->EvalMap.Map2Texture1.u2);
1945	       v[2] = ROUNDF(ctx->EvalMap.Map2Texture1.v1);
1946	       v[3] = ROUNDF(ctx->EvalMap.Map2Texture1.v2);
1947	       break;
1948	    case GL_MAP2_TEXTURE_COORD_2:
1949	       v[0] = ROUNDF(ctx->EvalMap.Map2Texture2.u1);
1950	       v[1] = ROUNDF(ctx->EvalMap.Map2Texture2.u2);
1951	       v[2] = ROUNDF(ctx->EvalMap.Map2Texture2.v1);
1952	       v[3] = ROUNDF(ctx->EvalMap.Map2Texture2.v2);
1953	       break;
1954	    case GL_MAP2_TEXTURE_COORD_3:
1955	       v[0] = ROUNDF(ctx->EvalMap.Map2Texture3.u1);
1956	       v[1] = ROUNDF(ctx->EvalMap.Map2Texture3.u2);
1957	       v[2] = ROUNDF(ctx->EvalMap.Map2Texture3.v1);
1958	       v[3] = ROUNDF(ctx->EvalMap.Map2Texture3.v2);
1959	       break;
1960	    case GL_MAP2_TEXTURE_COORD_4:
1961	       v[0] = ROUNDF(ctx->EvalMap.Map2Texture4.u1);
1962	       v[1] = ROUNDF(ctx->EvalMap.Map2Texture4.u2);
1963	       v[2] = ROUNDF(ctx->EvalMap.Map2Texture4.v1);
1964	       v[3] = ROUNDF(ctx->EvalMap.Map2Texture4.v2);
1965	       break;
1966	    case GL_MAP2_VERTEX_3:
1967	       v[0] = ROUNDF(ctx->EvalMap.Map2Vertex3.u1);
1968	       v[1] = ROUNDF(ctx->EvalMap.Map2Vertex3.u2);
1969	       v[2] = ROUNDF(ctx->EvalMap.Map2Vertex3.v1);
1970	       v[3] = ROUNDF(ctx->EvalMap.Map2Vertex3.v2);
1971	       break;
1972	    case GL_MAP2_VERTEX_4:
1973	       v[0] = ROUNDF(ctx->EvalMap.Map2Vertex4.u1);
1974	       v[1] = ROUNDF(ctx->EvalMap.Map2Vertex4.u2);
1975	       v[2] = ROUNDF(ctx->EvalMap.Map2Vertex4.v1);
1976	       v[3] = ROUNDF(ctx->EvalMap.Map2Vertex4.v2);
1977	       break;
1978	    default:
1979	       gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
1980	 }
1981         break;
1982      default:
1983         gl_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
1984   }
1985}
1986
1987
1988
1989static void eval_points1( GLfloat outcoord[][4],
1990			  GLfloat coord[][4],
1991			  const GLuint *flags,
1992			  GLuint start,
1993			  GLfloat du, GLfloat u1 )
1994{
1995   GLuint i;
1996   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
1997      if (flags[i] & VERT_EVAL_P1)
1998	 outcoord[i][0] = coord[i][0] * du + u1;
1999      else if (flags[i] & VERT_EVAL_ANY) {
2000	 outcoord[i][0] = coord[i][0];
2001	 outcoord[i][1] = coord[i][1];
2002      }
2003}
2004
2005static void eval_points2( GLfloat outcoord[][4],
2006			  GLfloat coord[][4],
2007			  const GLuint *flags,
2008			  GLuint start,
2009			  GLfloat du, GLfloat u1,
2010			  GLfloat dv, GLfloat v1 )
2011{
2012   GLuint i;
2013   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2014      if (flags[i] & VERT_EVAL_P2) {
2015	 outcoord[i][0] = coord[i][0] * du + u1;
2016	 outcoord[i][1] = coord[i][1] * dv + v1;
2017      } else if (flags[i] & VERT_EVAL_ANY) {
2018	 outcoord[i][0] = coord[i][0];
2019	 outcoord[i][1] = coord[i][1];
2020      }
2021}
2022
2023
2024static const GLubyte dirty_flags[5] = {
2025   0,				/* not possible */
2026   VEC_DIRTY_0,
2027   VEC_DIRTY_1,
2028   VEC_DIRTY_2,
2029   VEC_DIRTY_3
2030};
2031
2032
2033static GLvector4f *eval1_4f( GLvector4f *dest,
2034			     GLfloat coord[][4],
2035			     const GLuint *flags,
2036			     GLuint start,
2037			     GLuint dimension,
2038			     struct gl_1d_map *map )
2039{
2040   const GLfloat u1 = map->u1;
2041   const GLfloat du = map->du;
2042   GLfloat (*to)[4] = dest->data;
2043   GLuint i;
2044
2045   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2046      if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
2047	 GLfloat u = (coord[i][0] - u1) * du;
2048	 ASSIGN_4V(to[i], 0,0,0,1);
2049	 horner_bezier_curve(map->Points, to[i], u, dimension, map->Order);
2050      }
2051
2052   dest->count = i;
2053   dest->start = VEC_ELT(dest, GLfloat, start);
2054   dest->size = MAX2(dest->size, dimension);
2055   dest->flags |= dirty_flags[dimension];
2056   return dest;
2057}
2058
2059
2060static GLvector1ui *eval1_1ui( GLvector1ui *dest,
2061			       GLfloat coord[][4],
2062			       const GLuint *flags,
2063			       GLuint start,
2064			       struct gl_1d_map *map )
2065{
2066   const GLfloat u1 = map->u1;
2067   const GLfloat du = map->du;
2068   GLuint *to = dest->data;
2069   GLuint i;
2070
2071   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2072      if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
2073	 GLfloat u = (coord[i][0] - u1) * du;
2074	 GLfloat tmp;
2075	 horner_bezier_curve(map->Points, &tmp, u, 1, map->Order);
2076	 to[i] = (GLuint) (GLint) tmp;
2077      }
2078
2079   dest->start = VEC_ELT(dest, GLuint, start);
2080   dest->count = i;
2081   return dest;
2082}
2083
2084static GLvector3f *eval1_norm( GLvector3f *dest,
2085			       GLfloat coord[][4],
2086			       GLuint *flags, /* not const */
2087			       GLuint start,
2088			       struct gl_1d_map *map )
2089{
2090   const GLfloat u1 = map->u1;
2091   const GLfloat du = map->du;
2092   GLfloat (*to)[3] = dest->data;
2093   GLuint i;
2094
2095   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2096      if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
2097	 GLfloat u = (coord[i][0] - u1) * du;
2098	 horner_bezier_curve(map->Points, to[i], u, 3, map->Order);
2099	 flags[i+1] |= VERT_NORM; /* reset */
2100      }
2101
2102   dest->start = VEC_ELT(dest, GLfloat, start);
2103   dest->count = i;
2104   return dest;
2105}
2106
2107static GLvector4ub *eval1_color( GLvector4ub *dest,
2108				 GLfloat coord[][4],
2109				 GLuint *flags, /* not const */
2110				 GLuint start,
2111				 struct gl_1d_map *map )
2112{
2113   const GLfloat u1 = map->u1;
2114   const GLfloat du = map->du;
2115   GLubyte (*to)[4] = dest->data;
2116   GLuint i;
2117
2118   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2119      if (flags[i] & (VERT_EVAL_C1|VERT_EVAL_P1)) {
2120	 GLfloat u = (coord[i][0] - u1) * du;
2121	 GLfloat fcolor[4];
2122	 horner_bezier_curve(map->Points, fcolor, u, 4, map->Order);
2123	 FLOAT_RGBA_TO_UBYTE_RGBA(to[i], fcolor);
2124	 flags[i+1] |= VERT_RGBA; /* reset */
2125      }
2126
2127   dest->start = VEC_ELT(dest, GLubyte, start);
2128   dest->count = i;
2129   return dest;
2130}
2131
2132
2133
2134
2135static GLvector4f *eval2_obj_norm( GLvector4f *obj_ptr,
2136				   GLvector3f *norm_ptr,
2137				   GLfloat coord[][4],
2138				   GLuint *flags,
2139				   GLuint start,
2140				   GLuint dimension,
2141				   struct gl_2d_map *map )
2142{
2143   const GLfloat u1 = map->u1;
2144   const GLfloat du = map->du;
2145   const GLfloat v1 = map->v1;
2146   const GLfloat dv = map->dv;
2147   GLfloat (*obj)[4] = obj_ptr->data;
2148   GLfloat (*normal)[3] = norm_ptr->data;
2149   GLuint i;
2150
2151   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2152      if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
2153	 GLfloat u = (coord[i][0] - u1) * du;
2154	 GLfloat v = (coord[i][1] - v1) * dv;
2155	 GLfloat du[4], dv[4];
2156
2157	 ASSIGN_4V(obj[i], 0,0,0,1);
2158	 de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension,
2159			   map->Uorder, map->Vorder);
2160
2161	 CROSS3(normal[i], du, dv);
2162	 NORMALIZE_3FV(normal[i]);
2163	 flags[i+1] |= VERT_NORM;
2164      }
2165
2166   obj_ptr->start = VEC_ELT(obj_ptr, GLfloat, start);
2167   obj_ptr->count = i;
2168   obj_ptr->size = MAX2(obj_ptr->size, dimension);
2169   obj_ptr->flags |= dirty_flags[dimension];
2170   return obj_ptr;
2171}
2172
2173
2174static GLvector4f *eval2_4f( GLvector4f *dest,
2175			     GLfloat coord[][4],
2176			     const GLuint *flags,
2177			     GLuint start,
2178			     GLuint dimension,
2179			     struct gl_2d_map *map )
2180{
2181   const GLfloat u1 = map->u1;
2182   const GLfloat du = map->du;
2183   const GLfloat v1 = map->v1;
2184   const GLfloat dv = map->dv;
2185   GLfloat (*to)[4] = dest->data;
2186   GLuint i;
2187
2188   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2189      if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
2190	 GLfloat u = (coord[i][0] - u1) * du;
2191	 GLfloat v = (coord[i][1] - v1) * dv;
2192	 horner_bezier_surf(map->Points, to[i], u, v, dimension,
2193			    map->Uorder, map->Vorder);
2194      }
2195
2196   dest->start = VEC_ELT(dest, GLfloat, start);
2197   dest->count = i;
2198   dest->size = MAX2(dest->size, dimension);
2199   dest->flags |= dirty_flags[dimension];
2200   return dest;
2201}
2202
2203
2204static GLvector3f *eval2_norm( GLvector3f *dest,
2205			       GLfloat coord[][4],
2206			       GLuint *flags,
2207			       GLuint start,
2208			       struct gl_2d_map *map )
2209{
2210   const GLfloat u1 = map->u1;
2211   const GLfloat du = map->du;
2212   const GLfloat v1 = map->v1;
2213   const GLfloat dv = map->dv;
2214   GLfloat (*to)[3] = dest->data;
2215   GLuint i;
2216
2217   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2218      if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
2219	 GLfloat u = (coord[i][0] - u1) * du;
2220	 GLfloat v = (coord[i][1] - v1) * dv;
2221	 horner_bezier_surf(map->Points, to[i], u, v, 3,
2222			    map->Uorder, map->Vorder);
2223 	 flags[i+1] |= VERT_NORM; /* reset */
2224     }
2225
2226   dest->start = VEC_ELT(dest, GLfloat, start);
2227   dest->count = i;
2228   return dest;
2229}
2230
2231
2232static GLvector1ui *eval2_1ui( GLvector1ui *dest,
2233			       GLfloat coord[][4],
2234			       const GLuint *flags,
2235			       GLuint start,
2236			       struct gl_2d_map *map )
2237{
2238   const GLfloat u1 = map->u1;
2239   const GLfloat du = map->du;
2240   const GLfloat v1 = map->v1;
2241   const GLfloat dv = map->dv;
2242   GLuint *to = dest->data;
2243   GLuint i;
2244
2245   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2246      if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
2247	 GLfloat u = (coord[i][0] - u1) * du;
2248	 GLfloat v = (coord[i][1] - v1) * dv;
2249	 GLfloat tmp;
2250	 horner_bezier_surf(map->Points, &tmp, u, v, 1,
2251			    map->Uorder, map->Vorder);
2252
2253	 to[i] = (GLuint) (GLint) tmp;
2254      }
2255
2256   dest->start = VEC_ELT(dest, GLuint, start);
2257   dest->count = i;
2258   return dest;
2259}
2260
2261
2262
2263static GLvector4ub *eval2_color( GLvector4ub *dest,
2264				 GLfloat coord[][4],
2265				 GLuint *flags,
2266				 GLuint start,
2267				 struct gl_2d_map *map )
2268{
2269   const GLfloat u1 = map->u1;
2270   const GLfloat du = map->du;
2271   const GLfloat v1 = map->v1;
2272   const GLfloat dv = map->dv;
2273   GLubyte (*to)[4] = dest->data;
2274   GLuint i;
2275
2276   for (i = start ; !(flags[i] & VERT_END_VB) ; i++)
2277      if (flags[i] & (VERT_EVAL_C2|VERT_EVAL_P2)) {
2278	 GLfloat u = (coord[i][0] - u1) * du;
2279	 GLfloat v = (coord[i][1] - v1) * dv;
2280	 GLfloat fcolor[4];
2281	 horner_bezier_surf(map->Points, fcolor, u, v, 4,
2282			    map->Uorder, map->Vorder);
2283	 FLOAT_RGBA_TO_UBYTE_RGBA(to[i], fcolor);
2284	 flags[i+1] |= VERT_RGBA; /* reset */
2285      }
2286
2287   dest->start = VEC_ELT(dest, GLubyte, start);
2288   dest->count = i;
2289   return dest;
2290}
2291
2292
2293static GLvector4f *copy_4f( GLvector4f *out, CONST GLvector4f *in,
2294			    const GLuint *flags,
2295			    GLuint start )
2296{
2297   GLfloat (*to)[4] = out->data;
2298   GLfloat (*from)[4] = in->data;
2299   GLuint i;
2300
2301   for ( i = start ; !(flags[i] & VERT_END_VB) ; i++)
2302      if (!(flags[i] & VERT_EVAL_ANY))
2303	 COPY_4FV( to[i], from[i] );
2304
2305   out->start = VEC_ELT(out, GLfloat, start);
2306   return out;
2307}
2308
2309static GLvector3f *copy_3f( GLvector3f *out, CONST GLvector3f *in,
2310			    const GLuint *flags,
2311			    GLuint start )
2312{
2313   GLfloat (*to)[3] = out->data;
2314   GLfloat (*from)[3] = in->data;
2315   GLuint i;
2316
2317   for ( i = start ; !(flags[i] & VERT_END_VB) ; i++)
2318      if (!(flags[i] & VERT_EVAL_ANY))
2319	 COPY_3V( to[i], from[i] );
2320
2321   out->start = VEC_ELT(out, GLfloat, start);
2322   return out;
2323}
2324
2325static GLvector4ub *copy_4ub( GLvector4ub *out,
2326			      CONST GLvector4ub *in,
2327			      const GLuint *flags,
2328			      GLuint start )
2329{
2330   GLubyte (*to)[4] = out->data;
2331   GLubyte (*from)[4] = in->data;
2332   GLuint i;
2333
2334   for ( i = start ; !(flags[i] & VERT_END_VB) ; i++)
2335      if (!(flags[i] & VERT_EVAL_ANY))
2336	 COPY_4UBV( to[i], from[i] );
2337
2338   out->start = VEC_ELT(out, GLubyte, start);
2339   return out;
2340}
2341
2342static GLvector1ui *copy_1ui( GLvector1ui *out,
2343			      CONST GLvector1ui *in,
2344			      const GLuint *flags,
2345			      GLuint start )
2346{
2347   GLuint *to = out->data;
2348   CONST GLuint *from = in->data;
2349   GLuint i;
2350
2351   for ( i = start ; !(flags[i] & VERT_END_VB) ; i++)
2352      if (!(flags[i] & VERT_EVAL_ANY))
2353	 to[i] = from[i];
2354
2355   out->start = VEC_ELT(out, GLuint, start);
2356   return out;
2357}
2358
2359
2360/* KW: Rewrote this to perform eval on a whole buffer at once.
2361 *     Only evaluates active data items, and avoids scribbling
2362 *     the source buffer if we are running from a display list.
2363 *
2364 *     If the user (in this case looser) sends eval coordinates
2365 *     or runs a display list containing eval coords with no
2366 *     vertex maps enabled, we have to either copy all non-eval
2367 *     data to a new buffer, or find a way of working around
2368 *     the eval data.  I choose the second option.
2369 *
2370 * KW: This code not reached by cva - use IM to access storage.
2371 */
2372void gl_eval_vb( struct vertex_buffer *VB )
2373{
2374   struct immediate *IM = VB->IM;
2375   GLcontext *ctx = VB->ctx;
2376   GLuint req = ctx->CVA.elt.inputs;
2377   GLfloat (*coord)[4] = VB->ObjPtr->data;
2378   GLuint *flags = VB->Flag;
2379   GLuint new_flags = 0;
2380
2381
2382   GLuint any_eval1 = VB->OrFlag & (VERT_EVAL_C1|VERT_EVAL_P1);
2383   GLuint any_eval2 = VB->OrFlag & (VERT_EVAL_C2|VERT_EVAL_P2);
2384   GLuint all_eval = IM->AndFlag & VERT_EVAL_ANY;
2385
2386   /* Handle the degenerate cases.
2387    */
2388   if (any_eval1 && !ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3) {
2389      VB->PurgeFlags |= (VERT_EVAL_C1|VERT_EVAL_P1);
2390      VB->EarlyCull = 0;
2391      any_eval1 = GL_FALSE;
2392   }
2393
2394   if (any_eval2 && !ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3) {
2395      VB->PurgeFlags |= (VERT_EVAL_C2|VERT_EVAL_P2);
2396      VB->EarlyCull = 0;
2397      any_eval2 = GL_FALSE;
2398   }
2399
2400   /* KW: This really is a degenerate case - doing this disables
2401    * culling, and causes dummy values for the missing vertices to be
2402    * transformed and clip tested.  It also forces the individual
2403    * cliptesting of each primitive in vb_render.  I wish there was a
2404    * nice alternative, but I can't say I want to put effort into
2405    * optimizing such a bad usage of the library - I'd much rather
2406    * work on useful changes.
2407    */
2408   if (VB->PurgeFlags) {
2409      if (!any_eval1 && !any_eval2 && all_eval) VB->Count = VB->Start;
2410      gl_purge_vertices( VB );
2411      if (!any_eval1 && !any_eval2) return;
2412   } else
2413      VB->IndirectCount = VB->Count;
2414
2415   /* Translate points into coords.
2416    */
2417   if (any_eval1 && (VB->OrFlag & VERT_EVAL_P1))
2418   {
2419      eval_points1( IM->Obj, coord, flags, IM->Start,
2420		    ctx->Eval.MapGrid1du,
2421		    ctx->Eval.MapGrid1u1);
2422
2423      coord = IM->Obj;
2424   }
2425
2426   if (any_eval2 && (VB->OrFlag & VERT_EVAL_P2))
2427   {
2428      eval_points2( IM->Obj, coord, flags, IM->Start,
2429		    ctx->Eval.MapGrid2du,
2430		    ctx->Eval.MapGrid2u1,
2431		    ctx->Eval.MapGrid2dv,
2432		    ctx->Eval.MapGrid2v1 );
2433
2434      coord = IM->Obj;
2435   }
2436
2437   /* Perform the evaluations on active data elements.
2438    */
2439   if (req & VERT_INDEX)
2440   {
2441      GLvector1ui  *in_index = VB->IndexPtr;
2442      GLvector1ui  *out_index = &IM->v.Index;
2443
2444      if (ctx->Eval.Map1Index && any_eval1)
2445	 VB->IndexPtr = eval1_1ui( out_index, coord, flags, IM->Start,
2446				   &ctx->EvalMap.Map1Index );
2447
2448      if (ctx->Eval.Map2Index && any_eval2)
2449	 VB->IndexPtr = eval2_1ui( out_index, coord, flags, IM->Start,
2450				   &ctx->EvalMap.Map2Index );
2451
2452      if (VB->IndexPtr != in_index) {
2453	 new_flags |= VERT_INDEX;
2454	 if (!all_eval)
2455	    VB->IndexPtr = copy_1ui( out_index, in_index, flags, IM->Start );
2456      }
2457   }
2458
2459   if (req & VERT_RGBA)
2460   {
2461      GLvector4ub  *in_color = VB->ColorPtr;
2462      GLvector4ub  *out_color = &IM->v.Color;
2463
2464      if (ctx->Eval.Map1Color4 && any_eval1)
2465	 VB->ColorPtr = eval1_color( out_color, coord, flags, IM->Start,
2466				   &ctx->EvalMap.Map1Color4 );
2467
2468      if (ctx->Eval.Map2Color4 && any_eval2)
2469	 VB->ColorPtr = eval2_color( out_color, coord, flags, IM->Start,
2470				     &ctx->EvalMap.Map2Color4 );
2471
2472      if (VB->ColorPtr != in_color) {
2473	 new_flags |= VERT_RGBA;
2474	 if (!all_eval)
2475	    VB->ColorPtr = copy_4ub( out_color, in_color, flags, IM->Start );
2476      }
2477
2478      VB->Color[0] = VB->Color[1] = VB->ColorPtr;
2479   }
2480
2481
2482   if (req & VERT_NORM)
2483   {
2484      GLvector3f  *in_normal = VB->NormalPtr;
2485      GLvector3f  *out_normal = &IM->v.Normal;
2486
2487      if (ctx->Eval.Map1Normal && any_eval1)
2488	 VB->NormalPtr = eval1_norm( out_normal, coord, flags, IM->Start,
2489				     &ctx->EvalMap.Map1Normal );
2490
2491      if (ctx->Eval.Map2Normal && any_eval2)
2492	 VB->NormalPtr = eval2_norm( out_normal, coord, flags, IM->Start,
2493				     &ctx->EvalMap.Map2Normal );
2494
2495      if (VB->NormalPtr != in_normal) {
2496	 new_flags |= VERT_NORM;
2497	 if (!all_eval)
2498	    VB->NormalPtr = copy_3f( out_normal, in_normal, flags, IM->Start );
2499      }
2500   }
2501
2502
2503   if (req & VERT_TEX_ANY(0))
2504   {
2505      GLvector4f *tc = VB->TexCoordPtr[0];
2506      GLvector4f *in = tc;
2507      GLvector4f *out = &IM->v.TexCoord[0];
2508
2509      if (any_eval1) {
2510	 if (ctx->Eval.Map1TextureCoord4)
2511	    tc = eval1_4f( out, coord, flags, IM->Start,
2512			   4, &ctx->EvalMap.Map1Texture4);
2513	 else if (ctx->Eval.Map1TextureCoord3)
2514	    tc = eval1_4f( out, coord, flags, IM->Start, 3,
2515			   &ctx->EvalMap.Map1Texture3);
2516	 else if (ctx->Eval.Map1TextureCoord2)
2517	    tc = eval1_4f( out, coord, flags, IM->Start, 2,
2518			   &ctx->EvalMap.Map1Texture2);
2519	 else if (ctx->Eval.Map1TextureCoord1)
2520	    tc = eval1_4f( out, coord, flags, IM->Start, 1,
2521			   &ctx->EvalMap.Map1Texture1);
2522      }
2523
2524      if (any_eval2) {
2525	 if (ctx->Eval.Map2TextureCoord4)
2526	    tc = eval2_4f( out, coord, flags, IM->Start,
2527			   4, &ctx->EvalMap.Map2Texture4);
2528	 else if (ctx->Eval.Map2TextureCoord3)
2529	    tc = eval2_4f( out, coord, flags, IM->Start,
2530			   3, &ctx->EvalMap.Map2Texture3);
2531	 else if (ctx->Eval.Map2TextureCoord2)
2532	    tc = eval2_4f( out, coord, flags, IM->Start,
2533			   2, &ctx->EvalMap.Map2Texture2);
2534	 else if (ctx->Eval.Map2TextureCoord1)
2535	    tc = eval2_4f( out, coord, flags, IM->Start,
2536			   1, &ctx->EvalMap.Map2Texture1);
2537      }
2538
2539      if (tc != in) {
2540	 new_flags |= VERT_TEX_ANY(0); /* fix for sizes.. */
2541	 if (!all_eval)
2542	    tc = copy_4f( out, in, flags, IM->Start );
2543      }
2544
2545      VB->TexCoordPtr[0] = tc;
2546   }
2547
2548
2549   {
2550      GLvector4f *in = VB->ObjPtr;
2551      GLvector4f *out = &IM->v.Obj;
2552      GLvector4f *obj = in;
2553
2554      if (any_eval1) {
2555	 if (ctx->Eval.Map1Vertex4)
2556	    obj = eval1_4f( out, coord, flags, IM->Start,
2557			    4, &ctx->EvalMap.Map1Vertex4);
2558	 else
2559	    obj = eval1_4f( out, coord, flags, IM->Start,
2560			    3, &ctx->EvalMap.Map1Vertex3);
2561      }
2562
2563      if (any_eval2) {
2564	 if (ctx->Eval.Map2Vertex4)
2565	 {
2566	    if (ctx->Eval.AutoNormal && (req & VERT_NORM))
2567	       obj = eval2_obj_norm( out, VB->NormalPtr, coord, flags, IM->Start,
2568				     4, &ctx->EvalMap.Map2Vertex4 );
2569	    else
2570	       obj = eval2_4f( out, coord, flags, IM->Start,
2571			       4, &ctx->EvalMap.Map2Vertex4);
2572	 }
2573	 else if (ctx->Eval.Map2Vertex3)
2574	 {
2575	    if (ctx->Eval.AutoNormal && (req & VERT_NORM))
2576	       obj = eval2_obj_norm( out, VB->NormalPtr, coord, flags, IM->Start,
2577				     3, &ctx->EvalMap.Map2Vertex3 );
2578	    else
2579	       obj = eval2_4f( out, coord, flags, IM->Start,
2580			       3, &ctx->EvalMap.Map2Vertex3 );
2581	 }
2582      }
2583
2584      if (obj != in && !all_eval)
2585	 obj = copy_4f( out, in, flags, IM->Start );
2586
2587      VB->ObjPtr = obj;
2588   }
2589
2590   if (new_flags) {
2591      GLuint *oldflags = VB->Flag;
2592      GLuint *flags = VB->Flag = VB->EvaluatedFlags;
2593      GLuint i;
2594      GLuint count = VB->Count;
2595
2596      if (!flags) {
2597	 VB->EvaluatedFlags = (GLuint *) MALLOC(VB->Size * sizeof(GLuint));
2598	 flags = VB->Flag = VB->EvaluatedFlags;
2599      }
2600
2601      if (all_eval) {
2602	 for (i = 0 ; i < count ; i++)
2603	    flags[i] = oldflags[i] | new_flags;
2604      } else {
2605	 GLuint andflag = ~0;
2606	 for (i = 0 ; i < count ; i++) {
2607	    if (oldflags[i] & VERT_EVAL_ANY)
2608	       flags[i] = oldflags[i] | new_flags;
2609	    andflag &= flags[i];
2610	 }
2611      }
2612   }
2613}
2614
2615
2616void gl_MapGrid1f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2 )
2617{
2618   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMapGrid1f");
2619
2620   if (un<1) {
2621      gl_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
2622      return;
2623   }
2624   ctx->Eval.MapGrid1un = un;
2625   ctx->Eval.MapGrid1u1 = u1;
2626   ctx->Eval.MapGrid1u2 = u2;
2627   ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
2628}
2629
2630
2631void gl_MapGrid2f( GLcontext* ctx, GLint un, GLfloat u1, GLfloat u2,
2632		  GLint vn, GLfloat v1, GLfloat v2 )
2633{
2634   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glMapGrid2f");
2635   if (un<1) {
2636      gl_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
2637      return;
2638   }
2639   if (vn<1) {
2640      gl_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
2641      return;
2642   }
2643   ctx->Eval.MapGrid2un = un;
2644   ctx->Eval.MapGrid2u1 = u1;
2645   ctx->Eval.MapGrid2u2 = u2;
2646   ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
2647   ctx->Eval.MapGrid2vn = vn;
2648   ctx->Eval.MapGrid2v1 = v1;
2649   ctx->Eval.MapGrid2v2 = v2;
2650   ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
2651}
2652
2653
2654
2655void gl_EvalMesh1( GLcontext* ctx, GLenum mode, GLint i1, GLint i2 )
2656{
2657   GLint i;
2658   GLfloat u, du;
2659   GLenum prim;
2660
2661   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glEvalMesh1");
2662
2663   switch (mode) {
2664      case GL_POINT:
2665         prim = GL_POINTS;
2666         break;
2667      case GL_LINE:
2668         prim = GL_LINE_STRIP;
2669         break;
2670      default:
2671         gl_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
2672         return;
2673   }
2674
2675   /* No effect if vertex maps disabled.
2676    */
2677   if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3)
2678      return;
2679
2680   du = ctx->Eval.MapGrid1du;
2681   u = ctx->Eval.MapGrid1u1 + i1 * du;
2682
2683   /* KW: Could short-circuit this to avoid the immediate mechanism.
2684    */
2685   RESET_IMMEDIATE(ctx);
2686
2687   gl_Begin( ctx, prim );
2688   for (i=i1;i<=i2;i++,u+=du) {
2689      gl_EvalCoord1f( ctx, u );
2690   }
2691   gl_End(ctx);
2692}
2693
2694
2695
2696void gl_EvalMesh2( GLcontext* ctx,
2697		   GLenum mode,
2698		   GLint i1, GLint i2,
2699		   GLint j1, GLint j2 )
2700{
2701   GLint i, j;
2702   GLfloat u, du, v, dv, v1, u1;
2703
2704   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glEvalMesh2");
2705
2706   /* No effect if vertex maps disabled.
2707    */
2708   if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3)
2709      return;
2710
2711   du = ctx->Eval.MapGrid2du;
2712   dv = ctx->Eval.MapGrid2dv;
2713   v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
2714   u1 = ctx->Eval.MapGrid2u1 + i1 * du;
2715
2716   RESET_IMMEDIATE(ctx);
2717
2718   switch (mode) {
2719   case GL_POINT:
2720      gl_Begin( ctx, GL_POINTS );
2721      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
2722	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
2723	    gl_EvalCoord2f( ctx, u, v );
2724	 }
2725      }
2726      gl_End(ctx);
2727      break;
2728   case GL_LINE:
2729      for (v=v1,j=j1;j<=j2;j++,v+=dv) {
2730	 gl_Begin( ctx, GL_LINE_STRIP );
2731	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
2732	    gl_EvalCoord2f( ctx, u, v );
2733	 }
2734	 gl_End(ctx);
2735      }
2736      for (u=u1,i=i1;i<=i2;i++,u+=du) {
2737	 gl_Begin( ctx, GL_LINE_STRIP );
2738	 for (v=v1,j=j1;j<=j2;j++,v+=dv) {
2739	    gl_EvalCoord2f( ctx, u, v );
2740	 }
2741	 gl_End(ctx);
2742      }
2743      break;
2744   case GL_FILL:
2745      for (v=v1,j=j1;j<j2;j++,v+=dv) {
2746	 /* NOTE: a quad strip can't be used because the four */
2747	 /* can't be guaranteed to be coplanar! */
2748	 gl_Begin( ctx, GL_TRIANGLE_STRIP );
2749	 for (u=u1,i=i1;i<=i2;i++,u+=du) {
2750	    gl_EvalCoord2f( ctx, u, v );
2751	    gl_EvalCoord2f( ctx, u, v+dv );
2752	 }
2753	 gl_End(ctx);
2754      }
2755      break;
2756   default:
2757      gl_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
2758      return;
2759   }
2760}
2761