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