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