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