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 "context.h"
42#include "eval.h"
43#include "macros.h"
44#include "mtypes.h"
45#include "main/dispatch.h"
46
47
48/*
49 * Return the number of components per control point for any type of
50 * evaluator.  Return 0 if bad target.
51 * See table 5.1 in the OpenGL 1.2 spec.
52 */
53GLuint _mesa_evaluator_components( GLenum target )
54{
55   switch (target) {
56      case GL_MAP1_VERTEX_3:		return 3;
57      case GL_MAP1_VERTEX_4:		return 4;
58      case GL_MAP1_INDEX:		return 1;
59      case GL_MAP1_COLOR_4:		return 4;
60      case GL_MAP1_NORMAL:		return 3;
61      case GL_MAP1_TEXTURE_COORD_1:	return 1;
62      case GL_MAP1_TEXTURE_COORD_2:	return 2;
63      case GL_MAP1_TEXTURE_COORD_3:	return 3;
64      case GL_MAP1_TEXTURE_COORD_4:	return 4;
65      case GL_MAP2_VERTEX_3:		return 3;
66      case GL_MAP2_VERTEX_4:		return 4;
67      case GL_MAP2_INDEX:		return 1;
68      case GL_MAP2_COLOR_4:		return 4;
69      case GL_MAP2_NORMAL:		return 3;
70      case GL_MAP2_TEXTURE_COORD_1:	return 1;
71      case GL_MAP2_TEXTURE_COORD_2:	return 2;
72      case GL_MAP2_TEXTURE_COORD_3:	return 3;
73      case GL_MAP2_TEXTURE_COORD_4:	return 4;
74      default:				break;
75   }
76
77   return 0;
78}
79
80
81/*
82 * Return pointer to the gl_1d_map struct for the named target.
83 */
84static struct gl_1d_map *
85get_1d_map( struct gl_context *ctx, GLenum target )
86{
87   switch (target) {
88      case GL_MAP1_VERTEX_3:
89         return &ctx->EvalMap.Map1Vertex3;
90      case GL_MAP1_VERTEX_4:
91         return &ctx->EvalMap.Map1Vertex4;
92      case GL_MAP1_INDEX:
93         return &ctx->EvalMap.Map1Index;
94      case GL_MAP1_COLOR_4:
95         return &ctx->EvalMap.Map1Color4;
96      case GL_MAP1_NORMAL:
97         return &ctx->EvalMap.Map1Normal;
98      case GL_MAP1_TEXTURE_COORD_1:
99         return &ctx->EvalMap.Map1Texture1;
100      case GL_MAP1_TEXTURE_COORD_2:
101         return &ctx->EvalMap.Map1Texture2;
102      case GL_MAP1_TEXTURE_COORD_3:
103         return &ctx->EvalMap.Map1Texture3;
104      case GL_MAP1_TEXTURE_COORD_4:
105         return &ctx->EvalMap.Map1Texture4;
106      default:
107         return NULL;
108   }
109}
110
111
112/*
113 * Return pointer to the gl_2d_map struct for the named target.
114 */
115static struct gl_2d_map *
116get_2d_map( struct gl_context *ctx, GLenum target )
117{
118   switch (target) {
119      case GL_MAP2_VERTEX_3:
120         return &ctx->EvalMap.Map2Vertex3;
121      case GL_MAP2_VERTEX_4:
122         return &ctx->EvalMap.Map2Vertex4;
123      case GL_MAP2_INDEX:
124         return &ctx->EvalMap.Map2Index;
125      case GL_MAP2_COLOR_4:
126         return &ctx->EvalMap.Map2Color4;
127      case GL_MAP2_NORMAL:
128         return &ctx->EvalMap.Map2Normal;
129      case GL_MAP2_TEXTURE_COORD_1:
130         return &ctx->EvalMap.Map2Texture1;
131      case GL_MAP2_TEXTURE_COORD_2:
132         return &ctx->EvalMap.Map2Texture2;
133      case GL_MAP2_TEXTURE_COORD_3:
134         return &ctx->EvalMap.Map2Texture3;
135      case GL_MAP2_TEXTURE_COORD_4:
136         return &ctx->EvalMap.Map2Texture4;
137      default:
138         return NULL;
139   }
140}
141
142
143/**********************************************************************/
144/***            Copy and deallocate control points                  ***/
145/**********************************************************************/
146
147
148/*
149 * Copy 1-parametric evaluator control points from user-specified
150 * memory space to a buffer of contiguous control points.
151 * \param see glMap1f for details
152 * \return pointer to buffer of contiguous control points or NULL if out
153 *          of memory.
154 */
155GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
156                                  const GLfloat *points )
157{
158   GLfloat *buffer, *p;
159   GLint i, k, size = _mesa_evaluator_components(target);
160
161   if (!points || !size)
162      return NULL;
163
164   buffer = malloc(uorder * size * sizeof(GLfloat));
165
166   if (buffer)
167      for (i = 0, p = buffer; i < uorder; i++, points += ustride)
168	for (k = 0; k < size; k++)
169	  *p++ = points[k];
170
171   return buffer;
172}
173
174
175
176/*
177 * Same as above but convert doubles to floats.
178 */
179GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
180                                  const GLdouble *points )
181{
182   GLfloat *buffer, *p;
183   GLint i, k, size = _mesa_evaluator_components(target);
184
185   if (!points || !size)
186      return NULL;
187
188   buffer = malloc(uorder * size * sizeof(GLfloat));
189
190   if (buffer)
191      for (i = 0, p = buffer; i < uorder; i++, points += ustride)
192	for (k = 0; k < size; k++)
193	  *p++ = (GLfloat) points[k];
194
195   return buffer;
196}
197
198
199
200/*
201 * Copy 2-parametric evaluator control points from user-specified
202 * memory space to a buffer of contiguous control points.
203 * Additional memory is allocated to be used by the horner and
204 * de Casteljau evaluation schemes.
205 *
206 * \param see glMap2f for details
207 * \return pointer to buffer of contiguous control points or NULL if out
208 *          of memory.
209 */
210GLfloat *_mesa_copy_map_points2f( GLenum target,
211                                  GLint ustride, GLint uorder,
212                                  GLint vstride, GLint vorder,
213                                  const GLfloat *points )
214{
215   GLfloat *buffer, *p;
216   GLint i, j, k, size, dsize, hsize;
217   GLint uinc;
218
219   size = _mesa_evaluator_components(target);
220
221   if (!points || size==0) {
222      return NULL;
223   }
224
225   /* max(uorder, vorder) additional points are used in      */
226   /* horner evaluation and uorder*vorder additional */
227   /* values are needed for de Casteljau                     */
228   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
229   hsize = (uorder > vorder ? uorder : vorder)*size;
230
231   if(hsize>dsize)
232     buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
233   else
234     buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
235
236   /* compute the increment value for the u-loop */
237   uinc = ustride - vorder*vstride;
238
239   if (buffer)
240      for (i=0, p=buffer; i<uorder; i++, points += uinc)
241	 for (j=0; j<vorder; j++, points += vstride)
242	    for (k=0; k<size; k++)
243	       *p++ = points[k];
244
245   return buffer;
246}
247
248
249
250/*
251 * Same as above but convert doubles to floats.
252 */
253GLfloat *_mesa_copy_map_points2d(GLenum target,
254                                 GLint ustride, GLint uorder,
255                                 GLint vstride, GLint vorder,
256                                 const GLdouble *points )
257{
258   GLfloat *buffer, *p;
259   GLint i, j, k, size, hsize, dsize;
260   GLint uinc;
261
262   size = _mesa_evaluator_components(target);
263
264   if (!points || size==0) {
265      return NULL;
266   }
267
268   /* max(uorder, vorder) additional points are used in      */
269   /* horner evaluation and uorder*vorder additional */
270   /* values are needed for de Casteljau                     */
271   dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
272   hsize = (uorder > vorder ? uorder : vorder)*size;
273
274   if(hsize>dsize)
275     buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
276   else
277     buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
278
279   /* compute the increment value for the u-loop */
280   uinc = ustride - vorder*vstride;
281
282   if (buffer)
283      for (i=0, p=buffer; i<uorder; i++, points += uinc)
284	 for (j=0; j<vorder; j++, points += vstride)
285	    for (k=0; k<size; k++)
286	       *p++ = (GLfloat) points[k];
287
288   return buffer;
289}
290
291
292
293
294/**********************************************************************/
295/***                      API entry points                          ***/
296/**********************************************************************/
297
298
299/*
300 * This does the work of glMap1[fd].
301 */
302static void
303map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
304     GLint uorder, const GLvoid *points, GLenum type )
305{
306   GET_CURRENT_CONTEXT(ctx);
307   GLint k;
308   GLfloat *pnts;
309   struct gl_1d_map *map = NULL;
310
311   assert(type == GL_FLOAT || type == GL_DOUBLE);
312
313   if (u1 == u2) {
314      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
315      return;
316   }
317   if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
318      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
319      return;
320   }
321   if (!points) {
322      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
323      return;
324   }
325
326   k = _mesa_evaluator_components( target );
327   if (k == 0) {
328      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
329      return;
330   }
331
332   if (ustride < k) {
333      _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
334      return;
335   }
336
337   if (ctx->Texture.CurrentUnit != 0) {
338      /* See OpenGL 1.2.1 spec, section F.2.13 */
339      _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
340      return;
341   }
342
343   map = get_1d_map(ctx, target);
344   if (!map) {
345      _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
346      return;
347   }
348
349   /* make copy of the control points */
350   if (type == GL_FLOAT)
351      pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
352   else
353      pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
354
355
356   FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
357   vbo_exec_update_eval_maps(ctx);
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, 0, GL_EVAL_BIT);
453   vbo_exec_update_eval_maps(ctx);
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] = lroundf(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] = lroundf(map1d->u1);
733            v[1] = lroundf(map1d->u2);
734         }
735         else {
736            numBytes = 4 * sizeof *v;
737            if (bufSize < numBytes)
738               goto overflow;
739            v[0] = lroundf(map2d->u1);
740            v[1] = lroundf(map2d->u2);
741            v[2] = lroundf(map2d->v1);
742            v[3] = lroundf(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, 0, GL_EVAL_BIT);
774   vbo_exec_update_eval_maps(ctx);
775   ctx->Eval.MapGrid1un = un;
776   ctx->Eval.MapGrid1u1 = u1;
777   ctx->Eval.MapGrid1u2 = u2;
778   ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
779}
780
781
782void GLAPIENTRY
783_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
784{
785   _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
786}
787
788
789void GLAPIENTRY
790_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
791                 GLint vn, GLfloat v1, GLfloat v2 )
792{
793   GET_CURRENT_CONTEXT(ctx);
794
795   if (un<1) {
796      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
797      return;
798   }
799   if (vn<1) {
800      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
801      return;
802   }
803
804   FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
805   vbo_exec_update_eval_maps(ctx);
806   ctx->Eval.MapGrid2un = un;
807   ctx->Eval.MapGrid2u1 = u1;
808   ctx->Eval.MapGrid2u2 = u2;
809   ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
810   ctx->Eval.MapGrid2vn = vn;
811   ctx->Eval.MapGrid2v1 = v1;
812   ctx->Eval.MapGrid2v2 = v2;
813   ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
814}
815
816
817void GLAPIENTRY
818_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
819                 GLint vn, GLdouble v1, GLdouble v2 )
820{
821   _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
822		    vn, (GLfloat) v1, (GLfloat) v2 );
823}
824
825
826void
827_mesa_install_eval_vtxfmt(struct _glapi_table *disp,
828                          const GLvertexformat *vfmt)
829{
830   SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
831   SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
832   SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
833   SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
834   SET_EvalPoint1(disp, vfmt->EvalPoint1);
835   SET_EvalPoint2(disp, vfmt->EvalPoint2);
836}
837
838
839/**********************************************************************/
840/*****                      Initialization                        *****/
841/**********************************************************************/
842
843/**
844 * Initialize a 1-D evaluator map.
845 */
846static void
847init_1d_map( struct gl_1d_map *map, int n, const float *initial )
848{
849   map->Order = 1;
850   map->u1 = 0.0;
851   map->u2 = 1.0;
852   map->Points = malloc(n * sizeof(GLfloat));
853   if (map->Points) {
854      GLint i;
855      for (i=0;i<n;i++)
856         map->Points[i] = initial[i];
857   }
858}
859
860
861/**
862 * Initialize a 2-D evaluator map
863 */
864static void
865init_2d_map( struct gl_2d_map *map, int n, const float *initial )
866{
867   map->Uorder = 1;
868   map->Vorder = 1;
869   map->u1 = 0.0;
870   map->u2 = 1.0;
871   map->v1 = 0.0;
872   map->v2 = 1.0;
873   map->Points = malloc(n * sizeof(GLfloat));
874   if (map->Points) {
875      GLint i;
876      for (i=0;i<n;i++)
877         map->Points[i] = initial[i];
878   }
879}
880
881
882void _mesa_init_eval( struct gl_context *ctx )
883{
884   /* Evaluators group */
885   ctx->Eval.Map1Color4 = GL_FALSE;
886   ctx->Eval.Map1Index = GL_FALSE;
887   ctx->Eval.Map1Normal = GL_FALSE;
888   ctx->Eval.Map1TextureCoord1 = GL_FALSE;
889   ctx->Eval.Map1TextureCoord2 = GL_FALSE;
890   ctx->Eval.Map1TextureCoord3 = GL_FALSE;
891   ctx->Eval.Map1TextureCoord4 = GL_FALSE;
892   ctx->Eval.Map1Vertex3 = GL_FALSE;
893   ctx->Eval.Map1Vertex4 = GL_FALSE;
894   ctx->Eval.Map2Color4 = GL_FALSE;
895   ctx->Eval.Map2Index = GL_FALSE;
896   ctx->Eval.Map2Normal = GL_FALSE;
897   ctx->Eval.Map2TextureCoord1 = GL_FALSE;
898   ctx->Eval.Map2TextureCoord2 = GL_FALSE;
899   ctx->Eval.Map2TextureCoord3 = GL_FALSE;
900   ctx->Eval.Map2TextureCoord4 = GL_FALSE;
901   ctx->Eval.Map2Vertex3 = GL_FALSE;
902   ctx->Eval.Map2Vertex4 = GL_FALSE;
903   ctx->Eval.AutoNormal = GL_FALSE;
904   ctx->Eval.MapGrid1un = 1;
905   ctx->Eval.MapGrid1u1 = 0.0;
906   ctx->Eval.MapGrid1u2 = 1.0;
907   ctx->Eval.MapGrid2un = 1;
908   ctx->Eval.MapGrid2vn = 1;
909   ctx->Eval.MapGrid2u1 = 0.0;
910   ctx->Eval.MapGrid2u2 = 1.0;
911   ctx->Eval.MapGrid2v1 = 0.0;
912   ctx->Eval.MapGrid2v2 = 1.0;
913
914   /* Evaluator data */
915   {
916      static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
917      static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
918      static GLfloat index[1] = { 1.0 };
919      static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
920      static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
921
922      init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
923      init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
924      init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
925      init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
926      init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
927      init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
928      init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
929      init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
930      init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
931
932      init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
933      init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
934      init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
935      init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
936      init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
937      init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
938      init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
939      init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
940      init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
941   }
942}
943
944
945void _mesa_free_eval_data( struct gl_context *ctx )
946{
947   /* Free evaluator data */
948   free(ctx->EvalMap.Map1Vertex3.Points);
949   free(ctx->EvalMap.Map1Vertex4.Points);
950   free(ctx->EvalMap.Map1Index.Points);
951   free(ctx->EvalMap.Map1Color4.Points);
952   free(ctx->EvalMap.Map1Normal.Points);
953   free(ctx->EvalMap.Map1Texture1.Points);
954   free(ctx->EvalMap.Map1Texture2.Points);
955   free(ctx->EvalMap.Map1Texture3.Points);
956   free(ctx->EvalMap.Map1Texture4.Points);
957
958   free(ctx->EvalMap.Map2Vertex3.Points);
959   free(ctx->EvalMap.Map2Vertex4.Points);
960   free(ctx->EvalMap.Map2Index.Points);
961   free(ctx->EvalMap.Map2Color4.Points);
962   free(ctx->EvalMap.Map2Normal.Points);
963   free(ctx->EvalMap.Map2Texture1.Points);
964   free(ctx->EvalMap.Map2Texture2.Points);
965   free(ctx->EvalMap.Map2Texture3.Points);
966   free(ctx->EvalMap.Map2Texture4.Points);
967}
968