xref: /third_party/mesa3d/src/mesa/main/eval.c (revision bf215546)
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#include "api_exec_decl.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, 0, GL_EVAL_BIT);
358   vbo_exec_update_eval_maps(ctx);
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, 0, GL_EVAL_BIT);
454   vbo_exec_update_eval_maps(ctx);
455   map->Uorder = uorder;
456   map->u1 = u1;
457   map->u2 = u2;
458   map->du = 1.0F / (u2 - u1);
459   map->Vorder = vorder;
460   map->v1 = v1;
461   map->v2 = v2;
462   map->dv = 1.0F / (v2 - v1);
463   free(map->Points);
464   map->Points = pnts;
465}
466
467
468void GLAPIENTRY
469_mesa_Map2f( GLenum target,
470             GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
471             GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
472             const GLfloat *points)
473{
474   map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
475        points, GL_FLOAT);
476}
477
478
479void GLAPIENTRY
480_mesa_Map2d( GLenum target,
481             GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
482             GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
483             const GLdouble *points )
484{
485   map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
486	(GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
487}
488
489
490
491void GLAPIENTRY
492_mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, GLdouble *v )
493{
494   GET_CURRENT_CONTEXT(ctx);
495   struct gl_1d_map *map1d;
496   struct gl_2d_map *map2d;
497   GLint i, n;
498   GLfloat *data;
499   GLuint comps;
500   GLsizei numBytes;
501
502   comps = _mesa_evaluator_components(target);
503   if (!comps) {
504      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
505      return;
506   }
507
508   map1d = get_1d_map(ctx, target);
509   map2d = get_2d_map(ctx, target);
510   assert(map1d || map2d);
511
512   switch (query) {
513      case GL_COEFF:
514         if (map1d) {
515            data = map1d->Points;
516            n = map1d->Order * comps;
517         }
518         else {
519            data = map2d->Points;
520            n = map2d->Uorder * map2d->Vorder * comps;
521         }
522	 if (data) {
523            numBytes = n * sizeof *v;
524            if (bufSize < numBytes)
525               goto overflow;
526	    for (i=0;i<n;i++) {
527	       v[i] = data[i];
528	    }
529	 }
530         break;
531      case GL_ORDER:
532         if (map1d) {
533            numBytes = 1 * sizeof *v;
534            if (bufSize < numBytes)
535               goto overflow;
536            v[0] = (GLdouble) map1d->Order;
537         }
538         else {
539            numBytes = 2 * sizeof *v;
540            if (bufSize < numBytes)
541               goto overflow;
542            v[0] = (GLdouble) map2d->Uorder;
543            v[1] = (GLdouble) map2d->Vorder;
544         }
545         break;
546      case GL_DOMAIN:
547         if (map1d) {
548            numBytes = 2 * sizeof *v;
549            if (bufSize < numBytes)
550              goto overflow;
551            v[0] = (GLdouble) map1d->u1;
552            v[1] = (GLdouble) map1d->u2;
553         }
554         else {
555            numBytes = 4 * sizeof *v;
556            if (bufSize < numBytes)
557               goto overflow;
558            v[0] = (GLdouble) map2d->u1;
559            v[1] = (GLdouble) map2d->u2;
560            v[2] = (GLdouble) map2d->v1;
561            v[3] = (GLdouble) map2d->v2;
562         }
563         break;
564      default:
565         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
566   }
567   return;
568
569overflow:
570   _mesa_error( ctx, GL_INVALID_OPERATION,
571               "glGetnMapdvARB(out of bounds: bufSize is %d,"
572               " but %d bytes are required)", bufSize, numBytes );
573}
574
575void GLAPIENTRY
576_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
577{
578   _mesa_GetnMapdvARB(target, query, INT_MAX, v);
579}
580
581void GLAPIENTRY
582_mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v )
583{
584   GET_CURRENT_CONTEXT(ctx);
585   struct gl_1d_map *map1d;
586   struct gl_2d_map *map2d;
587   GLint i, n;
588   GLfloat *data;
589   GLuint comps;
590   GLsizei numBytes;
591
592   comps = _mesa_evaluator_components(target);
593   if (!comps) {
594      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
595      return;
596   }
597
598   map1d = get_1d_map(ctx, target);
599   map2d = get_2d_map(ctx, target);
600   assert(map1d || map2d);
601
602   switch (query) {
603      case GL_COEFF:
604         if (map1d) {
605            data = map1d->Points;
606            n = map1d->Order * comps;
607         }
608         else {
609            data = map2d->Points;
610            n = map2d->Uorder * map2d->Vorder * comps;
611         }
612	 if (data) {
613            numBytes = n * sizeof *v;
614            if (bufSize < numBytes)
615               goto overflow;
616	    for (i=0;i<n;i++) {
617	       v[i] = data[i];
618	    }
619	 }
620         break;
621      case GL_ORDER:
622         if (map1d) {
623            numBytes = 1 * sizeof *v;
624            if (bufSize < numBytes)
625               goto overflow;
626            v[0] = (GLfloat) map1d->Order;
627         }
628         else {
629            numBytes = 2 * sizeof *v;
630            if (bufSize < numBytes)
631               goto overflow;
632            v[0] = (GLfloat) map2d->Uorder;
633            v[1] = (GLfloat) map2d->Vorder;
634         }
635         break;
636      case GL_DOMAIN:
637         if (map1d) {
638            numBytes = 2 * sizeof *v;
639            if (bufSize < numBytes)
640               goto overflow;
641            v[0] = map1d->u1;
642            v[1] = map1d->u2;
643         }
644         else {
645            numBytes = 4 * sizeof *v;
646            if (bufSize < numBytes)
647               goto overflow;
648            v[0] = map2d->u1;
649            v[1] = map2d->u2;
650            v[2] = map2d->v1;
651            v[3] = map2d->v2;
652         }
653         break;
654      default:
655         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
656   }
657   return;
658
659overflow:
660   _mesa_error( ctx, GL_INVALID_OPERATION,
661               "glGetnMapfvARB(out of bounds: bufSize is %d,"
662               " but %d bytes are required)", bufSize, numBytes );
663}
664
665
666void GLAPIENTRY
667_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
668{
669   _mesa_GetnMapfvARB(target, query, INT_MAX, v);
670}
671
672
673void GLAPIENTRY
674_mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, 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   GLsizei numBytes;
683
684   comps = _mesa_evaluator_components(target);
685   if (!comps) {
686      _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
687      return;
688   }
689
690   map1d = get_1d_map(ctx, target);
691   map2d = get_2d_map(ctx, target);
692   assert(map1d || map2d);
693
694   switch (query) {
695      case GL_COEFF:
696         if (map1d) {
697            data = map1d->Points;
698            n = map1d->Order * comps;
699         }
700         else {
701            data = map2d->Points;
702            n = map2d->Uorder * map2d->Vorder * comps;
703         }
704	 if (data) {
705            numBytes = n * sizeof *v;
706            if (bufSize < numBytes)
707               goto overflow;
708	    for (i=0;i<n;i++) {
709	       v[i] = lroundf(data[i]);
710	    }
711	 }
712         break;
713      case GL_ORDER:
714         if (map1d) {
715            numBytes = 1 * sizeof *v;
716            if (bufSize < numBytes)
717               goto overflow;
718            v[0] = map1d->Order;
719         }
720         else {
721            numBytes = 2 * sizeof *v;
722            if (bufSize < numBytes)
723               goto overflow;
724            v[0] = map2d->Uorder;
725            v[1] = map2d->Vorder;
726         }
727         break;
728      case GL_DOMAIN:
729         if (map1d) {
730            numBytes = 2 * sizeof *v;
731            if (bufSize < numBytes)
732               goto overflow;
733            v[0] = lroundf(map1d->u1);
734            v[1] = lroundf(map1d->u2);
735         }
736         else {
737            numBytes = 4 * sizeof *v;
738            if (bufSize < numBytes)
739               goto overflow;
740            v[0] = lroundf(map2d->u1);
741            v[1] = lroundf(map2d->u2);
742            v[2] = lroundf(map2d->v1);
743            v[3] = lroundf(map2d->v2);
744         }
745         break;
746      default:
747         _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
748   }
749   return;
750
751overflow:
752   _mesa_error( ctx, GL_INVALID_OPERATION,
753               "glGetnMapivARB(out of bounds: bufSize is %d,"
754               " but %d bytes are required)", bufSize, numBytes );
755}
756
757
758void GLAPIENTRY
759_mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
760{
761   _mesa_GetnMapivARB(target, query, INT_MAX, v);
762}
763
764
765void GLAPIENTRY
766_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
767{
768   GET_CURRENT_CONTEXT(ctx);
769
770   if (un<1) {
771      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
772      return;
773   }
774   FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
775   vbo_exec_update_eval_maps(ctx);
776   ctx->Eval.MapGrid1un = un;
777   ctx->Eval.MapGrid1u1 = u1;
778   ctx->Eval.MapGrid1u2 = u2;
779   ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
780}
781
782
783void GLAPIENTRY
784_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
785{
786   _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
787}
788
789
790void GLAPIENTRY
791_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
792                 GLint vn, GLfloat v1, GLfloat v2 )
793{
794   GET_CURRENT_CONTEXT(ctx);
795
796   if (un<1) {
797      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
798      return;
799   }
800   if (vn<1) {
801      _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
802      return;
803   }
804
805   FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
806   vbo_exec_update_eval_maps(ctx);
807   ctx->Eval.MapGrid2un = un;
808   ctx->Eval.MapGrid2u1 = u1;
809   ctx->Eval.MapGrid2u2 = u2;
810   ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
811   ctx->Eval.MapGrid2vn = vn;
812   ctx->Eval.MapGrid2v1 = v1;
813   ctx->Eval.MapGrid2v2 = v2;
814   ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
815}
816
817
818void GLAPIENTRY
819_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
820                 GLint vn, GLdouble v1, GLdouble v2 )
821{
822   _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
823		    vn, (GLfloat) v1, (GLfloat) v2 );
824}
825
826
827/**********************************************************************/
828/*****                      Initialization                        *****/
829/**********************************************************************/
830
831/**
832 * Initialize a 1-D evaluator map.
833 */
834static void
835init_1d_map( struct gl_1d_map *map, int n, const float *initial )
836{
837   map->Order = 1;
838   map->u1 = 0.0;
839   map->u2 = 1.0;
840   map->Points = malloc(n * sizeof(GLfloat));
841   if (map->Points) {
842      GLint i;
843      for (i=0;i<n;i++)
844         map->Points[i] = initial[i];
845   }
846}
847
848
849/**
850 * Initialize a 2-D evaluator map
851 */
852static void
853init_2d_map( struct gl_2d_map *map, int n, const float *initial )
854{
855   map->Uorder = 1;
856   map->Vorder = 1;
857   map->u1 = 0.0;
858   map->u2 = 1.0;
859   map->v1 = 0.0;
860   map->v2 = 1.0;
861   map->Points = malloc(n * sizeof(GLfloat));
862   if (map->Points) {
863      GLint i;
864      for (i=0;i<n;i++)
865         map->Points[i] = initial[i];
866   }
867}
868
869
870void _mesa_init_eval( struct gl_context *ctx )
871{
872   /* Evaluators group */
873   ctx->Eval.Map1Color4 = GL_FALSE;
874   ctx->Eval.Map1Index = GL_FALSE;
875   ctx->Eval.Map1Normal = GL_FALSE;
876   ctx->Eval.Map1TextureCoord1 = GL_FALSE;
877   ctx->Eval.Map1TextureCoord2 = GL_FALSE;
878   ctx->Eval.Map1TextureCoord3 = GL_FALSE;
879   ctx->Eval.Map1TextureCoord4 = GL_FALSE;
880   ctx->Eval.Map1Vertex3 = GL_FALSE;
881   ctx->Eval.Map1Vertex4 = GL_FALSE;
882   ctx->Eval.Map2Color4 = GL_FALSE;
883   ctx->Eval.Map2Index = GL_FALSE;
884   ctx->Eval.Map2Normal = GL_FALSE;
885   ctx->Eval.Map2TextureCoord1 = GL_FALSE;
886   ctx->Eval.Map2TextureCoord2 = GL_FALSE;
887   ctx->Eval.Map2TextureCoord3 = GL_FALSE;
888   ctx->Eval.Map2TextureCoord4 = GL_FALSE;
889   ctx->Eval.Map2Vertex3 = GL_FALSE;
890   ctx->Eval.Map2Vertex4 = GL_FALSE;
891   ctx->Eval.AutoNormal = GL_FALSE;
892   ctx->Eval.MapGrid1un = 1;
893   ctx->Eval.MapGrid1u1 = 0.0;
894   ctx->Eval.MapGrid1u2 = 1.0;
895   ctx->Eval.MapGrid2un = 1;
896   ctx->Eval.MapGrid2vn = 1;
897   ctx->Eval.MapGrid2u1 = 0.0;
898   ctx->Eval.MapGrid2u2 = 1.0;
899   ctx->Eval.MapGrid2v1 = 0.0;
900   ctx->Eval.MapGrid2v2 = 1.0;
901
902   /* Evaluator data */
903   {
904      static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
905      static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
906      static GLfloat index[1] = { 1.0 };
907      static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
908      static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
909
910      init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
911      init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
912      init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
913      init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
914      init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
915      init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
916      init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
917      init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
918      init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
919
920      init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
921      init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
922      init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
923      init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
924      init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
925      init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
926      init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
927      init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
928      init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
929   }
930}
931
932
933void _mesa_free_eval_data( struct gl_context *ctx )
934{
935   /* Free evaluator data */
936   free(ctx->EvalMap.Map1Vertex3.Points);
937   free(ctx->EvalMap.Map1Vertex4.Points);
938   free(ctx->EvalMap.Map1Index.Points);
939   free(ctx->EvalMap.Map1Color4.Points);
940   free(ctx->EvalMap.Map1Normal.Points);
941   free(ctx->EvalMap.Map1Texture1.Points);
942   free(ctx->EvalMap.Map1Texture2.Points);
943   free(ctx->EvalMap.Map1Texture3.Points);
944   free(ctx->EvalMap.Map1Texture4.Points);
945
946   free(ctx->EvalMap.Map2Vertex3.Points);
947   free(ctx->EvalMap.Map2Vertex4.Points);
948   free(ctx->EvalMap.Map2Index.Points);
949   free(ctx->EvalMap.Map2Color4.Points);
950   free(ctx->EvalMap.Map2Normal.Points);
951   free(ctx->EvalMap.Map2Texture1.Points);
952   free(ctx->EvalMap.Map2Texture2.Points);
953   free(ctx->EvalMap.Map2Texture3.Points);
954   free(ctx->EvalMap.Map2Texture4.Points);
955}
956