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#include "api_exec_decl.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 */ 54GLuint _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 */ 85static struct gl_1d_map * 86get_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 */ 116static struct gl_2d_map * 117get_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 */ 156GLfloat *_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 */ 180GLfloat *_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 */ 211GLfloat *_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 */ 254GLfloat *_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 */ 303static void 304map1(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, 0, GL_EVAL_BIT); 358 vbo_exec_update_eval_maps(ctx); 359 map->Order = uorder; 360 map->u1 = u1; 361 map->u2 = u2; 362 map->du = 1.0F / (u2 - u1); 363 free(map->Points); 364 map->Points = pnts; 365} 366 367 368 369void GLAPIENTRY 370_mesa_Map1f( GLenum target, GLfloat u1, GLfloat u2, GLint stride, 371 GLint order, const GLfloat *points ) 372{ 373 map1(target, u1, u2, stride, order, points, GL_FLOAT); 374} 375 376 377void GLAPIENTRY 378_mesa_Map1d( GLenum target, GLdouble u1, GLdouble u2, GLint stride, 379 GLint order, const GLdouble *points ) 380{ 381 map1(target, (GLfloat) u1, (GLfloat) u2, stride, order, points, GL_DOUBLE); 382} 383 384 385static void 386map2( GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, 387 GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, 388 const GLvoid *points, GLenum type ) 389{ 390 GET_CURRENT_CONTEXT(ctx); 391 GLint k; 392 GLfloat *pnts; 393 struct gl_2d_map *map = NULL; 394 395 assert(type == GL_FLOAT || type == GL_DOUBLE); 396 397 if (u1==u2) { 398 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(u1,u2)" ); 399 return; 400 } 401 402 if (v1==v2) { 403 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(v1,v2)" ); 404 return; 405 } 406 407 if (uorder<1 || uorder>MAX_EVAL_ORDER) { 408 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(uorder)" ); 409 return; 410 } 411 412 if (vorder<1 || vorder>MAX_EVAL_ORDER) { 413 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vorder)" ); 414 return; 415 } 416 417 k = _mesa_evaluator_components( target ); 418 if (k==0) { 419 _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" ); 420 return; 421 } 422 423 if (ustride < k) { 424 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(ustride)" ); 425 return; 426 } 427 if (vstride < k) { 428 _mesa_error( ctx, GL_INVALID_VALUE, "glMap2(vstride)" ); 429 return; 430 } 431 432 if (ctx->Texture.CurrentUnit != 0) { 433 /* See OpenGL 1.2.1 spec, section F.2.13 */ 434 _mesa_error( ctx, GL_INVALID_OPERATION, "glMap2(ACTIVE_TEXTURE != 0)" ); 435 return; 436 } 437 438 map = get_2d_map(ctx, target); 439 if (!map) { 440 _mesa_error( ctx, GL_INVALID_ENUM, "glMap2(target)" ); 441 return; 442 } 443 444 /* make copy of the control points */ 445 if (type == GL_FLOAT) 446 pnts = _mesa_copy_map_points2f(target, ustride, uorder, 447 vstride, vorder, (GLfloat*) points); 448 else 449 pnts = _mesa_copy_map_points2d(target, ustride, uorder, 450 vstride, vorder, (GLdouble*) points); 451 452 453 FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT); 454 vbo_exec_update_eval_maps(ctx); 455 map->Uorder = uorder; 456 map->u1 = u1; 457 map->u2 = u2; 458 map->du = 1.0F / (u2 - u1); 459 map->Vorder = vorder; 460 map->v1 = v1; 461 map->v2 = v2; 462 map->dv = 1.0F / (v2 - v1); 463 free(map->Points); 464 map->Points = pnts; 465} 466 467 468void GLAPIENTRY 469_mesa_Map2f( GLenum target, 470 GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, 471 GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, 472 const GLfloat *points) 473{ 474 map2(target, u1, u2, ustride, uorder, v1, v2, vstride, vorder, 475 points, GL_FLOAT); 476} 477 478 479void GLAPIENTRY 480_mesa_Map2d( GLenum target, 481 GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, 482 GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, 483 const GLdouble *points ) 484{ 485 map2(target, (GLfloat) u1, (GLfloat) u2, ustride, uorder, 486 (GLfloat) v1, (GLfloat) v2, vstride, vorder, points, GL_DOUBLE); 487} 488 489 490 491void GLAPIENTRY 492_mesa_GetnMapdvARB( GLenum target, GLenum query, GLsizei bufSize, GLdouble *v ) 493{ 494 GET_CURRENT_CONTEXT(ctx); 495 struct gl_1d_map *map1d; 496 struct gl_2d_map *map2d; 497 GLint i, n; 498 GLfloat *data; 499 GLuint comps; 500 GLsizei numBytes; 501 502 comps = _mesa_evaluator_components(target); 503 if (!comps) { 504 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(target)" ); 505 return; 506 } 507 508 map1d = get_1d_map(ctx, target); 509 map2d = get_2d_map(ctx, target); 510 assert(map1d || map2d); 511 512 switch (query) { 513 case GL_COEFF: 514 if (map1d) { 515 data = map1d->Points; 516 n = map1d->Order * comps; 517 } 518 else { 519 data = map2d->Points; 520 n = map2d->Uorder * map2d->Vorder * comps; 521 } 522 if (data) { 523 numBytes = n * sizeof *v; 524 if (bufSize < numBytes) 525 goto overflow; 526 for (i=0;i<n;i++) { 527 v[i] = data[i]; 528 } 529 } 530 break; 531 case GL_ORDER: 532 if (map1d) { 533 numBytes = 1 * sizeof *v; 534 if (bufSize < numBytes) 535 goto overflow; 536 v[0] = (GLdouble) map1d->Order; 537 } 538 else { 539 numBytes = 2 * sizeof *v; 540 if (bufSize < numBytes) 541 goto overflow; 542 v[0] = (GLdouble) map2d->Uorder; 543 v[1] = (GLdouble) map2d->Vorder; 544 } 545 break; 546 case GL_DOMAIN: 547 if (map1d) { 548 numBytes = 2 * sizeof *v; 549 if (bufSize < numBytes) 550 goto overflow; 551 v[0] = (GLdouble) map1d->u1; 552 v[1] = (GLdouble) map1d->u2; 553 } 554 else { 555 numBytes = 4 * sizeof *v; 556 if (bufSize < numBytes) 557 goto overflow; 558 v[0] = (GLdouble) map2d->u1; 559 v[1] = (GLdouble) map2d->u2; 560 v[2] = (GLdouble) map2d->v1; 561 v[3] = (GLdouble) map2d->v2; 562 } 563 break; 564 default: 565 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapdv(query)" ); 566 } 567 return; 568 569overflow: 570 _mesa_error( ctx, GL_INVALID_OPERATION, 571 "glGetnMapdvARB(out of bounds: bufSize is %d," 572 " but %d bytes are required)", bufSize, numBytes ); 573} 574 575void GLAPIENTRY 576_mesa_GetMapdv( GLenum target, GLenum query, GLdouble *v ) 577{ 578 _mesa_GetnMapdvARB(target, query, INT_MAX, v); 579} 580 581void GLAPIENTRY 582_mesa_GetnMapfvARB( GLenum target, GLenum query, GLsizei bufSize, GLfloat *v ) 583{ 584 GET_CURRENT_CONTEXT(ctx); 585 struct gl_1d_map *map1d; 586 struct gl_2d_map *map2d; 587 GLint i, n; 588 GLfloat *data; 589 GLuint comps; 590 GLsizei numBytes; 591 592 comps = _mesa_evaluator_components(target); 593 if (!comps) { 594 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(target)" ); 595 return; 596 } 597 598 map1d = get_1d_map(ctx, target); 599 map2d = get_2d_map(ctx, target); 600 assert(map1d || map2d); 601 602 switch (query) { 603 case GL_COEFF: 604 if (map1d) { 605 data = map1d->Points; 606 n = map1d->Order * comps; 607 } 608 else { 609 data = map2d->Points; 610 n = map2d->Uorder * map2d->Vorder * comps; 611 } 612 if (data) { 613 numBytes = n * sizeof *v; 614 if (bufSize < numBytes) 615 goto overflow; 616 for (i=0;i<n;i++) { 617 v[i] = data[i]; 618 } 619 } 620 break; 621 case GL_ORDER: 622 if (map1d) { 623 numBytes = 1 * sizeof *v; 624 if (bufSize < numBytes) 625 goto overflow; 626 v[0] = (GLfloat) map1d->Order; 627 } 628 else { 629 numBytes = 2 * sizeof *v; 630 if (bufSize < numBytes) 631 goto overflow; 632 v[0] = (GLfloat) map2d->Uorder; 633 v[1] = (GLfloat) map2d->Vorder; 634 } 635 break; 636 case GL_DOMAIN: 637 if (map1d) { 638 numBytes = 2 * sizeof *v; 639 if (bufSize < numBytes) 640 goto overflow; 641 v[0] = map1d->u1; 642 v[1] = map1d->u2; 643 } 644 else { 645 numBytes = 4 * sizeof *v; 646 if (bufSize < numBytes) 647 goto overflow; 648 v[0] = map2d->u1; 649 v[1] = map2d->u2; 650 v[2] = map2d->v1; 651 v[3] = map2d->v2; 652 } 653 break; 654 default: 655 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapfv(query)" ); 656 } 657 return; 658 659overflow: 660 _mesa_error( ctx, GL_INVALID_OPERATION, 661 "glGetnMapfvARB(out of bounds: bufSize is %d," 662 " but %d bytes are required)", bufSize, numBytes ); 663} 664 665 666void GLAPIENTRY 667_mesa_GetMapfv( GLenum target, GLenum query, GLfloat *v ) 668{ 669 _mesa_GetnMapfvARB(target, query, INT_MAX, v); 670} 671 672 673void GLAPIENTRY 674_mesa_GetnMapivARB( GLenum target, GLenum query, GLsizei bufSize, GLint *v ) 675{ 676 GET_CURRENT_CONTEXT(ctx); 677 struct gl_1d_map *map1d; 678 struct gl_2d_map *map2d; 679 GLuint i, n; 680 GLfloat *data; 681 GLuint comps; 682 GLsizei numBytes; 683 684 comps = _mesa_evaluator_components(target); 685 if (!comps) { 686 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(target)" ); 687 return; 688 } 689 690 map1d = get_1d_map(ctx, target); 691 map2d = get_2d_map(ctx, target); 692 assert(map1d || map2d); 693 694 switch (query) { 695 case GL_COEFF: 696 if (map1d) { 697 data = map1d->Points; 698 n = map1d->Order * comps; 699 } 700 else { 701 data = map2d->Points; 702 n = map2d->Uorder * map2d->Vorder * comps; 703 } 704 if (data) { 705 numBytes = n * sizeof *v; 706 if (bufSize < numBytes) 707 goto overflow; 708 for (i=0;i<n;i++) { 709 v[i] = lroundf(data[i]); 710 } 711 } 712 break; 713 case GL_ORDER: 714 if (map1d) { 715 numBytes = 1 * sizeof *v; 716 if (bufSize < numBytes) 717 goto overflow; 718 v[0] = map1d->Order; 719 } 720 else { 721 numBytes = 2 * sizeof *v; 722 if (bufSize < numBytes) 723 goto overflow; 724 v[0] = map2d->Uorder; 725 v[1] = map2d->Vorder; 726 } 727 break; 728 case GL_DOMAIN: 729 if (map1d) { 730 numBytes = 2 * sizeof *v; 731 if (bufSize < numBytes) 732 goto overflow; 733 v[0] = lroundf(map1d->u1); 734 v[1] = lroundf(map1d->u2); 735 } 736 else { 737 numBytes = 4 * sizeof *v; 738 if (bufSize < numBytes) 739 goto overflow; 740 v[0] = lroundf(map2d->u1); 741 v[1] = lroundf(map2d->u2); 742 v[2] = lroundf(map2d->v1); 743 v[3] = lroundf(map2d->v2); 744 } 745 break; 746 default: 747 _mesa_error( ctx, GL_INVALID_ENUM, "glGetMapiv(query)" ); 748 } 749 return; 750 751overflow: 752 _mesa_error( ctx, GL_INVALID_OPERATION, 753 "glGetnMapivARB(out of bounds: bufSize is %d," 754 " but %d bytes are required)", bufSize, numBytes ); 755} 756 757 758void GLAPIENTRY 759_mesa_GetMapiv( GLenum target, GLenum query, GLint *v ) 760{ 761 _mesa_GetnMapivARB(target, query, INT_MAX, v); 762} 763 764 765void GLAPIENTRY 766_mesa_MapGrid1f( GLint un, GLfloat u1, GLfloat u2 ) 767{ 768 GET_CURRENT_CONTEXT(ctx); 769 770 if (un<1) { 771 _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid1f" ); 772 return; 773 } 774 FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT); 775 vbo_exec_update_eval_maps(ctx); 776 ctx->Eval.MapGrid1un = un; 777 ctx->Eval.MapGrid1u1 = u1; 778 ctx->Eval.MapGrid1u2 = u2; 779 ctx->Eval.MapGrid1du = (u2 - u1) / (GLfloat) un; 780} 781 782 783void GLAPIENTRY 784_mesa_MapGrid1d( GLint un, GLdouble u1, GLdouble u2 ) 785{ 786 _mesa_MapGrid1f( un, (GLfloat) u1, (GLfloat) u2 ); 787} 788 789 790void GLAPIENTRY 791_mesa_MapGrid2f( GLint un, GLfloat u1, GLfloat u2, 792 GLint vn, GLfloat v1, GLfloat v2 ) 793{ 794 GET_CURRENT_CONTEXT(ctx); 795 796 if (un<1) { 797 _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(un)" ); 798 return; 799 } 800 if (vn<1) { 801 _mesa_error( ctx, GL_INVALID_VALUE, "glMapGrid2f(vn)" ); 802 return; 803 } 804 805 FLUSH_VERTICES(ctx, 0, GL_EVAL_BIT); 806 vbo_exec_update_eval_maps(ctx); 807 ctx->Eval.MapGrid2un = un; 808 ctx->Eval.MapGrid2u1 = u1; 809 ctx->Eval.MapGrid2u2 = u2; 810 ctx->Eval.MapGrid2du = (u2 - u1) / (GLfloat) un; 811 ctx->Eval.MapGrid2vn = vn; 812 ctx->Eval.MapGrid2v1 = v1; 813 ctx->Eval.MapGrid2v2 = v2; 814 ctx->Eval.MapGrid2dv = (v2 - v1) / (GLfloat) vn; 815} 816 817 818void GLAPIENTRY 819_mesa_MapGrid2d( GLint un, GLdouble u1, GLdouble u2, 820 GLint vn, GLdouble v1, GLdouble v2 ) 821{ 822 _mesa_MapGrid2f( un, (GLfloat) u1, (GLfloat) u2, 823 vn, (GLfloat) v1, (GLfloat) v2 ); 824} 825 826 827/**********************************************************************/ 828/***** Initialization *****/ 829/**********************************************************************/ 830 831/** 832 * Initialize a 1-D evaluator map. 833 */ 834static void 835init_1d_map( struct gl_1d_map *map, int n, const float *initial ) 836{ 837 map->Order = 1; 838 map->u1 = 0.0; 839 map->u2 = 1.0; 840 map->Points = malloc(n * sizeof(GLfloat)); 841 if (map->Points) { 842 GLint i; 843 for (i=0;i<n;i++) 844 map->Points[i] = initial[i]; 845 } 846} 847 848 849/** 850 * Initialize a 2-D evaluator map 851 */ 852static void 853init_2d_map( struct gl_2d_map *map, int n, const float *initial ) 854{ 855 map->Uorder = 1; 856 map->Vorder = 1; 857 map->u1 = 0.0; 858 map->u2 = 1.0; 859 map->v1 = 0.0; 860 map->v2 = 1.0; 861 map->Points = malloc(n * sizeof(GLfloat)); 862 if (map->Points) { 863 GLint i; 864 for (i=0;i<n;i++) 865 map->Points[i] = initial[i]; 866 } 867} 868 869 870void _mesa_init_eval( struct gl_context *ctx ) 871{ 872 /* Evaluators group */ 873 ctx->Eval.Map1Color4 = GL_FALSE; 874 ctx->Eval.Map1Index = GL_FALSE; 875 ctx->Eval.Map1Normal = GL_FALSE; 876 ctx->Eval.Map1TextureCoord1 = GL_FALSE; 877 ctx->Eval.Map1TextureCoord2 = GL_FALSE; 878 ctx->Eval.Map1TextureCoord3 = GL_FALSE; 879 ctx->Eval.Map1TextureCoord4 = GL_FALSE; 880 ctx->Eval.Map1Vertex3 = GL_FALSE; 881 ctx->Eval.Map1Vertex4 = GL_FALSE; 882 ctx->Eval.Map2Color4 = GL_FALSE; 883 ctx->Eval.Map2Index = GL_FALSE; 884 ctx->Eval.Map2Normal = GL_FALSE; 885 ctx->Eval.Map2TextureCoord1 = GL_FALSE; 886 ctx->Eval.Map2TextureCoord2 = GL_FALSE; 887 ctx->Eval.Map2TextureCoord3 = GL_FALSE; 888 ctx->Eval.Map2TextureCoord4 = GL_FALSE; 889 ctx->Eval.Map2Vertex3 = GL_FALSE; 890 ctx->Eval.Map2Vertex4 = GL_FALSE; 891 ctx->Eval.AutoNormal = GL_FALSE; 892 ctx->Eval.MapGrid1un = 1; 893 ctx->Eval.MapGrid1u1 = 0.0; 894 ctx->Eval.MapGrid1u2 = 1.0; 895 ctx->Eval.MapGrid2un = 1; 896 ctx->Eval.MapGrid2vn = 1; 897 ctx->Eval.MapGrid2u1 = 0.0; 898 ctx->Eval.MapGrid2u2 = 1.0; 899 ctx->Eval.MapGrid2v1 = 0.0; 900 ctx->Eval.MapGrid2v2 = 1.0; 901 902 /* Evaluator data */ 903 { 904 static GLfloat vertex[4] = { 0.0, 0.0, 0.0, 1.0 }; 905 static GLfloat normal[3] = { 0.0, 0.0, 1.0 }; 906 static GLfloat index[1] = { 1.0 }; 907 static GLfloat color[4] = { 1.0, 1.0, 1.0, 1.0 }; 908 static GLfloat texcoord[4] = { 0.0, 0.0, 0.0, 1.0 }; 909 910 init_1d_map( &ctx->EvalMap.Map1Vertex3, 3, vertex ); 911 init_1d_map( &ctx->EvalMap.Map1Vertex4, 4, vertex ); 912 init_1d_map( &ctx->EvalMap.Map1Index, 1, index ); 913 init_1d_map( &ctx->EvalMap.Map1Color4, 4, color ); 914 init_1d_map( &ctx->EvalMap.Map1Normal, 3, normal ); 915 init_1d_map( &ctx->EvalMap.Map1Texture1, 1, texcoord ); 916 init_1d_map( &ctx->EvalMap.Map1Texture2, 2, texcoord ); 917 init_1d_map( &ctx->EvalMap.Map1Texture3, 3, texcoord ); 918 init_1d_map( &ctx->EvalMap.Map1Texture4, 4, texcoord ); 919 920 init_2d_map( &ctx->EvalMap.Map2Vertex3, 3, vertex ); 921 init_2d_map( &ctx->EvalMap.Map2Vertex4, 4, vertex ); 922 init_2d_map( &ctx->EvalMap.Map2Index, 1, index ); 923 init_2d_map( &ctx->EvalMap.Map2Color4, 4, color ); 924 init_2d_map( &ctx->EvalMap.Map2Normal, 3, normal ); 925 init_2d_map( &ctx->EvalMap.Map2Texture1, 1, texcoord ); 926 init_2d_map( &ctx->EvalMap.Map2Texture2, 2, texcoord ); 927 init_2d_map( &ctx->EvalMap.Map2Texture3, 3, texcoord ); 928 init_2d_map( &ctx->EvalMap.Map2Texture4, 4, texcoord ); 929 } 930} 931 932 933void _mesa_free_eval_data( struct gl_context *ctx ) 934{ 935 /* Free evaluator data */ 936 free(ctx->EvalMap.Map1Vertex3.Points); 937 free(ctx->EvalMap.Map1Vertex4.Points); 938 free(ctx->EvalMap.Map1Index.Points); 939 free(ctx->EvalMap.Map1Color4.Points); 940 free(ctx->EvalMap.Map1Normal.Points); 941 free(ctx->EvalMap.Map1Texture1.Points); 942 free(ctx->EvalMap.Map1Texture2.Points); 943 free(ctx->EvalMap.Map1Texture3.Points); 944 free(ctx->EvalMap.Map1Texture4.Points); 945 946 free(ctx->EvalMap.Map2Vertex3.Points); 947 free(ctx->EvalMap.Map2Vertex4.Points); 948 free(ctx->EvalMap.Map2Index.Points); 949 free(ctx->EvalMap.Map2Color4.Points); 950 free(ctx->EvalMap.Map2Normal.Points); 951 free(ctx->EvalMap.Map2Texture1.Points); 952 free(ctx->EvalMap.Map2Texture2.Points); 953 free(ctx->EvalMap.Map2Texture3.Points); 954 free(ctx->EvalMap.Map2Texture4.Points); 955} 956