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 */ 53GLuint _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 */ 84static struct gl_1d_map * 85get_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 */ 115static struct gl_2d_map * 116get_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 */ 155GLfloat *_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 */ 179GLfloat *_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 */ 210GLfloat *_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 */ 253GLfloat *_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 */ 302static void 303map1(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 368void 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 376void 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 384static void 385map2( 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 467void GLAPIENTRY 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 478void GLAPIENTRY 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 490void GLAPIENTRY 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 568overflow: 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 574void GLAPIENTRY 575_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v ) 576{ 577 _mesa_GetnMapdvARB(target, query, INT_MAX, v); 578} 579 580void GLAPIENTRY 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 658overflow: 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 665void GLAPIENTRY 666_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v ) 667{ 668 _mesa_GetnMapfvARB(target, query, INT_MAX, v); 669} 670 671 672void GLAPIENTRY 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 750overflow: 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 757void GLAPIENTRY 758_mesa_GetMapiv( GLenum target, GLenum query, GLint *v ) 759{ 760 _mesa_GetnMapivARB(target, query, INT_MAX, v); 761} 762 763 764void GLAPIENTRY 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 782void GLAPIENTRY 783_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 ) 784{ 785 _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 ); 786} 787 788 789void GLAPIENTRY 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 817void GLAPIENTRY 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 826void 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 */ 846static void 847init_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 */ 864static void 865init_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 882void _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 945void _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