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