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