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