1
2/*
3 * Mesa 3-D graphics library
4 *
5 * Copyright (C) 1999-2003  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * 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 "context.h"
43#include "eval.h"
44#include "macros.h"
45#include "mtypes.h"
46#include "main/dispatch.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   return 0;
79}
80
81
82/*
83 * Return pointer to the gl_1d_map struct for the named target.
84 */
85static struct gl_1d_map *
86get_1d_map( struct gl_context *ctx, GLenum target )
87{
88   switch (target) {
89      case GL_MAP1_VERTEX_3:
90         return &ctx->EvalMap.Map1Vertex3;
91      case GL_MAP1_VERTEX_4:
92         return &ctx->EvalMap.Map1Vertex4;
93      case GL_MAP1_INDEX:
94         return &ctx->EvalMap.Map1Index;
95      case GL_MAP1_COLOR_4:
96         return &ctx->EvalMap.Map1Color4;
97      case GL_MAP1_NORMAL:
98         return &ctx->EvalMap.Map1Normal;
99      case GL_MAP1_TEXTURE_COORD_1:
100         return &ctx->EvalMap.Map1Texture1;
101      case GL_MAP1_TEXTURE_COORD_2:
102         return &ctx->EvalMap.Map1Texture2;
103      case GL_MAP1_TEXTURE_COORD_3:
104         return &ctx->EvalMap.Map1Texture3;
105      case GL_MAP1_TEXTURE_COORD_4:
106         return &ctx->EvalMap.Map1Texture4;
107      default:
108         return NULL;
109   }
110}
111
112
113/*
114 * Return pointer to the gl_2d_map struct for the named target.
115 */
116static struct gl_2d_map *
117get_2d_map( struct gl_context *ctx, GLenum target )
118{
119   switch (target) {
120      case GL_MAP2_VERTEX_3:
121         return &ctx->EvalMap.Map2Vertex3;
122      case GL_MAP2_VERTEX_4:
123         return &ctx->EvalMap.Map2Vertex4;
124      case GL_MAP2_INDEX:
125         return &ctx->EvalMap.Map2Index;
126      case GL_MAP2_COLOR_4:
127         return &ctx->EvalMap.Map2Color4;
128      case GL_MAP2_NORMAL:
129         return &ctx->EvalMap.Map2Normal;
130      case GL_MAP2_TEXTURE_COORD_1:
131         return &ctx->EvalMap.Map2Texture1;
132      case GL_MAP2_TEXTURE_COORD_2:
133         return &ctx->EvalMap.Map2Texture2;
134      case GL_MAP2_TEXTURE_COORD_3:
135         return &ctx->EvalMap.Map2Texture3;
136      case GL_MAP2_TEXTURE_COORD_4:
137         return &ctx->EvalMap.Map2Texture4;
138      default:
139         return NULL;
140   }
141}
142
143
144/**********************************************************************/
145/***            Copy and deallocate control points                  ***/
146/**********************************************************************/
147
148
149/*
150 * Copy 1-parametric evaluator control points from user-specified
151 * memory space to a buffer of contiguous control points.
152 * \param see glMap1f for details
153 * \return pointer to buffer of contiguous control points or NULL if out
154 *          of memory.
155 */
156GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
157                                  const GLfloat *points )
158{
159   GLfloat *buffer, *p;
160   GLint i, k, size = _mesa_evaluator_components(target);
161
162   if (!points || !size)
163      return NULL;
164
165   buffer = malloc(uorder * size * sizeof(GLfloat));
166
167   if (buffer)
168      for (i = 0, p = buffer; i < uorder; i++, points += ustride)
169	for (k = 0; k < size; k++)
170	  *p++ = points[k];
171
172   return buffer;
173}
174
175
176
177/*
178 * Same as above but convert doubles to floats.
179 */
180GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
181                                  const GLdouble *points )
182{
183   GLfloat *buffer, *p;
184   GLint i, k, size = _mesa_evaluator_components(target);
185
186   if (!points || !size)
187      return NULL;
188
189   buffer = malloc(uorder * size * sizeof(GLfloat));
190
191   if (buffer)
192      for (i = 0, p = buffer; i < uorder; i++, points += ustride)
193	for (k = 0; k < size; k++)
194	  *p++ = (GLfloat) points[k];
195
196   return buffer;
197}
198
199
200
201/*
202 * Copy 2-parametric evaluator control points from user-specified
203 * memory space to a buffer of contiguous control points.
204 * Additional memory is allocated to be used by the horner and
205 * de Casteljau evaluation schemes.
206 *
207 * \param see glMap2f for details
208 * \return pointer to buffer of contiguous control points or NULL if out
209 *          of memory.
210 */
211GLfloat *_mesa_copy_map_points2f( GLenum target,
212                                  GLint ustride, GLint uorder,
213                                  GLint vstride, GLint vorder,
214                                  const GLfloat *points )
215{
216   GLfloat *buffer, *p;
217   GLint i, j, k, size, dsize, hsize;
218   GLint uinc;
219
220   size = _mesa_evaluator_components(target);
221
222   if (!points || size==0) {
223      return NULL;
224   }
225
226   /* max(uorder, vorder) additional points are used in      */
227   /* horner evaluation and uorder*vorder additional */
228   /* values are needed for de Casteljau                     */
229   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
230   hsize = (uorder > vorder ? uorder : vorder)*size;
231
232   if(hsize>dsize)
233     buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
234   else
235     buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
236
237   /* compute the increment value for the u-loop */
238   uinc = ustride - vorder*vstride;
239
240   if (buffer)
241      for (i=0, p=buffer; i<uorder; i++, points += uinc)
242	 for (j=0; j<vorder; j++, points += vstride)
243	    for (k=0; k<size; k++)
244	       *p++ = points[k];
245
246   return buffer;
247}
248
249
250
251/*
252 * Same as above but convert doubles to floats.
253 */
254GLfloat *_mesa_copy_map_points2d(GLenum target,
255                                 GLint ustride, GLint uorder,
256                                 GLint vstride, GLint vorder,
257                                 const GLdouble *points )
258{
259   GLfloat *buffer, *p;
260   GLint i, j, k, size, hsize, dsize;
261   GLint uinc;
262
263   size = _mesa_evaluator_components(target);
264
265   if (!points || size==0) {
266      return NULL;
267   }
268
269   /* max(uorder, vorder) additional points are used in      */
270   /* horner evaluation and uorder*vorder additional */
271   /* values are needed for de Casteljau                     */
272   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
273   hsize = (uorder > vorder ? uorder : vorder)*size;
274
275   if(hsize>dsize)
276     buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
277   else
278     buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
279
280   /* compute the increment value for the u-loop */
281   uinc = ustride - vorder*vstride;
282
283   if (buffer)
284      for (i=0, p=buffer; i<uorder; i++, points += uinc)
285	 for (j=0; j<vorder; j++, points += vstride)
286	    for (k=0; k<size; k++)
287	       *p++ = (GLfloat) points[k];
288
289   return buffer;
290}
291
292
293
294
295/**********************************************************************/
296/***                      API entry points                          ***/
297/**********************************************************************/
298
299
300/*
301 * This does the work of glMap1[fd].
302 */
303static void
304map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
305     GLint uorder, const GLvoid *points, GLenum type )
306{
307   GET_CURRENT_CONTEXT(ctx);
308   GLint k;
309   GLfloat *pnts;
310   struct gl_1d_map *map = NULL;
311
312   assert(type == GL_FLOAT || type == GL_DOUBLE);
313
314   if (u1 == u2) {
315      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
316      return;
317   }
318   if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
319      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
320      return;
321   }
322   if (!points) {
323      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
324      return;
325   }
326
327   k = _mesa_evaluator_components( target );
328   if (k == 0) {
329      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
330      return;
331   }
332
333   if (ustride < k) {
334      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
335      return;
336   }
337
338   if (ctx->Texture.CurrentUnit != 0) {
339      /* See OpenGL 1.2.1 spec, section F.2.13 */
340      _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
341      return;
342   }
343
344   map = get_1d_map(ctx, target);
345   if (!map) {
346      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
347      return;
348   }
349
350   /* make copy of the control points */
351   if (type == GL_FLOAT)
352      pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
353   else
354      pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
355
356
357   FLUSH_VERTICES(ctx, _NEW_EVAL);
358   map->Order = uorder;
359   map->u1 = u1;
360   map->u2 = u2;
361   map->du = 1.0F / (u2 - u1);
362   free(map->Points);
363   map->Points = pnts;
364}
365
366
367
368void GLAPIENTRY
369_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
370             GLint order, const GLfloat *points )
371{
372   map1(target, u1, u2, stride, order, points, GL_FLOAT);
373}
374
375
376void GLAPIENTRY
377_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
378             GLint order, const GLdouble *points )
379{
380   map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
381}
382
383
384static void
385map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
386      GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
387      const GLvoid *points, GLenum type )
388{
389   GET_CURRENT_CONTEXT(ctx);
390   GLint k;
391   GLfloat *pnts;
392   struct gl_2d_map *map = NULL;
393
394   assert(type == GL_FLOAT || type == GL_DOUBLE);
395
396   if (u1==u2) {
397      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
398      return;
399   }
400
401   if (v1==v2) {
402      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
403      return;
404   }
405
406   if (uorder<1 || uorder>MAX_EVAL_ORDER) {
407      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
408      return;
409   }
410
411   if (vorder<1 || vorder>MAX_EVAL_ORDER) {
412      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
413      return;
414   }
415
416   k = _mesa_evaluator_components( target );
417   if (k==0) {
418      _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
419      return;
420   }
421
422   if (ustride < k) {
423      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
424      return;
425   }
426   if (vstride < k) {
427      _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
428      return;
429   }
430
431   if (ctx->Texture.CurrentUnit != 0) {
432      /* See OpenGL 1.2.1 spec, section F.2.13 */
433      _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
434      return;
435   }
436
437   map = get_2d_map(ctx, target);
438   if (!map) {
439      _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
440      return;
441   }
442
443   /* make copy of the control points */
444   if (type == GL_FLOAT)
445      pnts = _mesa_copy_map_points2f(target, ustride, uorder,
446                                  vstride, vorder, (GLfloat*) points);
447   else
448      pnts = _mesa_copy_map_points2d(target, ustride, uorder,
449                                  vstride, vorder, (GLdouble*) points);
450
451
452   FLUSH_VERTICES(ctx, _NEW_EVAL);
453   map->Uorder = uorder;
454   map->u1 = u1;
455   map->u2 = u2;
456   map->du = 1.0F / (u2 - u1);
457   map->Vorder = vorder;
458   map->v1 = v1;
459   map->v2 = v2;
460   map->dv = 1.0F / (v2 - v1);
461   free(map->Points);
462   map->Points = pnts;
463}
464
465
466void GLAPIENTRY
467_mesa_Map2f( GLenum target,
468             GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
469             GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
470             const GLfloat *points)
471{
472   map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
473        points, GL_FLOAT);
474}
475
476
477void GLAPIENTRY
478_mesa_Map2d( GLenum target,
479             GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
480             GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
481             const GLdouble *points )
482{
483   map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
484	(GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
485}
486
487
488
489void GLAPIENTRY
490_mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, GLdouble *v )
491{
492   GET_CURRENT_CONTEXT(ctx);
493   struct gl_1d_map *map1d;
494   struct gl_2d_map *map2d;
495   GLint i, n;
496   GLfloat *data;
497   GLuint comps;
498   GLsizei numBytes;
499
500   comps = _mesa_evaluator_components(target);
501   if (!comps) {
502      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
503      return;
504   }
505
506   map1d = get_1d_map(ctx, target);
507   map2d = get_2d_map(ctx, target);
508   assert(map1d || map2d);
509
510   switch (query) {
511      case GL_COEFF:
512         if (map1d) {
513            data = map1d->Points;
514            n = map1d->Order * comps;
515         }
516         else {
517            data = map2d->Points;
518            n = map2d->Uorder * map2d->Vorder * comps;
519         }
520	 if (data) {
521            numBytes = n * sizeof *v;
522            if (bufSize < numBytes)
523               goto overflow;
524	    for (i=0;i<n;i++) {
525	       v[i] = data[i];
526	    }
527	 }
528         break;
529      case GL_ORDER:
530         if (map1d) {
531            numBytes = 1 * sizeof *v;
532            if (bufSize < numBytes)
533               goto overflow;
534            v[0] = (GLdouble) map1d->Order;
535         }
536         else {
537            numBytes = 2 * sizeof *v;
538            if (bufSize < numBytes)
539               goto overflow;
540            v[0] = (GLdouble) map2d->Uorder;
541            v[1] = (GLdouble) map2d->Vorder;
542         }
543         break;
544      case GL_DOMAIN:
545         if (map1d) {
546            numBytes = 2 * sizeof *v;
547            if (bufSize < numBytes)
548              goto overflow;
549            v[0] = (GLdouble) map1d->u1;
550            v[1] = (GLdouble) map1d->u2;
551         }
552         else {
553            numBytes = 4 * sizeof *v;
554            if (bufSize < numBytes)
555               goto overflow;
556            v[0] = (GLdouble) map2d->u1;
557            v[1] = (GLdouble) map2d->u2;
558            v[2] = (GLdouble) map2d->v1;
559            v[3] = (GLdouble) map2d->v2;
560         }
561         break;
562      default:
563         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
564   }
565   return;
566
567overflow:
568   _mesa_error( ctx, GL_INVALID_OPERATION,
569               "glGetnMapdvARB(out of bounds: bufSize is %d,"
570               " but %d bytes are required)", bufSize, numBytes );
571}
572
573void GLAPIENTRY
574_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
575{
576   _mesa_GetnMapdvARB(target, query, INT_MAX, v);
577}
578
579void GLAPIENTRY
580_mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v )
581{
582   GET_CURRENT_CONTEXT(ctx);
583   struct gl_1d_map *map1d;
584   struct gl_2d_map *map2d;
585   GLint i, n;
586   GLfloat *data;
587   GLuint comps;
588   GLsizei numBytes;
589
590   comps = _mesa_evaluator_components(target);
591   if (!comps) {
592      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
593      return;
594   }
595
596   map1d = get_1d_map(ctx, target);
597   map2d = get_2d_map(ctx, target);
598   assert(map1d || map2d);
599
600   switch (query) {
601      case GL_COEFF:
602         if (map1d) {
603            data = map1d->Points;
604            n = map1d->Order * comps;
605         }
606         else {
607            data = map2d->Points;
608            n = map2d->Uorder * map2d->Vorder * comps;
609         }
610	 if (data) {
611            numBytes = n * sizeof *v;
612            if (bufSize < numBytes)
613               goto overflow;
614	    for (i=0;i<n;i++) {
615	       v[i] = data[i];
616	    }
617	 }
618         break;
619      case GL_ORDER:
620         if (map1d) {
621            numBytes = 1 * sizeof *v;
622            if (bufSize < numBytes)
623               goto overflow;
624            v[0] = (GLfloat) map1d->Order;
625         }
626         else {
627            numBytes = 2 * sizeof *v;
628            if (bufSize < numBytes)
629               goto overflow;
630            v[0] = (GLfloat) map2d->Uorder;
631            v[1] = (GLfloat) map2d->Vorder;
632         }
633         break;
634      case GL_DOMAIN:
635         if (map1d) {
636            numBytes = 2 * sizeof *v;
637            if (bufSize < numBytes)
638               goto overflow;
639            v[0] = map1d->u1;
640            v[1] = map1d->u2;
641         }
642         else {
643            numBytes = 4 * sizeof *v;
644            if (bufSize < numBytes)
645               goto overflow;
646            v[0] = map2d->u1;
647            v[1] = map2d->u2;
648            v[2] = map2d->v1;
649            v[3] = map2d->v2;
650         }
651         break;
652      default:
653         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
654   }
655   return;
656
657overflow:
658   _mesa_error( ctx, GL_INVALID_OPERATION,
659               "glGetnMapfvARB(out of bounds: bufSize is %d,"
660               " but %d bytes are required)", bufSize, numBytes );
661}
662
663
664void GLAPIENTRY
665_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
666{
667   _mesa_GetnMapfvARB(target, query, INT_MAX, v);
668}
669
670
671void GLAPIENTRY
672_mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
673{
674   GET_CURRENT_CONTEXT(ctx);
675   struct gl_1d_map *map1d;
676   struct gl_2d_map *map2d;
677   GLuint i, n;
678   GLfloat *data;
679   GLuint comps;
680   GLsizei numBytes;
681
682   comps = _mesa_evaluator_components(target);
683   if (!comps) {
684      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
685      return;
686   }
687
688   map1d = get_1d_map(ctx, target);
689   map2d = get_2d_map(ctx, target);
690   assert(map1d || map2d);
691
692   switch (query) {
693      case GL_COEFF:
694         if (map1d) {
695            data = map1d->Points;
696            n = map1d->Order * comps;
697         }
698         else {
699            data = map2d->Points;
700            n = map2d->Uorder * map2d->Vorder * comps;
701         }
702	 if (data) {
703            numBytes = n * sizeof *v;
704            if (bufSize < numBytes)
705               goto overflow;
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            numBytes = 1 * sizeof *v;
714            if (bufSize < numBytes)
715               goto overflow;
716            v[0] = map1d->Order;
717         }
718         else {
719            numBytes = 2 * sizeof *v;
720            if (bufSize < numBytes)
721               goto overflow;
722            v[0] = map2d->Uorder;
723            v[1] = map2d->Vorder;
724         }
725         break;
726      case GL_DOMAIN:
727         if (map1d) {
728            numBytes = 2 * sizeof *v;
729            if (bufSize < numBytes)
730               goto overflow;
731            v[0] = IROUND(map1d->u1);
732            v[1] = IROUND(map1d->u2);
733         }
734         else {
735            numBytes = 4 * sizeof *v;
736            if (bufSize < numBytes)
737               goto overflow;
738            v[0] = IROUND(map2d->u1);
739            v[1] = IROUND(map2d->u2);
740            v[2] = IROUND(map2d->v1);
741            v[3] = IROUND(map2d->v2);
742         }
743         break;
744      default:
745         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
746   }
747   return;
748
749overflow:
750   _mesa_error( ctx, GL_INVALID_OPERATION,
751               "glGetnMapivARB(out of bounds: bufSize is %d,"
752               " but %d bytes are required)", bufSize, numBytes );
753}
754
755
756void GLAPIENTRY
757_mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
758{
759   _mesa_GetnMapivARB(target, query, INT_MAX, v);
760}
761
762
763void GLAPIENTRY
764_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
765{
766   GET_CURRENT_CONTEXT(ctx);
767
768   if (un<1) {
769      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
770      return;
771   }
772   FLUSH_VERTICES(ctx, _NEW_EVAL);
773   ctx->Eval.MapGrid1un = un;
774   ctx->Eval.MapGrid1u1 = u1;
775   ctx->Eval.MapGrid1u2 = u2;
776   ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
777}
778
779
780void GLAPIENTRY
781_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
782{
783   _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
784}
785
786
787void GLAPIENTRY
788_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
789                 GLint vn, GLfloat v1, GLfloat v2 )
790{
791   GET_CURRENT_CONTEXT(ctx);
792
793   if (un<1) {
794      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
795      return;
796   }
797   if (vn<1) {
798      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
799      return;
800   }
801
802   FLUSH_VERTICES(ctx, _NEW_EVAL);
803   ctx->Eval.MapGrid2un = un;
804   ctx->Eval.MapGrid2u1 = u1;
805   ctx->Eval.MapGrid2u2 = u2;
806   ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
807   ctx->Eval.MapGrid2vn = vn;
808   ctx->Eval.MapGrid2v1 = v1;
809   ctx->Eval.MapGrid2v2 = v2;
810   ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
811}
812
813
814void GLAPIENTRY
815_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
816                 GLint vn, GLdouble v1, GLdouble v2 )
817{
818   _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
819		    vn, (GLfloat) v1, (GLfloat) v2 );
820}
821
822
823void
824_mesa_install_eval_vtxfmt(struct _glapi_table *disp,
825                          const GLvertexformat *vfmt)
826{
827   SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
828   SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
829   SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
830   SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
831   SET_EvalPoint1(disp, vfmt->EvalPoint1);
832   SET_EvalPoint2(disp, vfmt->EvalPoint2);
833}
834
835
836/**********************************************************************/
837/*****                      Initialization                        *****/
838/**********************************************************************/
839
840/**
841 * Initialize a 1-D evaluator map.
842 */
843static void
844init_1d_map( struct gl_1d_map *map, int n, const float *initial )
845{
846   map->Order = 1;
847   map->u1 = 0.0;
848   map->u2 = 1.0;
849   map->Points = malloc(n * sizeof(GLfloat));
850   if (map->Points) {
851      GLint i;
852      for (i=0;i<n;i++)
853         map->Points[i] = initial[i];
854   }
855}
856
857
858/**
859 * Initialize a 2-D evaluator map
860 */
861static void
862init_2d_map( struct gl_2d_map *map, int n, const float *initial )
863{
864   map->Uorder = 1;
865   map->Vorder = 1;
866   map->u1 = 0.0;
867   map->u2 = 1.0;
868   map->v1 = 0.0;
869   map->v2 = 1.0;
870   map->Points = malloc(n * sizeof(GLfloat));
871   if (map->Points) {
872      GLint i;
873      for (i=0;i<n;i++)
874         map->Points[i] = initial[i];
875   }
876}
877
878
879void _mesa_init_eval( struct gl_context *ctx )
880{
881   /* Evaluators group */
882   ctx->Eval.Map1Color4 = GL_FALSE;
883   ctx->Eval.Map1Index = GL_FALSE;
884   ctx->Eval.Map1Normal = GL_FALSE;
885   ctx->Eval.Map1TextureCoord1 = GL_FALSE;
886   ctx->Eval.Map1TextureCoord2 = GL_FALSE;
887   ctx->Eval.Map1TextureCoord3 = GL_FALSE;
888   ctx->Eval.Map1TextureCoord4 = GL_FALSE;
889   ctx->Eval.Map1Vertex3 = GL_FALSE;
890   ctx->Eval.Map1Vertex4 = GL_FALSE;
891   ctx->Eval.Map2Color4 = GL_FALSE;
892   ctx->Eval.Map2Index = GL_FALSE;
893   ctx->Eval.Map2Normal = GL_FALSE;
894   ctx->Eval.Map2TextureCoord1 = GL_FALSE;
895   ctx->Eval.Map2TextureCoord2 = GL_FALSE;
896   ctx->Eval.Map2TextureCoord3 = GL_FALSE;
897   ctx->Eval.Map2TextureCoord4 = GL_FALSE;
898   ctx->Eval.Map2Vertex3 = GL_FALSE;
899   ctx->Eval.Map2Vertex4 = GL_FALSE;
900   ctx->Eval.AutoNormal = GL_FALSE;
901   ctx->Eval.MapGrid1un = 1;
902   ctx->Eval.MapGrid1u1 = 0.0;
903   ctx->Eval.MapGrid1u2 = 1.0;
904   ctx->Eval.MapGrid2un = 1;
905   ctx->Eval.MapGrid2vn = 1;
906   ctx->Eval.MapGrid2u1 = 0.0;
907   ctx->Eval.MapGrid2u2 = 1.0;
908   ctx->Eval.MapGrid2v1 = 0.0;
909   ctx->Eval.MapGrid2v2 = 1.0;
910
911   /* Evaluator data */
912   {
913      static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
914      static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
915      static GLfloat index[1] = { 1.0 };
916      static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
917      static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
918
919      init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
920      init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
921      init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
922      init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
923      init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
924      init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
925      init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
926      init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
927      init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
928
929      init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
930      init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
931      init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
932      init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
933      init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
934      init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
935      init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
936      init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
937      init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
938   }
939}
940
941
942void _mesa_free_eval_data( struct gl_context *ctx )
943{
944   /* Free evaluator data */
945   free(ctx->EvalMap.Map1Vertex3.Points);
946   free(ctx->EvalMap.Map1Vertex4.Points);
947   free(ctx->EvalMap.Map1Index.Points);
948   free(ctx->EvalMap.Map1Color4.Points);
949   free(ctx->EvalMap.Map1Normal.Points);
950   free(ctx->EvalMap.Map1Texture1.Points);
951   free(ctx->EvalMap.Map1Texture2.Points);
952   free(ctx->EvalMap.Map1Texture3.Points);
953   free(ctx->EvalMap.Map1Texture4.Points);
954
955   free(ctx->EvalMap.Map2Vertex3.Points);
956   free(ctx->EvalMap.Map2Vertex4.Points);
957   free(ctx->EvalMap.Map2Index.Points);
958   free(ctx->EvalMap.Map2Color4.Points);
959   free(ctx->EvalMap.Map2Normal.Points);
960   free(ctx->EvalMap.Map2Texture1.Points);
961   free(ctx->EvalMap.Map2Texture2.Points);
962   free(ctx->EvalMap.Map2Texture3.Points);
963   free(ctx->EvalMap.Map2Texture4.Points);
964}
965