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