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