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