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