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