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