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