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 (at) cip.informatik.uni-erlangen.de) and 30 * Volker Weiss (vrweiss (at) 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 */ 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 * 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 * 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 574 _mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v ) 575 { 576 _mesa_GetnMapdvARB(target, query, INT_MAX, v); 577 } 578 579 void GLAPIENTRY 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 665 _mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v ) 666 { 667 _mesa_GetnMapfvARB(target, query, INT_MAX, v); 668 } 669 670 671 void GLAPIENTRY 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 757 _mesa_GetMapiv( GLenum target, GLenum query, GLint *v ) 758 { 759 _mesa_GetnMapivARB(target, query, INT_MAX, v); 760 } 761 762 763 void GLAPIENTRY 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 781 _mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 ) 782 { 783 _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 ); 784 } 785 786 787 void GLAPIENTRY 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 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 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 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 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 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 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