• 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 "context.h"
42 #include "eval.h"
43 #include "macros.h"
44 #include "mtypes.h"
45 #include "main/dispatch.h"
46 #include "api_exec_decl.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, 0, GL_EVAL_BIT);
358    vbo_exec_update_eval_maps(ctx);
359    map->Order = uorder;
360    map->u1 = u1;
361    map->u2 = u2;
362    map->du = 1.0F / (u2 - u1);
363    free(map->Points);
364    map->Points = pnts;
365 }
366 
367 
368 
369 void GLAPIENTRY
_mesa_Map1f(GLenum target,GLfloat u1,GLfloat u2,GLint stride,GLint order,const GLfloat * points)370 _mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
371              GLint order, const GLfloat *points )
372 {
373    map1(target, u1, u2, stride, order, points, GL_FLOAT);
374 }
375 
376 
377 void GLAPIENTRY
_mesa_Map1d(GLenum target,GLdouble u1,GLdouble u2,GLint stride,GLint order,const GLdouble * points)378 _mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
379              GLint order, const GLdouble *points )
380 {
381    map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
382 }
383 
384 
385 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)386 map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
387       GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
388       const GLvoid *points, GLenum type )
389 {
390    GET_CURRENT_CONTEXT(ctx);
391    GLint k;
392    GLfloat *pnts;
393    struct gl_2d_map *map = NULL;
394 
395    assert(type == GL_FLOAT || type == GL_DOUBLE);
396 
397    if (u1==u2) {
398       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
399       return;
400    }
401 
402    if (v1==v2) {
403       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
404       return;
405    }
406 
407    if (uorder<1 || uorder>MAX_EVAL_ORDER) {
408       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
409       return;
410    }
411 
412    if (vorder<1 || vorder>MAX_EVAL_ORDER) {
413       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
414       return;
415    }
416 
417    k = _mesa_evaluator_components( target );
418    if (k==0) {
419       _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
420       return;
421    }
422 
423    if (ustride < k) {
424       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
425       return;
426    }
427    if (vstride < k) {
428       _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
429       return;
430    }
431 
432    if (ctx->Texture.CurrentUnit != 0) {
433       /* See OpenGL 1.2.1 spec, section F.2.13 */
434       _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
435       return;
436    }
437 
438    map = get_2d_map(ctx, target);
439    if (!map) {
440       _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
441       return;
442    }
443 
444    /* make copy of the control points */
445    if (type == GL_FLOAT)
446       pnts = _mesa_copy_map_points2f(target, ustride, uorder,
447                                   vstride, vorder, (GLfloat*) points);
448    else
449       pnts = _mesa_copy_map_points2d(target, ustride, uorder,
450                                   vstride, vorder, (GLdouble*) points);
451 
452 
453    FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
454    vbo_exec_update_eval_maps(ctx);
455    map->Uorder = uorder;
456    map->u1 = u1;
457    map->u2 = u2;
458    map->du = 1.0F / (u2 - u1);
459    map->Vorder = vorder;
460    map->v1 = v1;
461    map->v2 = v2;
462    map->dv = 1.0F / (v2 - v1);
463    free(map->Points);
464    map->Points = pnts;
465 }
466 
467 
468 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)469 _mesa_Map2f( GLenum target,
470              GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
471              GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
472              const GLfloat *points)
473 {
474    map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder,
475         points, GL_FLOAT);
476 }
477 
478 
479 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)480 _mesa_Map2d( GLenum target,
481              GLdouble u1, GLdouble u2, GLint ustride, GLint uorder,
482              GLdouble v1, GLdouble v2, GLint vstride, GLint vorder,
483              const GLdouble *points )
484 {
485    map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder,
486 	(GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE);
487 }
488 
489 
490 
491 void GLAPIENTRY
_mesa_GetnMapdvARB(GLenum target,GLenum query,GLsizei bufSize,GLdouble * v)492 _mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, GLdouble *v )
493 {
494    GET_CURRENT_CONTEXT(ctx);
495    struct gl_1d_map *map1d;
496    struct gl_2d_map *map2d;
497    GLint i, n;
498    GLfloat *data;
499    GLuint comps;
500    GLsizei numBytes;
501 
502    comps = _mesa_evaluator_components(target);
503    if (!comps) {
504       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" );
505       return;
506    }
507 
508    map1d = get_1d_map(ctx, target);
509    map2d = get_2d_map(ctx, target);
510    assert(map1d || map2d);
511 
512    switch (query) {
513       case GL_COEFF:
514          if (map1d) {
515             data = map1d->Points;
516             n = map1d->Order * comps;
517          }
518          else {
519             data = map2d->Points;
520             n = map2d->Uorder * map2d->Vorder * comps;
521          }
522 	 if (data) {
523             numBytes = n * sizeof *v;
524             if (bufSize < numBytes)
525                goto overflow;
526 	    for (i=0;i<n;i++) {
527 	       v[i] = data[i];
528 	    }
529 	 }
530          break;
531       case GL_ORDER:
532          if (map1d) {
533             numBytes = 1 * sizeof *v;
534             if (bufSize < numBytes)
535                goto overflow;
536             v[0] = (GLdouble) map1d->Order;
537          }
538          else {
539             numBytes = 2 * sizeof *v;
540             if (bufSize < numBytes)
541                goto overflow;
542             v[0] = (GLdouble) map2d->Uorder;
543             v[1] = (GLdouble) map2d->Vorder;
544          }
545          break;
546       case GL_DOMAIN:
547          if (map1d) {
548             numBytes = 2 * sizeof *v;
549             if (bufSize < numBytes)
550               goto overflow;
551             v[0] = (GLdouble) map1d->u1;
552             v[1] = (GLdouble) map1d->u2;
553          }
554          else {
555             numBytes = 4 * sizeof *v;
556             if (bufSize < numBytes)
557                goto overflow;
558             v[0] = (GLdouble) map2d->u1;
559             v[1] = (GLdouble) map2d->u2;
560             v[2] = (GLdouble) map2d->v1;
561             v[3] = (GLdouble) map2d->v2;
562          }
563          break;
564       default:
565          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" );
566    }
567    return;
568 
569 overflow:
570    _mesa_error( ctx, GL_INVALID_OPERATION,
571                "glGetnMapdvARB(out of bounds: bufSize is %d,"
572                " but %d bytes are required)", bufSize, numBytes );
573 }
574 
575 void GLAPIENTRY
_mesa_GetMapdv(GLenum target,GLenum query,GLdouble * v)576 _mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
577 {
578    _mesa_GetnMapdvARB(target, query, INT_MAX, v);
579 }
580 
581 void GLAPIENTRY
_mesa_GetnMapfvARB(GLenum target,GLenum query,GLsizei bufSize,GLfloat * v)582 _mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v )
583 {
584    GET_CURRENT_CONTEXT(ctx);
585    struct gl_1d_map *map1d;
586    struct gl_2d_map *map2d;
587    GLint i, n;
588    GLfloat *data;
589    GLuint comps;
590    GLsizei numBytes;
591 
592    comps = _mesa_evaluator_components(target);
593    if (!comps) {
594       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" );
595       return;
596    }
597 
598    map1d = get_1d_map(ctx, target);
599    map2d = get_2d_map(ctx, target);
600    assert(map1d || map2d);
601 
602    switch (query) {
603       case GL_COEFF:
604          if (map1d) {
605             data = map1d->Points;
606             n = map1d->Order * comps;
607          }
608          else {
609             data = map2d->Points;
610             n = map2d->Uorder * map2d->Vorder * comps;
611          }
612 	 if (data) {
613             numBytes = n * sizeof *v;
614             if (bufSize < numBytes)
615                goto overflow;
616 	    for (i=0;i<n;i++) {
617 	       v[i] = data[i];
618 	    }
619 	 }
620          break;
621       case GL_ORDER:
622          if (map1d) {
623             numBytes = 1 * sizeof *v;
624             if (bufSize < numBytes)
625                goto overflow;
626             v[0] = (GLfloat) map1d->Order;
627          }
628          else {
629             numBytes = 2 * sizeof *v;
630             if (bufSize < numBytes)
631                goto overflow;
632             v[0] = (GLfloat) map2d->Uorder;
633             v[1] = (GLfloat) map2d->Vorder;
634          }
635          break;
636       case GL_DOMAIN:
637          if (map1d) {
638             numBytes = 2 * sizeof *v;
639             if (bufSize < numBytes)
640                goto overflow;
641             v[0] = map1d->u1;
642             v[1] = map1d->u2;
643          }
644          else {
645             numBytes = 4 * sizeof *v;
646             if (bufSize < numBytes)
647                goto overflow;
648             v[0] = map2d->u1;
649             v[1] = map2d->u2;
650             v[2] = map2d->v1;
651             v[3] = map2d->v2;
652          }
653          break;
654       default:
655          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" );
656    }
657    return;
658 
659 overflow:
660    _mesa_error( ctx, GL_INVALID_OPERATION,
661                "glGetnMapfvARB(out of bounds: bufSize is %d,"
662                " but %d bytes are required)", bufSize, numBytes );
663 }
664 
665 
666 void GLAPIENTRY
_mesa_GetMapfv(GLenum target,GLenum query,GLfloat * v)667 _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
668 {
669    _mesa_GetnMapfvARB(target, query, INT_MAX, v);
670 }
671 
672 
673 void GLAPIENTRY
_mesa_GetnMapivARB(GLenum target,GLenum query,GLsizei bufSize,GLint * v)674 _mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v )
675 {
676    GET_CURRENT_CONTEXT(ctx);
677    struct gl_1d_map *map1d;
678    struct gl_2d_map *map2d;
679    GLuint i, n;
680    GLfloat *data;
681    GLuint comps;
682    GLsizei numBytes;
683 
684    comps = _mesa_evaluator_components(target);
685    if (!comps) {
686       _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" );
687       return;
688    }
689 
690    map1d = get_1d_map(ctx, target);
691    map2d = get_2d_map(ctx, target);
692    assert(map1d || map2d);
693 
694    switch (query) {
695       case GL_COEFF:
696          if (map1d) {
697             data = map1d->Points;
698             n = map1d->Order * comps;
699          }
700          else {
701             data = map2d->Points;
702             n = map2d->Uorder * map2d->Vorder * comps;
703          }
704 	 if (data) {
705             numBytes = n * sizeof *v;
706             if (bufSize < numBytes)
707                goto overflow;
708 	    for (i=0;i<n;i++) {
709 	       v[i] = lroundf(data[i]);
710 	    }
711 	 }
712          break;
713       case GL_ORDER:
714          if (map1d) {
715             numBytes = 1 * sizeof *v;
716             if (bufSize < numBytes)
717                goto overflow;
718             v[0] = map1d->Order;
719          }
720          else {
721             numBytes = 2 * sizeof *v;
722             if (bufSize < numBytes)
723                goto overflow;
724             v[0] = map2d->Uorder;
725             v[1] = map2d->Vorder;
726          }
727          break;
728       case GL_DOMAIN:
729          if (map1d) {
730             numBytes = 2 * sizeof *v;
731             if (bufSize < numBytes)
732                goto overflow;
733             v[0] = lroundf(map1d->u1);
734             v[1] = lroundf(map1d->u2);
735          }
736          else {
737             numBytes = 4 * sizeof *v;
738             if (bufSize < numBytes)
739                goto overflow;
740             v[0] = lroundf(map2d->u1);
741             v[1] = lroundf(map2d->u2);
742             v[2] = lroundf(map2d->v1);
743             v[3] = lroundf(map2d->v2);
744          }
745          break;
746       default:
747          _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" );
748    }
749    return;
750 
751 overflow:
752    _mesa_error( ctx, GL_INVALID_OPERATION,
753                "glGetnMapivARB(out of bounds: bufSize is %d,"
754                " but %d bytes are required)", bufSize, numBytes );
755 }
756 
757 
758 void GLAPIENTRY
_mesa_GetMapiv(GLenum target,GLenum query,GLint * v)759 _mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
760 {
761    _mesa_GetnMapivARB(target, query, INT_MAX, v);
762 }
763 
764 
765 void GLAPIENTRY
_mesa_MapGrid1f(GLint un,GLfloat u1,GLfloat u2)766 _mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 )
767 {
768    GET_CURRENT_CONTEXT(ctx);
769 
770    if (un<1) {
771       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" );
772       return;
773    }
774    FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
775    vbo_exec_update_eval_maps(ctx);
776    ctx->Eval.MapGrid1un = un;
777    ctx->Eval.MapGrid1u1 = u1;
778    ctx->Eval.MapGrid1u2 = u2;
779    ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
780 }
781 
782 
783 void GLAPIENTRY
_mesa_MapGrid1d(GLint un,GLdouble u1,GLdouble u2)784 _mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
785 {
786    _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
787 }
788 
789 
790 void GLAPIENTRY
_mesa_MapGrid2f(GLint un,GLfloat u1,GLfloat u2,GLint vn,GLfloat v1,GLfloat v2)791 _mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
792                  GLint vn, GLfloat v1, GLfloat v2 )
793 {
794    GET_CURRENT_CONTEXT(ctx);
795 
796    if (un<1) {
797       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
798       return;
799    }
800    if (vn<1) {
801       _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
802       return;
803    }
804 
805    FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT);
806    vbo_exec_update_eval_maps(ctx);
807    ctx->Eval.MapGrid2un = un;
808    ctx->Eval.MapGrid2u1 = u1;
809    ctx->Eval.MapGrid2u2 = u2;
810    ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
811    ctx->Eval.MapGrid2vn = vn;
812    ctx->Eval.MapGrid2v1 = v1;
813    ctx->Eval.MapGrid2v2 = v2;
814    ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
815 }
816 
817 
818 void GLAPIENTRY
_mesa_MapGrid2d(GLint un,GLdouble u1,GLdouble u2,GLint vn,GLdouble v1,GLdouble v2)819 _mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
820                  GLint vn, GLdouble v1, GLdouble v2 )
821 {
822    _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
823 		    vn, (GLfloat) v1, (GLfloat) v2 );
824 }
825 
826 
827 /**********************************************************************/
828 /*****                      Initialization                        *****/
829 /**********************************************************************/
830 
831 /**
832  * Initialize a 1-D evaluator map.
833  */
834 static void
init_1d_map(struct gl_1d_map * map,int n,const float * initial)835 init_1d_map( struct gl_1d_map *map, int n, const float *initial )
836 {
837    map->Order = 1;
838    map->u1 = 0.0;
839    map->u2 = 1.0;
840    map->Points = malloc(n * sizeof(GLfloat));
841    if (map->Points) {
842       GLint i;
843       for (i=0;i<n;i++)
844          map->Points[i] = initial[i];
845    }
846 }
847 
848 
849 /**
850  * Initialize a 2-D evaluator map
851  */
852 static void
init_2d_map(struct gl_2d_map * map,int n,const float * initial)853 init_2d_map( struct gl_2d_map *map, int n, const float *initial )
854 {
855    map->Uorder = 1;
856    map->Vorder = 1;
857    map->u1 = 0.0;
858    map->u2 = 1.0;
859    map->v1 = 0.0;
860    map->v2 = 1.0;
861    map->Points = malloc(n * sizeof(GLfloat));
862    if (map->Points) {
863       GLint i;
864       for (i=0;i<n;i++)
865          map->Points[i] = initial[i];
866    }
867 }
868 
869 
_mesa_init_eval(struct gl_context * ctx)870 void _mesa_init_eval( struct gl_context *ctx )
871 {
872    /* Evaluators group */
873    ctx->Eval.Map1Color4 = GL_FALSE;
874    ctx->Eval.Map1Index = GL_FALSE;
875    ctx->Eval.Map1Normal = GL_FALSE;
876    ctx->Eval.Map1TextureCoord1 = GL_FALSE;
877    ctx->Eval.Map1TextureCoord2 = GL_FALSE;
878    ctx->Eval.Map1TextureCoord3 = GL_FALSE;
879    ctx->Eval.Map1TextureCoord4 = GL_FALSE;
880    ctx->Eval.Map1Vertex3 = GL_FALSE;
881    ctx->Eval.Map1Vertex4 = GL_FALSE;
882    ctx->Eval.Map2Color4 = GL_FALSE;
883    ctx->Eval.Map2Index = GL_FALSE;
884    ctx->Eval.Map2Normal = GL_FALSE;
885    ctx->Eval.Map2TextureCoord1 = GL_FALSE;
886    ctx->Eval.Map2TextureCoord2 = GL_FALSE;
887    ctx->Eval.Map2TextureCoord3 = GL_FALSE;
888    ctx->Eval.Map2TextureCoord4 = GL_FALSE;
889    ctx->Eval.Map2Vertex3 = GL_FALSE;
890    ctx->Eval.Map2Vertex4 = GL_FALSE;
891    ctx->Eval.AutoNormal = GL_FALSE;
892    ctx->Eval.MapGrid1un = 1;
893    ctx->Eval.MapGrid1u1 = 0.0;
894    ctx->Eval.MapGrid1u2 = 1.0;
895    ctx->Eval.MapGrid2un = 1;
896    ctx->Eval.MapGrid2vn = 1;
897    ctx->Eval.MapGrid2u1 = 0.0;
898    ctx->Eval.MapGrid2u2 = 1.0;
899    ctx->Eval.MapGrid2v1 = 0.0;
900    ctx->Eval.MapGrid2v2 = 1.0;
901 
902    /* Evaluator data */
903    {
904       static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
905       static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
906       static GLfloat index[1] = { 1.0 };
907       static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
908       static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
909 
910       init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
911       init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
912       init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
913       init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
914       init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
915       init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
916       init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
917       init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
918       init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
919 
920       init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
921       init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
922       init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
923       init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
924       init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
925       init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
926       init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
927       init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
928       init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
929    }
930 }
931 
932 
_mesa_free_eval_data(struct gl_context * ctx)933 void _mesa_free_eval_data( struct gl_context *ctx )
934 {
935    /* Free evaluator data */
936    free(ctx->EvalMap.Map1Vertex3.Points);
937    free(ctx->EvalMap.Map1Vertex4.Points);
938    free(ctx->EvalMap.Map1Index.Points);
939    free(ctx->EvalMap.Map1Color4.Points);
940    free(ctx->EvalMap.Map1Normal.Points);
941    free(ctx->EvalMap.Map1Texture1.Points);
942    free(ctx->EvalMap.Map1Texture2.Points);
943    free(ctx->EvalMap.Map1Texture3.Points);
944    free(ctx->EvalMap.Map1Texture4.Points);
945 
946    free(ctx->EvalMap.Map2Vertex3.Points);
947    free(ctx->EvalMap.Map2Vertex4.Points);
948    free(ctx->EvalMap.Map2Index.Points);
949    free(ctx->EvalMap.Map2Color4.Points);
950    free(ctx->EvalMap.Map2Normal.Points);
951    free(ctx->EvalMap.Map2Texture1.Points);
952    free(ctx->EvalMap.Map2Texture2.Points);
953    free(ctx->EvalMap.Map2Texture3.Points);
954    free(ctx->EvalMap.Map2Texture4.Points);
955 }
956