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