eval.c revision 9ac51f57efe07ed43a1e4224a7f5daddec401b36
1
2/*
3 * Mesa 3-D graphics library
4 * Version:  5.1
5 *
6 * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27/*
28 * eval.c was written by
29 * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
30 * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
31 *
32 * My original implementation of evaluators was simplistic and didn't
33 * compute surface normal vectors properly.  Bernd and Volker applied
34 * used more sophisticated methods to get better results.
35 *
36 * Thanks guys!
37 */
38
39
40#include "glheader.h"
41#include "imports.h"
42#include "colormac.h"
43#include "context.h"
44#include "eval.h"
45#include "macros.h"
46#include "mtypes.h"
47
48
49/*
50 * Return the number of components per control point for any type of
51 * evaluator.  Return 0 if bad target.
52 * See table 5.1 in the OpenGL 1.2 spec.
53 */
54GLuint _mesa_evaluator_components( GLenum target )
55{
56   switch (target) {
57      case GL_MAP1_VERTEX_3:		return 3;
58      case GL_MAP1_VERTEX_4:		return 4;
59      case GL_MAP1_INDEX:		return 1;
60      case GL_MAP1_COLOR_4:		return 4;
61      case GL_MAP1_NORMAL:		return 3;
62      case GL_MAP1_TEXTURE_COORD_1:	return 1;
63      case GL_MAP1_TEXTURE_COORD_2:	return 2;
64      case GL_MAP1_TEXTURE_COORD_3:	return 3;
65      case GL_MAP1_TEXTURE_COORD_4:	return 4;
66      case GL_MAP2_VERTEX_3:		return 3;
67      case GL_MAP2_VERTEX_4:		return 4;
68      case GL_MAP2_INDEX:		return 1;
69      case GL_MAP2_COLOR_4:		return 4;
70      case GL_MAP2_NORMAL:		return 3;
71      case GL_MAP2_TEXTURE_COORD_1:	return 1;
72      case GL_MAP2_TEXTURE_COORD_2:	return 2;
73      case GL_MAP2_TEXTURE_COORD_3:	return 3;
74      case GL_MAP2_TEXTURE_COORD_4:	return 4;
75      default:				break;
76   }
77
78   /* XXX need to check for the vertex program extension
79   if (!ctx->Extensions.NV_vertex_program)
80      return 0;
81   */
82
83   if (target >= GL_MAP1_VERTEX_ATTRIB0_4_NV &&
84       target <= GL_MAP1_VERTEX_ATTRIB15_4_NV)
85      return 4;
86
87   if (target >= GL_MAP2_VERTEX_ATTRIB0_4_NV &&
88       target <= GL_MAP2_VERTEX_ATTRIB15_4_NV)
89      return 4;
90
91   return 0;
92}
93
94
95/*
96 * Return pointer to the gl_1d_map struct for the named target.
97 */
98static struct gl_1d_map *
99get_1d_map( GLcontext *ctx, GLenum target )
100{
101   switch (target) {
102      case GL_MAP1_VERTEX_3:
103         return &ctx->EvalMap.Map1Vertex3;
104      case GL_MAP1_VERTEX_4:
105         return &ctx->EvalMap.Map1Vertex4;
106      case GL_MAP1_INDEX:
107         return &ctx->EvalMap.Map1Index;
108      case GL_MAP1_COLOR_4:
109         return &ctx->EvalMap.Map1Color4;
110      case GL_MAP1_NORMAL:
111         return &ctx->EvalMap.Map1Normal;
112      case GL_MAP1_TEXTURE_COORD_1:
113         return &ctx->EvalMap.Map1Texture1;
114      case GL_MAP1_TEXTURE_COORD_2:
115         return &ctx->EvalMap.Map1Texture2;
116      case GL_MAP1_TEXTURE_COORD_3:
117         return &ctx->EvalMap.Map1Texture3;
118      case GL_MAP1_TEXTURE_COORD_4:
119         return &ctx->EvalMap.Map1Texture4;
120      case GL_MAP1_VERTEX_ATTRIB0_4_NV:
121      case GL_MAP1_VERTEX_ATTRIB1_4_NV:
122      case GL_MAP1_VERTEX_ATTRIB2_4_NV:
123      case GL_MAP1_VERTEX_ATTRIB3_4_NV:
124      case GL_MAP1_VERTEX_ATTRIB4_4_NV:
125      case GL_MAP1_VERTEX_ATTRIB5_4_NV:
126      case GL_MAP1_VERTEX_ATTRIB6_4_NV:
127      case GL_MAP1_VERTEX_ATTRIB7_4_NV:
128      case GL_MAP1_VERTEX_ATTRIB8_4_NV:
129      case GL_MAP1_VERTEX_ATTRIB9_4_NV:
130      case GL_MAP1_VERTEX_ATTRIB10_4_NV:
131      case GL_MAP1_VERTEX_ATTRIB11_4_NV:
132      case GL_MAP1_VERTEX_ATTRIB12_4_NV:
133      case GL_MAP1_VERTEX_ATTRIB13_4_NV:
134      case GL_MAP1_VERTEX_ATTRIB14_4_NV:
135      case GL_MAP1_VERTEX_ATTRIB15_4_NV:
136         if (!ctx->Extensions.NV_vertex_program)
137            return NULL;
138         return &ctx->EvalMap.Map1Attrib[target - GL_MAP1_VERTEX_ATTRIB0_4_NV];
139      default:
140         return NULL;
141   }
142}
143
144
145/*
146 * Return pointer to the gl_2d_map struct for the named target.
147 */
148static struct gl_2d_map *
149get_2d_map( GLcontext *ctx, GLenum target )
150{
151   switch (target) {
152      case GL_MAP2_VERTEX_3:
153         return &ctx->EvalMap.Map2Vertex3;
154      case GL_MAP2_VERTEX_4:
155         return &ctx->EvalMap.Map2Vertex4;
156      case GL_MAP2_INDEX:
157         return &ctx->EvalMap.Map2Index;
158      case GL_MAP2_COLOR_4:
159         return &ctx->EvalMap.Map2Color4;
160      case GL_MAP2_NORMAL:
161         return &ctx->EvalMap.Map2Normal;
162      case GL_MAP2_TEXTURE_COORD_1:
163         return &ctx->EvalMap.Map2Texture1;
164      case GL_MAP2_TEXTURE_COORD_2:
165         return &ctx->EvalMap.Map2Texture2;
166      case GL_MAP2_TEXTURE_COORD_3:
167         return &ctx->EvalMap.Map2Texture3;
168      case GL_MAP2_TEXTURE_COORD_4:
169         return &ctx->EvalMap.Map2Texture4;
170      case GL_MAP2_VERTEX_ATTRIB0_4_NV:
171      case GL_MAP2_VERTEX_ATTRIB1_4_NV:
172      case GL_MAP2_VERTEX_ATTRIB2_4_NV:
173      case GL_MAP2_VERTEX_ATTRIB3_4_NV:
174      case GL_MAP2_VERTEX_ATTRIB4_4_NV:
175      case GL_MAP2_VERTEX_ATTRIB5_4_NV:
176      case GL_MAP2_VERTEX_ATTRIB6_4_NV:
177      case GL_MAP2_VERTEX_ATTRIB7_4_NV:
178      case GL_MAP2_VERTEX_ATTRIB8_4_NV:
179      case GL_MAP2_VERTEX_ATTRIB9_4_NV:
180      case GL_MAP2_VERTEX_ATTRIB10_4_NV:
181      case GL_MAP2_VERTEX_ATTRIB11_4_NV:
182      case GL_MAP2_VERTEX_ATTRIB12_4_NV:
183      case GL_MAP2_VERTEX_ATTRIB13_4_NV:
184      case GL_MAP2_VERTEX_ATTRIB14_4_NV:
185      case GL_MAP2_VERTEX_ATTRIB15_4_NV:
186         if (!ctx->Extensions.NV_vertex_program)
187            return NULL;
188         return &ctx->EvalMap.Map2Attrib[target - GL_MAP2_VERTEX_ATTRIB0_4_NV];
189      default:
190         return NULL;
191   }
192}
193
194
195/**********************************************************************/
196/***            Copy and deallocate control points                  ***/
197/**********************************************************************/
198
199
200/*
201 * Copy 1-parametric evaluator control points from user-specified
202 * memory space to a buffer of contiguous control points.
203 * Input:  see glMap1f for details
204 * Return:  pointer to buffer of contiguous control points or NULL if out
205 *          of memory.
206 */
207GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
208                                  const GLfloat *points )
209{
210   GLfloat *buffer, *p;
211   GLint i, k, size = _mesa_evaluator_components(target);
212
213   if (!points || !size)
214      return NULL;
215
216   buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat));
217
218   if (buffer)
219      for (i = 0, p = buffer; i < uorder; i++, points += ustride)
220	for (k = 0; k < size; k++)
221	  *p++ = points[k];
222
223   return buffer;
224}
225
226
227
228/*
229 * Same as above but convert doubles to floats.
230 */
231GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
232                                  const GLdouble *points )
233{
234   GLfloat *buffer, *p;
235   GLint i, k, size = _mesa_evaluator_components(target);
236
237   if (!points || !size)
238      return NULL;
239
240   buffer = (GLfloat *) MALLOC(uorder * size * sizeof(GLfloat));
241
242   if (buffer)
243      for (i = 0, p = buffer; i < uorder; i++, points += ustride)
244	for (k = 0; k < size; k++)
245	  *p++ = (GLfloat) points[k];
246
247   return buffer;
248}
249
250
251
252/*
253 * Copy 2-parametric evaluator control points from user-specified
254 * memory space to a buffer of contiguous control points.
255 * Additional memory is allocated to be used by the horner and
256 * de Casteljau evaluation schemes.
257 *
258 * Input:  see glMap2f for details
259 * Return:  pointer to buffer of contiguous control points or NULL if out
260 *          of memory.
261 */
262GLfloat *_mesa_copy_map_points2f( GLenum target,
263                                  GLint ustride, GLint uorder,
264                                  GLint vstride, GLint vorder,
265                                  const GLfloat *points )
266{
267   GLfloat *buffer, *p;
268   GLint i, j, k, size, dsize, hsize;
269   GLint uinc;
270
271   size = _mesa_evaluator_components(target);
272
273   if (!points || size==0) {
274      return NULL;
275   }
276
277   /* max(uorder, vorder) additional points are used in      */
278   /* horner evaluation and uorder*vorder additional */
279   /* values are needed for de Casteljau                     */
280   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
281   hsize = (uorder > vorder ? uorder : vorder)*size;
282
283   if(hsize>dsize)
284     buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat));
285   else
286     buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat));
287
288   /* compute the increment value for the u-loop */
289   uinc = ustride - vorder*vstride;
290
291   if (buffer)
292      for (i=0, p=buffer; i<uorder; i++, points += uinc)
293	 for (j=0; j<vorder; j++, points += vstride)
294	    for (k=0; k<size; k++)
295	       *p++ = points[k];
296
297   return buffer;
298}
299
300
301
302/*
303 * Same as above but convert doubles to floats.
304 */
305GLfloat *_mesa_copy_map_points2d(GLenum target,
306                                 GLint ustride, GLint uorder,
307                                 GLint vstride, GLint vorder,
308                                 const GLdouble *points )
309{
310   GLfloat *buffer, *p;
311   GLint i, j, k, size, hsize, dsize;
312   GLint uinc;
313
314   size = _mesa_evaluator_components(target);
315
316   if (!points || size==0) {
317      return NULL;
318   }
319
320   /* max(uorder, vorder) additional points are used in      */
321   /* horner evaluation and uorder*vorder additional */
322   /* values are needed for de Casteljau                     */
323   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
324   hsize = (uorder > vorder ? uorder : vorder)*size;
325
326   if(hsize>dsize)
327     buffer = (GLfloat *) MALLOC((uorder*vorder*size+hsize)*sizeof(GLfloat));
328   else
329     buffer = (GLfloat *) MALLOC((uorder*vorder*size+dsize)*sizeof(GLfloat));
330
331   /* compute the increment value for the u-loop */
332   uinc = ustride - vorder*vstride;
333
334   if (buffer)
335      for (i=0, p=buffer; i<uorder; i++, points += uinc)
336	 for (j=0; j<vorder; j++, points += vstride)
337	    for (k=0; k<size; k++)
338	       *p++ = (GLfloat) points[k];
339
340   return buffer;
341}
342
343
344
345
346/**********************************************************************/
347/***                      API entry points                          ***/
348/**********************************************************************/
349
350
351/*
352 * This does the work of glMap1[fd].
353 */
354static void
355map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
356     GLint uorder, const GLvoid *points, GLenum type )
357{
358   GET_CURRENT_CONTEXT(ctx);
359   GLint k;
360   GLfloat *pnts;
361   struct gl_1d_map *map = NULL;
362
363   ASSERT_OUTSIDE_BEGIN_END(ctx);
364   ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
365
366   if (u1 == u2) {
367      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
368      return;
369   }
370   if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
371      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
372      return;
373   }
374   if (!points) {
375      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
376      return;
377   }
378
379   k = _mesa_evaluator_components( target );
380   if (k == 0) {
381      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
382   }
383
384   if (ustride < k) {
385      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
386      return;
387   }
388
389   if (ctx->Texture.CurrentUnit != 0) {
390      /* See OpenGL 1.2.1 spec, section F.2.13 */
391      _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
392      return;
393   }
394
395   map = get_1d_map(ctx, target);
396   if (!map) {
397      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
398      return;
399   }
400
401   /* make copy of the control points */
402   if (type == GL_FLOAT)
403      pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
404   else
405      pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
406
407
408   FLUSH_VERTICES(ctx, _NEW_EVAL);
409   map->Order = uorder;
410   map->u1 = u1;
411   map->u2 = u2;
412   map->du = 1.0F / (u2 - u1);
413   if (map->Points)
414      FREE( map->Points );
415   map->Points = pnts;
416}
417
418
419
420void
421_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
422             GLint order, const GLfloat *points )
423{
424   map1(target, u1, u2, stride, order, points, GL_FLOAT);
425}
426
427
428void
429_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
430             GLint order, const GLdouble *points )
431{
432   map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
433}
434
435
436static void
437map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
438      GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
439      const GLvoid *points, GLenum type )
440{
441   GET_CURRENT_CONTEXT(ctx);
442   GLint k;
443   GLfloat *pnts;
444   struct gl_2d_map *map = NULL;
445
446   ASSERT_OUTSIDE_BEGIN_END(ctx);
447   ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
448
449   if (u1==u2) {
450      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
451      return;
452   }
453
454   if (v1==v2) {
455      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
456      return;
457   }
458
459   if (uorder<1 || uorder>MAX_EVAL_ORDER) {
460      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
461      return;
462   }
463
464   if (vorder<1 || vorder>MAX_EVAL_ORDER) {
465      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
466      return;
467   }
468
469   k = _mesa_evaluator_components( target );
470   if (k==0) {
471      _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
472   }
473
474   if (ustride < k) {
475      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
476      return;
477   }
478   if (vstride < k) {
479      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
480      return;
481   }
482
483   if (ctx->Texture.CurrentUnit != 0) {
484      /* See OpenGL 1.2.1 spec, section F.2.13 */
485      _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
486      return;
487   }
488
489   map = get_2d_map(ctx, target);
490   if (!map) {
491      _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
492      return;
493   }
494
495   /* make copy of the control points */
496   if (type == GL_FLOAT)
497      pnts = _mesa_copy_map_points2f(target, ustride, uorder,
498                                  vstride, vorder, (GLfloat*) points);
499   else
500      pnts = _mesa_copy_map_points2d(target, ustride, uorder,
501                                  vstride, vorder, (GLdouble*) points);
502
503
504   FLUSH_VERTICES(ctx, _NEW_EVAL);
505   map->Uorder = uorder;
506   map->u1 = u1;
507   map->u2 = u2;
508   map->du = 1.0F / (u2 - u1);
509   map->Vorder = vorder;
510   map->v1 = v1;
511   map->v2 = v2;
512   map->dv = 1.0F / (v2 - v1);
513   if (map->Points)
514      FREE( map->Points );
515   map->Points = pnts;
516}
517
518
519void
520_mesa_Map2f( GLenum target,
521             GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
522             GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
523             const GLfloat *points)
524{
525   map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
526        points, GL_FLOAT);
527}
528
529
530void
531_mesa_Map2d( GLenum target,
532             GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
533             GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
534             const GLdouble *points )
535{
536   map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
537	(GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
538}
539
540
541
542void
543_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
544{
545   GET_CURRENT_CONTEXT(ctx);
546   struct gl_1d_map *map1d;
547   struct gl_2d_map *map2d;
548   GLint i, n;
549   GLfloat *data;
550   GLuint comps;
551
552   ASSERT_OUTSIDE_BEGIN_END(ctx);
553
554   comps = _mesa_evaluator_components(target);
555   if (!comps) {
556      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
557      return;
558   }
559
560   map1d = get_1d_map(ctx, target);
561   map2d = get_2d_map(ctx, target);
562   ASSERT(map1d || map2d);
563
564   switch (query) {
565      case GL_COEFF:
566         if (map1d) {
567            data = map1d->Points;
568            n = map1d->Order * comps;
569         }
570         else {
571            data = map2d->Points;
572            n = map2d->Uorder * map2d->Vorder * comps;
573         }
574	 if (data) {
575	    for (i=0;i<n;i++) {
576	       v[i] = data[i];
577	    }
578	 }
579         break;
580      case GL_ORDER:
581         if (map1d) {
582            v[0] = (GLdouble) map1d->Order;
583         }
584         else {
585            v[0] = (GLdouble) map2d->Uorder;
586            v[1] = (GLdouble) map2d->Vorder;
587         }
588         break;
589      case GL_DOMAIN:
590         if (map1d) {
591            v[0] = (GLdouble) map1d->u1;
592            v[1] = (GLdouble) map1d->u2;
593         }
594         else {
595            v[0] = (GLdouble) map2d->u1;
596            v[1] = (GLdouble) map2d->u2;
597            v[2] = (GLdouble) map2d->v1;
598            v[3] = (GLdouble) map2d->v2;
599         }
600         break;
601      default:
602         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
603   }
604}
605
606
607void
608_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
609{
610   GET_CURRENT_CONTEXT(ctx);
611   struct gl_1d_map *map1d;
612   struct gl_2d_map *map2d;
613   GLint i, n;
614   GLfloat *data;
615   GLuint comps;
616
617   ASSERT_OUTSIDE_BEGIN_END(ctx);
618
619   comps = _mesa_evaluator_components(target);
620   if (!comps) {
621      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
622      return;
623   }
624
625   map1d = get_1d_map(ctx, target);
626   map2d = get_2d_map(ctx, target);
627   ASSERT(map1d || map2d);
628
629   switch (query) {
630      case GL_COEFF:
631         if (map1d) {
632            data = map1d->Points;
633            n = map1d->Order * comps;
634         }
635         else {
636            data = map2d->Points;
637            n = map2d->Uorder * map2d->Vorder * comps;
638         }
639	 if (data) {
640	    for (i=0;i<n;i++) {
641	       v[i] = data[i];
642	    }
643	 }
644         break;
645      case GL_ORDER:
646         if (map1d) {
647            v[0] = (GLfloat) map1d->Order;
648         }
649         else {
650            v[0] = (GLfloat) map2d->Uorder;
651            v[1] = (GLfloat) map2d->Vorder;
652         }
653         break;
654      case GL_DOMAIN:
655         if (map1d) {
656            v[0] = map1d->u1;
657            v[1] = map1d->u2;
658         }
659         else {
660            v[0] = map2d->u1;
661            v[1] = map2d->u2;
662            v[2] = map2d->v1;
663            v[3] = map2d->v2;
664         }
665         break;
666      default:
667         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
668   }
669}
670
671
672void
673_mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
674{
675   GET_CURRENT_CONTEXT(ctx);
676   struct gl_1d_map *map1d;
677   struct gl_2d_map *map2d;
678   GLuint i, n;
679   GLfloat *data;
680   GLuint comps;
681
682   ASSERT_OUTSIDE_BEGIN_END(ctx);
683
684   comps = _mesa_evaluator_components(target);
685   if (!comps) {
686      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
687      return;
688   }
689
690   map1d = get_1d_map(ctx, target);
691   map2d = get_2d_map(ctx, target);
692   ASSERT(map1d || map2d);
693
694   switch (query) {
695      case GL_COEFF:
696         if (map1d) {
697            data = map1d->Points;
698            n = map1d->Order * comps;
699         }
700         else {
701            data = map2d->Points;
702            n = map2d->Uorder * map2d->Vorder * comps;
703         }
704	 if (data) {
705	    for (i=0;i<n;i++) {
706	       v[i] = IROUND(data[i]);
707	    }
708	 }
709         break;
710      case GL_ORDER:
711         if (map1d) {
712            v[0] = map1d->Order;
713         }
714         else {
715            v[0] = map2d->Uorder;
716            v[1] = map2d->Vorder;
717         }
718         break;
719      case GL_DOMAIN:
720         if (map1d) {
721            v[0] = IROUND(map1d->u1);
722            v[1] = IROUND(map1d->u2);
723         }
724         else {
725            v[0] = IROUND(map2d->u1);
726            v[1] = IROUND(map2d->u2);
727            v[2] = IROUND(map2d->v1);
728            v[3] = IROUND(map2d->v2);
729         }
730         break;
731      default:
732         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
733   }
734}
735
736
737
738void
739_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
740{
741   GET_CURRENT_CONTEXT(ctx);
742   ASSERT_OUTSIDE_BEGIN_END(ctx);
743
744   if (un<1) {
745      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
746      return;
747   }
748   FLUSH_VERTICES(ctx, _NEW_EVAL);
749   ctx->Eval.MapGrid1un = un;
750   ctx->Eval.MapGrid1u1 = u1;
751   ctx->Eval.MapGrid1u2 = u2;
752   ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
753}
754
755
756void
757_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
758{
759   _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
760}
761
762
763void
764_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
765                 GLint vn, GLfloat v1, GLfloat v2 )
766{
767   GET_CURRENT_CONTEXT(ctx);
768   ASSERT_OUTSIDE_BEGIN_END(ctx);
769
770   if (un<1) {
771      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
772      return;
773   }
774   if (vn<1) {
775      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
776      return;
777   }
778
779   FLUSH_VERTICES(ctx, _NEW_EVAL);
780   ctx->Eval.MapGrid2un = un;
781   ctx->Eval.MapGrid2u1 = u1;
782   ctx->Eval.MapGrid2u2 = u2;
783   ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
784   ctx->Eval.MapGrid2vn = vn;
785   ctx->Eval.MapGrid2v1 = v1;
786   ctx->Eval.MapGrid2v2 = v2;
787   ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
788}
789
790
791void
792_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
793                 GLint vn, GLdouble v1, GLdouble v2 )
794{
795   _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
796		    vn, (GLfloat) v1, (GLfloat) v2 );
797}
798