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