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  */
_mesa_evaluator_components(GLenum target)59 GLuint _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  */
103 static struct gl_1d_map *
get_1d_map(struct gl_context * ctx,GLenum target)104 get_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  */
153 static struct gl_2d_map *
get_2d_map(struct gl_context * ctx,GLenum target)154 get_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  */
_mesa_copy_map_points1f(GLenum target,GLint ustride,GLint uorder,const GLfloat * points)212 GLfloat *_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  */
_mesa_copy_map_points1d(GLenum target,GLint ustride,GLint uorder,const GLdouble * points)236 GLfloat *_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  */
_mesa_copy_map_points2f(GLenum target,GLint ustride,GLint uorder,GLint vstride,GLint vorder,const GLfloat * points)267 GLfloat *_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  */
_mesa_copy_map_points2d(GLenum target,GLint ustride,GLint uorder,GLint vstride,GLint vorder,const GLdouble * points)310 GLfloat *_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  */
359 static void
map1(GLenum target,GLfloat u1,GLfloat u2,GLint ustride,GLint uorder,const GLvoid * points,GLenum type)360 map1(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 
425 static void GLAPIENTRY
_mesa_Map1f(GLenum target,GLfloat u1,GLfloat u2,GLint stride,GLint order,const GLfloat * points)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 
433 static void GLAPIENTRY
_mesa_Map1d(GLenum target,GLdouble u1,GLdouble u2,GLint stride,GLint order,const GLdouble * points)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 
441 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)442 map2( 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 
524 static 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)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 
535 static 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)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 
547 static void GLAPIENTRY
_mesa_GetnMapdvARB(GLenum target,GLenum query,GLsizei bufSize,GLdouble * v)548 _mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, 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    GLsizei numBytes;
557 
558    ASSERT_OUTSIDE_BEGIN_END(ctx);
559 
560    comps = _mesa_evaluator_components(target);
561    if (!comps) {
562       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
563       return;
564    }
565 
566    map1d = get_1d_map(ctx, target);
567    map2d = get_2d_map(ctx, target);
568    ASSERT(map1d || map2d);
569 
570    switch (query) {
571       case GL_COEFF:
572          if (map1d) {
573             data = map1d->Points;
574             n = map1d->Order * comps;
575          }
576          else {
577             data = map2d->Points;
578             n = map2d->Uorder * map2d->Vorder * comps;
579          }
580 	 if (data) {
581             numBytes = n * sizeof *v;
582             if (bufSize < numBytes)
583                goto overflow;
584 	    for (i=0;i<n;i++) {
585 	       v[i] = data[i];
586 	    }
587 	 }
588          break;
589       case GL_ORDER:
590          if (map1d) {
591             numBytes = 1 * sizeof *v;
592             if (bufSize < numBytes)
593                goto overflow;
594             v[0] = (GLdouble) map1d->Order;
595          }
596          else {
597             numBytes = 2 * sizeof *v;
598             if (bufSize < numBytes)
599                goto overflow;
600             v[0] = (GLdouble) map2d->Uorder;
601             v[1] = (GLdouble) map2d->Vorder;
602          }
603          break;
604       case GL_DOMAIN:
605          if (map1d) {
606             numBytes = 2 * sizeof *v;
607             if (bufSize < numBytes)
608               goto overflow;
609             v[0] = (GLdouble) map1d->u1;
610             v[1] = (GLdouble) map1d->u2;
611          }
612          else {
613             numBytes = 4 * sizeof *v;
614             if (bufSize < numBytes)
615                goto overflow;
616             v[0] = (GLdouble) map2d->u1;
617             v[1] = (GLdouble) map2d->u2;
618             v[2] = (GLdouble) map2d->v1;
619             v[3] = (GLdouble) map2d->v2;
620          }
621          break;
622       default:
623          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
624    }
625    return;
626 
627 overflow:
628    _mesa_error( ctx, GL_INVALID_OPERATION,
629                "glGetnMapdvARB(out of bounds: bufSize is %d,"
630                " but %d bytes are required)", bufSize, numBytes );
631 }
632 
633 static void GLAPIENTRY
_mesa_GetMapdv(GLenum target,GLenum query,GLdouble * v)634 _mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
635 {
636    _mesa_GetnMapdvARB(target, query, INT_MAX, v);
637 }
638 
639 static void GLAPIENTRY
_mesa_GetnMapfvARB(GLenum target,GLenum query,GLsizei bufSize,GLfloat * v)640 _mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v )
641 {
642    GET_CURRENT_CONTEXT(ctx);
643    struct gl_1d_map *map1d;
644    struct gl_2d_map *map2d;
645    GLint i, n;
646    GLfloat *data;
647    GLuint comps;
648    GLsizei numBytes;
649 
650    ASSERT_OUTSIDE_BEGIN_END(ctx);
651 
652    comps = _mesa_evaluator_components(target);
653    if (!comps) {
654       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
655       return;
656    }
657 
658    map1d = get_1d_map(ctx, target);
659    map2d = get_2d_map(ctx, target);
660    ASSERT(map1d || map2d);
661 
662    switch (query) {
663       case GL_COEFF:
664          if (map1d) {
665             data = map1d->Points;
666             n = map1d->Order * comps;
667          }
668          else {
669             data = map2d->Points;
670             n = map2d->Uorder * map2d->Vorder * comps;
671          }
672 	 if (data) {
673             numBytes = n * sizeof *v;
674             if (bufSize < numBytes)
675                goto overflow;
676 	    for (i=0;i<n;i++) {
677 	       v[i] = data[i];
678 	    }
679 	 }
680          break;
681       case GL_ORDER:
682          if (map1d) {
683             numBytes = 1 * sizeof *v;
684             if (bufSize < numBytes)
685                goto overflow;
686             v[0] = (GLfloat) map1d->Order;
687          }
688          else {
689             numBytes = 2 * sizeof *v;
690             if (bufSize < numBytes)
691                goto overflow;
692             v[0] = (GLfloat) map2d->Uorder;
693             v[1] = (GLfloat) map2d->Vorder;
694          }
695          break;
696       case GL_DOMAIN:
697          if (map1d) {
698             numBytes = 2 * sizeof *v;
699             if (bufSize < numBytes)
700                goto overflow;
701             v[0] = map1d->u1;
702             v[1] = map1d->u2;
703          }
704          else {
705             numBytes = 4 * sizeof *v;
706             if (bufSize < numBytes)
707                goto overflow;
708             v[0] = map2d->u1;
709             v[1] = map2d->u2;
710             v[2] = map2d->v1;
711             v[3] = map2d->v2;
712          }
713          break;
714       default:
715          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
716    }
717    return;
718 
719 overflow:
720    _mesa_error( ctx, GL_INVALID_OPERATION,
721                "glGetnMapfvARB(out of bounds: bufSize is %d,"
722                " but %d bytes are required)", bufSize, numBytes );
723 }
724 
725 
726 static void GLAPIENTRY
_mesa_GetMapfv(GLenum target,GLenum query,GLfloat * v)727 _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
728 {
729    _mesa_GetnMapfvARB(target, query, INT_MAX, v);
730 }
731 
732 
733 static void GLAPIENTRY
_mesa_GetnMapivARB(GLenum target,GLenum query,GLsizei bufSize,GLint * v)734 _mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
735 {
736    GET_CURRENT_CONTEXT(ctx);
737    struct gl_1d_map *map1d;
738    struct gl_2d_map *map2d;
739    GLuint i, n;
740    GLfloat *data;
741    GLuint comps;
742    GLsizei numBytes;
743 
744    ASSERT_OUTSIDE_BEGIN_END(ctx);
745 
746    comps = _mesa_evaluator_components(target);
747    if (!comps) {
748       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
749       return;
750    }
751 
752    map1d = get_1d_map(ctx, target);
753    map2d = get_2d_map(ctx, target);
754    ASSERT(map1d || map2d);
755 
756    switch (query) {
757       case GL_COEFF:
758          if (map1d) {
759             data = map1d->Points;
760             n = map1d->Order * comps;
761          }
762          else {
763             data = map2d->Points;
764             n = map2d->Uorder * map2d->Vorder * comps;
765          }
766 	 if (data) {
767             numBytes = n * sizeof *v;
768             if (bufSize < numBytes)
769                goto overflow;
770 	    for (i=0;i<n;i++) {
771 	       v[i] = IROUND(data[i]);
772 	    }
773 	 }
774          break;
775       case GL_ORDER:
776          if (map1d) {
777             numBytes = 1 * sizeof *v;
778             if (bufSize < numBytes)
779                goto overflow;
780             v[0] = map1d->Order;
781          }
782          else {
783             numBytes = 2 * sizeof *v;
784             if (bufSize < numBytes)
785                goto overflow;
786             v[0] = map2d->Uorder;
787             v[1] = map2d->Vorder;
788          }
789          break;
790       case GL_DOMAIN:
791          if (map1d) {
792             numBytes = 2 * sizeof *v;
793             if (bufSize < numBytes)
794                goto overflow;
795             v[0] = IROUND(map1d->u1);
796             v[1] = IROUND(map1d->u2);
797          }
798          else {
799             numBytes = 4 * sizeof *v;
800             if (bufSize < numBytes)
801                goto overflow;
802             v[0] = IROUND(map2d->u1);
803             v[1] = IROUND(map2d->u2);
804             v[2] = IROUND(map2d->v1);
805             v[3] = IROUND(map2d->v2);
806          }
807          break;
808       default:
809          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
810    }
811    return;
812 
813 overflow:
814    _mesa_error( ctx, GL_INVALID_OPERATION,
815                "glGetnMapivARB(out of bounds: bufSize is %d,"
816                " but %d bytes are required)", bufSize, numBytes );
817 }
818 
819 
820 static void GLAPIENTRY
_mesa_GetMapiv(GLenum target,GLenum query,GLint * v)821 _mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
822 {
823    _mesa_GetnMapivARB(target, query, INT_MAX, v);
824 }
825 
826 
827 static void GLAPIENTRY
_mesa_MapGrid1f(GLint un,GLfloat u1,GLfloat u2)828 _mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
829 {
830    GET_CURRENT_CONTEXT(ctx);
831    ASSERT_OUTSIDE_BEGIN_END(ctx);
832 
833    if (un<1) {
834       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
835       return;
836    }
837    FLUSH_VERTICES(ctx, _NEW_EVAL);
838    ctx->Eval.MapGrid1un = un;
839    ctx->Eval.MapGrid1u1 = u1;
840    ctx->Eval.MapGrid1u2 = u2;
841    ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
842 }
843 
844 
845 static void GLAPIENTRY
_mesa_MapGrid1d(GLint un,GLdouble u1,GLdouble u2)846 _mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
847 {
848    _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
849 }
850 
851 
852 static void GLAPIENTRY
_mesa_MapGrid2f(GLint un,GLfloat u1,GLfloat u2,GLint vn,GLfloat v1,GLfloat v2)853 _mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
854                  GLint vn, GLfloat v1, GLfloat v2 )
855 {
856    GET_CURRENT_CONTEXT(ctx);
857    ASSERT_OUTSIDE_BEGIN_END(ctx);
858 
859    if (un<1) {
860       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
861       return;
862    }
863    if (vn<1) {
864       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
865       return;
866    }
867 
868    FLUSH_VERTICES(ctx, _NEW_EVAL);
869    ctx->Eval.MapGrid2un = un;
870    ctx->Eval.MapGrid2u1 = u1;
871    ctx->Eval.MapGrid2u2 = u2;
872    ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
873    ctx->Eval.MapGrid2vn = vn;
874    ctx->Eval.MapGrid2v1 = v1;
875    ctx->Eval.MapGrid2v2 = v2;
876    ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
877 }
878 
879 
880 static void GLAPIENTRY
_mesa_MapGrid2d(GLint un,GLdouble u1,GLdouble u2,GLint vn,GLdouble v1,GLdouble v2)881 _mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
882                  GLint vn, GLdouble v1, GLdouble v2 )
883 {
884    _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
885 		    vn, (GLfloat) v1, (GLfloat) v2 );
886 }
887 
888 
889 void
_mesa_install_eval_vtxfmt(struct _glapi_table * disp,const GLvertexformat * vfmt)890 _mesa_install_eval_vtxfmt(struct _glapi_table *disp,
891                           const GLvertexformat *vfmt)
892 {
893    SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
894    SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
895    SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
896    SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
897    SET_EvalPoint1(disp, vfmt->EvalPoint1);
898    SET_EvalPoint2(disp, vfmt->EvalPoint2);
899 
900    SET_EvalMesh1(disp, vfmt->EvalMesh1);
901    SET_EvalMesh2(disp, vfmt->EvalMesh2);
902 }
903 
904 
905 void
_mesa_init_eval_dispatch(struct _glapi_table * disp)906 _mesa_init_eval_dispatch(struct _glapi_table *disp)
907 {
908    SET_GetMapdv(disp, _mesa_GetMapdv);
909    SET_GetMapfv(disp, _mesa_GetMapfv);
910    SET_GetMapiv(disp, _mesa_GetMapiv);
911    SET_Map1d(disp, _mesa_Map1d);
912    SET_Map1f(disp, _mesa_Map1f);
913    SET_Map2d(disp, _mesa_Map2d);
914    SET_Map2f(disp, _mesa_Map2f);
915    SET_MapGrid1d(disp, _mesa_MapGrid1d);
916    SET_MapGrid1f(disp, _mesa_MapGrid1f);
917    SET_MapGrid2d(disp, _mesa_MapGrid2d);
918    SET_MapGrid2f(disp, _mesa_MapGrid2f);
919 
920    /* GL_ARB_robustness */
921    SET_GetnMapdvARB(disp, _mesa_GetnMapdvARB);
922    SET_GetnMapfvARB(disp, _mesa_GetnMapfvARB);
923    SET_GetnMapivARB(disp, _mesa_GetnMapivARB);
924 }
925 
926 
927 #endif /* FEATURE_evaluators */
928 
929 
930 /**********************************************************************/
931 /*****                      Initialization                        *****/
932 /**********************************************************************/
933 
934 /**
935  * Initialize a 1-D evaluator map.
936  */
937 static void
init_1d_map(struct gl_1d_map * map,int n,const float * initial)938 init_1d_map( struct gl_1d_map *map, int n, const float *initial )
939 {
940    map->Order = 1;
941    map->u1 = 0.0;
942    map->u2 = 1.0;
943    map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat));
944    if (map->Points) {
945       GLint i;
946       for (i=0;i<n;i++)
947          map->Points[i] = initial[i];
948    }
949 }
950 
951 
952 /**
953  * Initialize a 2-D evaluator map
954  */
955 static void
init_2d_map(struct gl_2d_map * map,int n,const float * initial)956 init_2d_map( struct gl_2d_map *map, int n, const float *initial )
957 {
958    map->Uorder = 1;
959    map->Vorder = 1;
960    map->u1 = 0.0;
961    map->u2 = 1.0;
962    map->v1 = 0.0;
963    map->v2 = 1.0;
964    map->Points = (GLfloat *) MALLOC(n * sizeof(GLfloat));
965    if (map->Points) {
966       GLint i;
967       for (i=0;i<n;i++)
968          map->Points[i] = initial[i];
969    }
970 }
971 
972 
_mesa_init_eval(struct gl_context * ctx)973 void _mesa_init_eval( struct gl_context *ctx )
974 {
975    int i;
976 
977    /* Evaluators group */
978    ctx->Eval.Map1Color4 = GL_FALSE;
979    ctx->Eval.Map1Index = GL_FALSE;
980    ctx->Eval.Map1Normal = GL_FALSE;
981    ctx->Eval.Map1TextureCoord1 = GL_FALSE;
982    ctx->Eval.Map1TextureCoord2 = GL_FALSE;
983    ctx->Eval.Map1TextureCoord3 = GL_FALSE;
984    ctx->Eval.Map1TextureCoord4 = GL_FALSE;
985    ctx->Eval.Map1Vertex3 = GL_FALSE;
986    ctx->Eval.Map1Vertex4 = GL_FALSE;
987    memset(ctx->Eval.Map1Attrib, 0, sizeof(ctx->Eval.Map1Attrib));
988    ctx->Eval.Map2Color4 = GL_FALSE;
989    ctx->Eval.Map2Index = GL_FALSE;
990    ctx->Eval.Map2Normal = GL_FALSE;
991    ctx->Eval.Map2TextureCoord1 = GL_FALSE;
992    ctx->Eval.Map2TextureCoord2 = GL_FALSE;
993    ctx->Eval.Map2TextureCoord3 = GL_FALSE;
994    ctx->Eval.Map2TextureCoord4 = GL_FALSE;
995    ctx->Eval.Map2Vertex3 = GL_FALSE;
996    ctx->Eval.Map2Vertex4 = GL_FALSE;
997    memset(ctx->Eval.Map2Attrib, 0, sizeof(ctx->Eval.Map2Attrib));
998    ctx->Eval.AutoNormal = GL_FALSE;
999    ctx->Eval.MapGrid1un = 1;
1000    ctx->Eval.MapGrid1u1 = 0.0;
1001    ctx->Eval.MapGrid1u2 = 1.0;
1002    ctx->Eval.MapGrid2un = 1;
1003    ctx->Eval.MapGrid2vn = 1;
1004    ctx->Eval.MapGrid2u1 = 0.0;
1005    ctx->Eval.MapGrid2u2 = 1.0;
1006    ctx->Eval.MapGrid2v1 = 0.0;
1007    ctx->Eval.MapGrid2v2 = 1.0;
1008 
1009    /* Evaluator data */
1010    {
1011       static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
1012       static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
1013       static GLfloat index[1] = { 1.0 };
1014       static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
1015       static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
1016       static GLfloat attrib[4] = { 0.0, 0.0, 0.0, 1.0 };
1017 
1018       init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
1019       init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
1020       init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
1021       init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
1022       init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
1023       init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
1024       init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
1025       init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
1026       init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
1027       for (i = 0; i < 16; i++)
1028          init_1d_map( ctx->EvalMap.Map1Attrib + i, 4, attrib );
1029 
1030       init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
1031       init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
1032       init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
1033       init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
1034       init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
1035       init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
1036       init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
1037       init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
1038       init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
1039       for (i = 0; i < 16; i++)
1040          init_2d_map( ctx->EvalMap.Map2Attrib + i, 4, attrib );
1041    }
1042 }
1043 
1044 
_mesa_free_eval_data(struct gl_context * ctx)1045 void _mesa_free_eval_data( struct gl_context *ctx )
1046 {
1047    int i;
1048 
1049    /* Free evaluator data */
1050    if (ctx->EvalMap.Map1Vertex3.Points)
1051       FREE( ctx->EvalMap.Map1Vertex3.Points );
1052    if (ctx->EvalMap.Map1Vertex4.Points)
1053       FREE( ctx->EvalMap.Map1Vertex4.Points );
1054    if (ctx->EvalMap.Map1Index.Points)
1055       FREE( ctx->EvalMap.Map1Index.Points );
1056    if (ctx->EvalMap.Map1Color4.Points)
1057       FREE( ctx->EvalMap.Map1Color4.Points );
1058    if (ctx->EvalMap.Map1Normal.Points)
1059       FREE( ctx->EvalMap.Map1Normal.Points );
1060    if (ctx->EvalMap.Map1Texture1.Points)
1061       FREE( ctx->EvalMap.Map1Texture1.Points );
1062    if (ctx->EvalMap.Map1Texture2.Points)
1063       FREE( ctx->EvalMap.Map1Texture2.Points );
1064    if (ctx->EvalMap.Map1Texture3.Points)
1065       FREE( ctx->EvalMap.Map1Texture3.Points );
1066    if (ctx->EvalMap.Map1Texture4.Points)
1067       FREE( ctx->EvalMap.Map1Texture4.Points );
1068    for (i = 0; i < 16; i++)
1069       FREE((ctx->EvalMap.Map1Attrib[i].Points));
1070 
1071    if (ctx->EvalMap.Map2Vertex3.Points)
1072       FREE( ctx->EvalMap.Map2Vertex3.Points );
1073    if (ctx->EvalMap.Map2Vertex4.Points)
1074       FREE( ctx->EvalMap.Map2Vertex4.Points );
1075    if (ctx->EvalMap.Map2Index.Points)
1076       FREE( ctx->EvalMap.Map2Index.Points );
1077    if (ctx->EvalMap.Map2Color4.Points)
1078       FREE( ctx->EvalMap.Map2Color4.Points );
1079    if (ctx->EvalMap.Map2Normal.Points)
1080       FREE( ctx->EvalMap.Map2Normal.Points );
1081    if (ctx->EvalMap.Map2Texture1.Points)
1082       FREE( ctx->EvalMap.Map2Texture1.Points );
1083    if (ctx->EvalMap.Map2Texture2.Points)
1084       FREE( ctx->EvalMap.Map2Texture2.Points );
1085    if (ctx->EvalMap.Map2Texture3.Points)
1086       FREE( ctx->EvalMap.Map2Texture3.Points );
1087    if (ctx->EvalMap.Map2Texture4.Points)
1088       FREE( ctx->EvalMap.Map2Texture4.Points );
1089    for (i = 0; i < 16; i++)
1090       FREE((ctx->EvalMap.Map2Attrib[i].Points));
1091 }
1092