mesa: Restore 78-column wrapping of license text in C-style comments.
[mesa.git] / src / mesa / main / eval.c
1
2 /*
3 * Mesa 3-D graphics library
4 * Version: 5.1
5 *
6 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 * OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /*
29 * eval.c was written by
30 * Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
31 * Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
32 *
33 * My original implementation of evaluators was simplistic and didn't
34 * compute surface normal vectors properly. Bernd and Volker applied
35 * used more sophisticated methods to get better results.
36 *
37 * Thanks guys!
38 */
39
40
41 #include "glheader.h"
42 #include "imports.h"
43 #include "colormac.h"
44 #include "context.h"
45 #include "eval.h"
46 #include "macros.h"
47 #include "mtypes.h"
48 #include "main/dispatch.h"
49
50
51 /*
52 * Return the number of components per control point for any type of
53 * evaluator. Return 0 if bad target.
54 * See table 5.1 in the OpenGL 1.2 spec.
55 */
56 GLuint _mesa_evaluator_components( GLenum target )
57 {
58 switch (target) {
59 case GL_MAP1_VERTEX_3: return 3;
60 case GL_MAP1_VERTEX_4: return 4;
61 case GL_MAP1_INDEX: return 1;
62 case GL_MAP1_COLOR_4: return 4;
63 case GL_MAP1_NORMAL: return 3;
64 case GL_MAP1_TEXTURE_COORD_1: return 1;
65 case GL_MAP1_TEXTURE_COORD_2: return 2;
66 case GL_MAP1_TEXTURE_COORD_3: return 3;
67 case GL_MAP1_TEXTURE_COORD_4: return 4;
68 case GL_MAP2_VERTEX_3: return 3;
69 case GL_MAP2_VERTEX_4: return 4;
70 case GL_MAP2_INDEX: return 1;
71 case GL_MAP2_COLOR_4: return 4;
72 case GL_MAP2_NORMAL: return 3;
73 case GL_MAP2_TEXTURE_COORD_1: return 1;
74 case GL_MAP2_TEXTURE_COORD_2: return 2;
75 case GL_MAP2_TEXTURE_COORD_3: return 3;
76 case GL_MAP2_TEXTURE_COORD_4: return 4;
77 default: break;
78 }
79
80 return 0;
81 }
82
83
84 /*
85 * Return pointer to the gl_1d_map struct for the named target.
86 */
87 static struct gl_1d_map *
88 get_1d_map( struct gl_context *ctx, GLenum target )
89 {
90 switch (target) {
91 case GL_MAP1_VERTEX_3:
92 return &ctx->EvalMap.Map1Vertex3;
93 case GL_MAP1_VERTEX_4:
94 return &ctx->EvalMap.Map1Vertex4;
95 case GL_MAP1_INDEX:
96 return &ctx->EvalMap.Map1Index;
97 case GL_MAP1_COLOR_4:
98 return &ctx->EvalMap.Map1Color4;
99 case GL_MAP1_NORMAL:
100 return &ctx->EvalMap.Map1Normal;
101 case GL_MAP1_TEXTURE_COORD_1:
102 return &ctx->EvalMap.Map1Texture1;
103 case GL_MAP1_TEXTURE_COORD_2:
104 return &ctx->EvalMap.Map1Texture2;
105 case GL_MAP1_TEXTURE_COORD_3:
106 return &ctx->EvalMap.Map1Texture3;
107 case GL_MAP1_TEXTURE_COORD_4:
108 return &ctx->EvalMap.Map1Texture4;
109 default:
110 return NULL;
111 }
112 }
113
114
115 /*
116 * Return pointer to the gl_2d_map struct for the named target.
117 */
118 static struct gl_2d_map *
119 get_2d_map( struct gl_context *ctx, GLenum target )
120 {
121 switch (target) {
122 case GL_MAP2_VERTEX_3:
123 return &ctx->EvalMap.Map2Vertex3;
124 case GL_MAP2_VERTEX_4:
125 return &ctx->EvalMap.Map2Vertex4;
126 case GL_MAP2_INDEX:
127 return &ctx->EvalMap.Map2Index;
128 case GL_MAP2_COLOR_4:
129 return &ctx->EvalMap.Map2Color4;
130 case GL_MAP2_NORMAL:
131 return &ctx->EvalMap.Map2Normal;
132 case GL_MAP2_TEXTURE_COORD_1:
133 return &ctx->EvalMap.Map2Texture1;
134 case GL_MAP2_TEXTURE_COORD_2:
135 return &ctx->EvalMap.Map2Texture2;
136 case GL_MAP2_TEXTURE_COORD_3:
137 return &ctx->EvalMap.Map2Texture3;
138 case GL_MAP2_TEXTURE_COORD_4:
139 return &ctx->EvalMap.Map2Texture4;
140 default:
141 return NULL;
142 }
143 }
144
145
146 /**********************************************************************/
147 /*** Copy and deallocate control points ***/
148 /**********************************************************************/
149
150
151 /*
152 * Copy 1-parametric evaluator control points from user-specified
153 * memory space to a buffer of contiguous control points.
154 * \param see glMap1f for details
155 * \return pointer to buffer of contiguous control points or NULL if out
156 * of memory.
157 */
158 GLfloat *_mesa_copy_map_points1f( GLenum target, GLint ustride, GLint uorder,
159 const GLfloat *points )
160 {
161 GLfloat *buffer, *p;
162 GLint i, k, size = _mesa_evaluator_components(target);
163
164 if (!points || !size)
165 return NULL;
166
167 buffer = malloc(uorder * size * sizeof(GLfloat));
168
169 if (buffer)
170 for (i = 0, p = buffer; i < uorder; i++, points += ustride)
171 for (k = 0; k < size; k++)
172 *p++ = points[k];
173
174 return buffer;
175 }
176
177
178
179 /*
180 * Same as above but convert doubles to floats.
181 */
182 GLfloat *_mesa_copy_map_points1d( GLenum target, GLint ustride, GLint uorder,
183 const GLdouble *points )
184 {
185 GLfloat *buffer, *p;
186 GLint i, k, size = _mesa_evaluator_components(target);
187
188 if (!points || !size)
189 return NULL;
190
191 buffer = malloc(uorder * size * sizeof(GLfloat));
192
193 if (buffer)
194 for (i = 0, p = buffer; i < uorder; i++, points += ustride)
195 for (k = 0; k < size; k++)
196 *p++ = (GLfloat) points[k];
197
198 return buffer;
199 }
200
201
202
203 /*
204 * Copy 2-parametric evaluator control points from user-specified
205 * memory space to a buffer of contiguous control points.
206 * Additional memory is allocated to be used by the horner and
207 * de Casteljau evaluation schemes.
208 *
209 * \param see glMap2f for details
210 * \return pointer to buffer of contiguous control points or NULL if out
211 * of memory.
212 */
213 GLfloat *_mesa_copy_map_points2f( GLenum target,
214 GLint ustride, GLint uorder,
215 GLint vstride, GLint vorder,
216 const GLfloat *points )
217 {
218 GLfloat *buffer, *p;
219 GLint i, j, k, size, dsize, hsize;
220 GLint uinc;
221
222 size = _mesa_evaluator_components(target);
223
224 if (!points || size==0) {
225 return NULL;
226 }
227
228 /* max(uorder, vorder) additional points are used in */
229 /* horner evaluation and uorder*vorder additional */
230 /* values are needed for de Casteljau */
231 dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
232 hsize = (uorder > vorder ? uorder : vorder)*size;
233
234 if(hsize>dsize)
235 buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
236 else
237 buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
238
239 /* compute the increment value for the u-loop */
240 uinc = ustride - vorder*vstride;
241
242 if (buffer)
243 for (i=0, p=buffer; i<uorder; i++, points += uinc)
244 for (j=0; j<vorder; j++, points += vstride)
245 for (k=0; k<size; k++)
246 *p++ = points[k];
247
248 return buffer;
249 }
250
251
252
253 /*
254 * Same as above but convert doubles to floats.
255 */
256 GLfloat *_mesa_copy_map_points2d(GLenum target,
257 GLint ustride, GLint uorder,
258 GLint vstride, GLint vorder,
259 const GLdouble *points )
260 {
261 GLfloat *buffer, *p;
262 GLint i, j, k, size, hsize, dsize;
263 GLint uinc;
264
265 size = _mesa_evaluator_components(target);
266
267 if (!points || size==0) {
268 return NULL;
269 }
270
271 /* max(uorder, vorder) additional points are used in */
272 /* horner evaluation and uorder*vorder additional */
273 /* values are needed for de Casteljau */
274 dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
275 hsize = (uorder > vorder ? uorder : vorder)*size;
276
277 if(hsize>dsize)
278 buffer = malloc((uorder*vorder*size+hsize)*sizeof(GLfloat));
279 else
280 buffer = malloc((uorder*vorder*size+dsize)*sizeof(GLfloat));
281
282 /* compute the increment value for the u-loop */
283 uinc = ustride - vorder*vstride;
284
285 if (buffer)
286 for (i=0, p=buffer; i<uorder; i++, points += uinc)
287 for (j=0; j<vorder; j++, points += vstride)
288 for (k=0; k<size; k++)
289 *p++ = (GLfloat) points[k];
290
291 return buffer;
292 }
293
294
295
296
297 /**********************************************************************/
298 /*** API entry points ***/
299 /**********************************************************************/
300
301
302 /*
303 * This does the work of glMap1[fd].
304 */
305 static void
306 map1(GLenum target, GLfloat u1, GLfloat u2, GLint ustride,
307 GLint uorder, const GLvoid *points, GLenum type )
308 {
309 GET_CURRENT_CONTEXT(ctx);
310 GLint k;
311 GLfloat *pnts;
312 struct gl_1d_map *map = NULL;
313
314 ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
315
316 if (u1 == u2) {
317 _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(u1,u2)" );
318 return;
319 }
320 if (uorder < 1 || uorder > MAX_EVAL_ORDER) {
321 _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(order)" );
322 return;
323 }
324 if (!points) {
325 _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(points)" );
326 return;
327 }
328
329 k = _mesa_evaluator_components( target );
330 if (k == 0) {
331 _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
332 return;
333 }
334
335 if (ustride < k) {
336 _mesa_error( ctx, GL_INVALID_VALUE, "glMap1(stride)" );
337 return;
338 }
339
340 if (ctx->Texture.CurrentUnit != 0) {
341 /* See OpenGL 1.2.1 spec, section F.2.13 */
342 _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
343 return;
344 }
345
346 map = get_1d_map(ctx, target);
347 if (!map) {
348 _mesa_error( ctx, GL_INVALID_ENUM, "glMap1(target)" );
349 return;
350 }
351
352 /* make copy of the control points */
353 if (type == GL_FLOAT)
354 pnts = _mesa_copy_map_points1f(target, ustride, uorder, (GLfloat*) points);
355 else
356 pnts = _mesa_copy_map_points1d(target, ustride, uorder, (GLdouble*) points);
357
358
359 FLUSH_VERTICES(ctx, _NEW_EVAL);
360 map->Order = uorder;
361 map->u1 = u1;
362 map->u2 = u2;
363 map->du = 1.0F / (u2 - u1);
364 free(map->Points);
365 map->Points = pnts;
366 }
367
368
369
370 void GLAPIENTRY
371 _mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride,
372 GLint order, const GLfloat *points )
373 {
374 map1(target, u1, u2, stride, order, points, GL_FLOAT);
375 }
376
377
378 void GLAPIENTRY
379 _mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride,
380 GLint order, const GLdouble *points )
381 {
382 map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE);
383 }
384
385
386 static void
387 map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder,
388 GLfloat v1, GLfloat v2, GLint vstride, GLint vorder,
389 const GLvoid *points, GLenum type )
390 {
391 GET_CURRENT_CONTEXT(ctx);
392 GLint k;
393 GLfloat *pnts;
394 struct gl_2d_map *map = NULL;
395
396 ASSERT(type == GL_FLOAT || type == GL_DOUBLE);
397
398 if (u1==u2) {
399 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" );
400 return;
401 }
402
403 if (v1==v2) {
404 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" );
405 return;
406 }
407
408 if (uorder<1 || uorder>MAX_EVAL_ORDER) {
409 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" );
410 return;
411 }
412
413 if (vorder<1 || vorder>MAX_EVAL_ORDER) {
414 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" );
415 return;
416 }
417
418 k = _mesa_evaluator_components( target );
419 if (k==0) {
420 _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
421 return;
422 }
423
424 if (ustride < k) {
425 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" );
426 return;
427 }
428 if (vstride < k) {
429 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" );
430 return;
431 }
432
433 if (ctx->Texture.CurrentUnit != 0) {
434 /* See OpenGL 1.2.1 spec, section F.2.13 */
435 _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" );
436 return;
437 }
438
439 map = get_2d_map(ctx, target);
440 if (!map) {
441 _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" );
442 return;
443 }
444
445 /* make copy of the control points */
446 if (type == GL_FLOAT)
447 pnts = _mesa_copy_map_points2f(target, ustride, uorder,
448 vstride, vorder, (GLfloat*) points);
449 else
450 pnts = _mesa_copy_map_points2d(target, ustride, uorder,
451 vstride, vorder, (GLdouble*) points);
452
453
454 FLUSH_VERTICES(ctx, _NEW_EVAL);
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
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
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
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
576 _mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v )
577 {
578 _mesa_GetnMapdvARB(target, query, INT_MAX, v);
579 }
580
581 void GLAPIENTRY
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
667 _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v )
668 {
669 _mesa_GetnMapfvARB(target, query, INT_MAX, v);
670 }
671
672
673 void GLAPIENTRY
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] = IROUND(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] = IROUND(map1d->u1);
734 v[1] = IROUND(map1d->u2);
735 }
736 else {
737 numBytes = 4 * sizeof *v;
738 if (bufSize < numBytes)
739 goto overflow;
740 v[0] = IROUND(map2d->u1);
741 v[1] = IROUND(map2d->u2);
742 v[2] = IROUND(map2d->v1);
743 v[3] = IROUND(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
759 _mesa_GetMapiv( GLenum target, GLenum query, GLint *v )
760 {
761 _mesa_GetnMapivARB(target, query, INT_MAX, v);
762 }
763
764
765 void GLAPIENTRY
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, _NEW_EVAL);
775 ctx->Eval.MapGrid1un = un;
776 ctx->Eval.MapGrid1u1 = u1;
777 ctx->Eval.MapGrid1u2 = u2;
778 ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un;
779 }
780
781
782 void GLAPIENTRY
783 _mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 )
784 {
785 _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 );
786 }
787
788
789 void GLAPIENTRY
790 _mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2,
791 GLint vn, GLfloat v1, GLfloat v2 )
792 {
793 GET_CURRENT_CONTEXT(ctx);
794
795 if (un<1) {
796 _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" );
797 return;
798 }
799 if (vn<1) {
800 _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" );
801 return;
802 }
803
804 FLUSH_VERTICES(ctx, _NEW_EVAL);
805 ctx->Eval.MapGrid2un = un;
806 ctx->Eval.MapGrid2u1 = u1;
807 ctx->Eval.MapGrid2u2 = u2;
808 ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un;
809 ctx->Eval.MapGrid2vn = vn;
810 ctx->Eval.MapGrid2v1 = v1;
811 ctx->Eval.MapGrid2v2 = v2;
812 ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn;
813 }
814
815
816 void GLAPIENTRY
817 _mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2,
818 GLint vn, GLdouble v1, GLdouble v2 )
819 {
820 _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2,
821 vn, (GLfloat) v1, (GLfloat) v2 );
822 }
823
824
825 void
826 _mesa_install_eval_vtxfmt(struct _glapi_table *disp,
827 const GLvertexformat *vfmt,
828 bool beginend)
829 {
830 SET_EvalCoord1f(disp, vfmt->EvalCoord1f);
831 SET_EvalCoord1fv(disp, vfmt->EvalCoord1fv);
832 SET_EvalCoord2f(disp, vfmt->EvalCoord2f);
833 SET_EvalCoord2fv(disp, vfmt->EvalCoord2fv);
834 SET_EvalPoint1(disp, vfmt->EvalPoint1);
835 SET_EvalPoint2(disp, vfmt->EvalPoint2);
836
837 /* glEvalMesh1 and glEvalMesh2 are not allowed between glBegin and glEnd.
838 */
839 if (!beginend) {
840 SET_EvalMesh1(disp, vfmt->EvalMesh1);
841 SET_EvalMesh2(disp, vfmt->EvalMesh2);
842 }
843 }
844
845
846 /**********************************************************************/
847 /***** Initialization *****/
848 /**********************************************************************/
849
850 /**
851 * Initialize a 1-D evaluator map.
852 */
853 static void
854 init_1d_map( struct gl_1d_map *map, int n, const float *initial )
855 {
856 map->Order = 1;
857 map->u1 = 0.0;
858 map->u2 = 1.0;
859 map->Points = malloc(n * sizeof(GLfloat));
860 if (map->Points) {
861 GLint i;
862 for (i=0;i<n;i++)
863 map->Points[i] = initial[i];
864 }
865 }
866
867
868 /**
869 * Initialize a 2-D evaluator map
870 */
871 static void
872 init_2d_map( struct gl_2d_map *map, int n, const float *initial )
873 {
874 map->Uorder = 1;
875 map->Vorder = 1;
876 map->u1 = 0.0;
877 map->u2 = 1.0;
878 map->v1 = 0.0;
879 map->v2 = 1.0;
880 map->Points = malloc(n * sizeof(GLfloat));
881 if (map->Points) {
882 GLint i;
883 for (i=0;i<n;i++)
884 map->Points[i] = initial[i];
885 }
886 }
887
888
889 void _mesa_init_eval( struct gl_context *ctx )
890 {
891 /* Evaluators group */
892 ctx->Eval.Map1Color4 = GL_FALSE;
893 ctx->Eval.Map1Index = GL_FALSE;
894 ctx->Eval.Map1Normal = GL_FALSE;
895 ctx->Eval.Map1TextureCoord1 = GL_FALSE;
896 ctx->Eval.Map1TextureCoord2 = GL_FALSE;
897 ctx->Eval.Map1TextureCoord3 = GL_FALSE;
898 ctx->Eval.Map1TextureCoord4 = GL_FALSE;
899 ctx->Eval.Map1Vertex3 = GL_FALSE;
900 ctx->Eval.Map1Vertex4 = GL_FALSE;
901 ctx->Eval.Map2Color4 = GL_FALSE;
902 ctx->Eval.Map2Index = GL_FALSE;
903 ctx->Eval.Map2Normal = GL_FALSE;
904 ctx->Eval.Map2TextureCoord1 = GL_FALSE;
905 ctx->Eval.Map2TextureCoord2 = GL_FALSE;
906 ctx->Eval.Map2TextureCoord3 = GL_FALSE;
907 ctx->Eval.Map2TextureCoord4 = GL_FALSE;
908 ctx->Eval.Map2Vertex3 = GL_FALSE;
909 ctx->Eval.Map2Vertex4 = GL_FALSE;
910 ctx->Eval.AutoNormal = GL_FALSE;
911 ctx->Eval.MapGrid1un = 1;
912 ctx->Eval.MapGrid1u1 = 0.0;
913 ctx->Eval.MapGrid1u2 = 1.0;
914 ctx->Eval.MapGrid2un = 1;
915 ctx->Eval.MapGrid2vn = 1;
916 ctx->Eval.MapGrid2u1 = 0.0;
917 ctx->Eval.MapGrid2u2 = 1.0;
918 ctx->Eval.MapGrid2v1 = 0.0;
919 ctx->Eval.MapGrid2v2 = 1.0;
920
921 /* Evaluator data */
922 {
923 static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 };
924 static GLfloat normal[3] = { 0.0, 0.0, 1.0 };
925 static GLfloat index[1] = { 1.0 };
926 static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 };
927 static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 };
928
929 init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex );
930 init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex );
931 init_1d_map( &ctx->EvalMap.Map1Index, 1, index );
932 init_1d_map( &ctx->EvalMap.Map1Color4, 4, color );
933 init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal );
934 init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord );
935 init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord );
936 init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord );
937 init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord );
938
939 init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex );
940 init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex );
941 init_2d_map( &ctx->EvalMap.Map2Index, 1, index );
942 init_2d_map( &ctx->EvalMap.Map2Color4, 4, color );
943 init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal );
944 init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord );
945 init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord );
946 init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord );
947 init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord );
948 }
949 }
950
951
952 void _mesa_free_eval_data( struct gl_context *ctx )
953 {
954 /* Free evaluator data */
955 free(ctx->EvalMap.Map1Vertex3.Points);
956 free(ctx->EvalMap.Map1Vertex4.Points);
957 free(ctx->EvalMap.Map1Index.Points);
958 free(ctx->EvalMap.Map1Color4.Points);
959 free(ctx->EvalMap.Map1Normal.Points);
960 free(ctx->EvalMap.Map1Texture1.Points);
961 free(ctx->EvalMap.Map1Texture2.Points);
962 free(ctx->EvalMap.Map1Texture3.Points);
963 free(ctx->EvalMap.Map1Texture4.Points);
964
965 free(ctx->EvalMap.Map2Vertex3.Points);
966 free(ctx->EvalMap.Map2Vertex4.Points);
967 free(ctx->EvalMap.Map2Index.Points);
968 free(ctx->EvalMap.Map2Color4.Points);
969 free(ctx->EvalMap.Map2Normal.Points);
970 free(ctx->EvalMap.Map2Texture1.Points);
971 free(ctx->EvalMap.Map2Texture2.Points);
972 free(ctx->EvalMap.Map2Texture3.Points);
973 free(ctx->EvalMap.Map2Texture4.Points);
974 }