1 /* 2 * Mesa 3-D graphics library 3 * Version: 6.5.2 4 * 5 * Copyright (C) 1999-2006 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 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 /** 26 * \file nvprogram.c 27 * NVIDIA vertex/fragment program state management functions. 28 * \author Brian Paul 29 */ 30 31 /* 32 * Regarding GL_NV_fragment/vertex_program, GL_NV_vertex_program1_1, etc: 33 * 34 * Portions of this software may use or implement intellectual 35 * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims 36 * any and all warranties with respect to such intellectual property, 37 * including any use thereof or modifications thereto. 38 */ 39 40 #include "main/glheader.h" 41 #include "main/context.h" 42 #include "main/hash.h" 43 #include "main/imports.h" 44 #include "main/macros.h" 45 #include "main/mtypes.h" 46 #include "main/nvprogram.h" 47 #include "program/arbprogparse.h" 48 #include "program/nvfragparse.h" 49 #include "program/nvvertparse.h" 50 #include "program/program.h" 51 #include "program/prog_instruction.h" 52 #include "program/prog_parameter.h" 53 54 55 56 /** 57 * Execute a vertex state program. 58 * \note Called from the GL API dispatcher. 59 */ 60 void GLAPIENTRY 61 _mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) 62 { 63 struct gl_vertex_program *vprog; 64 GET_CURRENT_CONTEXT(ctx); 65 ASSERT_OUTSIDE_BEGIN_END(ctx); 66 67 if (target != GL_VERTEX_STATE_PROGRAM_NV) { 68 _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV"); 69 return; 70 } 71 72 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 73 74 vprog = gl_vertex_program(_mesa_lookup_program(ctx, id)); 75 76 if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) { 77 _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV"); 78 return; 79 } 80 81 _mesa_problem(ctx, "glExecuteProgramNV() not supported"); 82 } 83 84 85 /** 86 * Determine if a set of programs is resident in hardware. 87 * \note Not compiled into display lists. 88 * \note Called from the GL API dispatcher. 89 */ 90 GLboolean GLAPIENTRY 91 _mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, 92 GLboolean *residences) 93 { 94 GLint i, j; 95 GLboolean allResident = GL_TRUE; 96 GET_CURRENT_CONTEXT(ctx); 97 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 98 99 if (n < 0) { 100 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)"); 101 return GL_FALSE; 102 } 103 104 for (i = 0; i < n; i++) { 105 const struct gl_program *prog; 106 if (ids[i] == 0) { 107 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); 108 return GL_FALSE; 109 } 110 prog = _mesa_lookup_program(ctx, ids[i]); 111 if (!prog) { 112 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); 113 return GL_FALSE; 114 } 115 if (prog->Resident) { 116 if (!allResident) 117 residences[i] = GL_TRUE; 118 } 119 else { 120 if (allResident) { 121 allResident = GL_FALSE; 122 for (j = 0; j < i; j++) 123 residences[j] = GL_TRUE; 124 } 125 residences[i] = GL_FALSE; 126 } 127 } 128 129 return allResident; 130 } 131 132 133 /** 134 * Request that a set of programs be resident in hardware. 135 * \note Called from the GL API dispatcher. 136 */ 137 void GLAPIENTRY 138 _mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids) 139 { 140 GLint i; 141 GET_CURRENT_CONTEXT(ctx); 142 ASSERT_OUTSIDE_BEGIN_END(ctx); 143 144 if (n < 0) { 145 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)"); 146 return; 147 } 148 149 /* just error checking for now */ 150 for (i = 0; i < n; i++) { 151 struct gl_program *prog; 152 153 if (ids[i] == 0) { 154 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); 155 return; 156 } 157 158 prog = _mesa_lookup_program(ctx, ids[i]); 159 if (!prog) { 160 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); 161 return; 162 } 163 164 /* XXX this is really a hardware thing we should hook out */ 165 prog->Resident = GL_TRUE; 166 } 167 } 168 169 170 /** 171 * Get a program parameter register. 172 * \note Not compiled into display lists. 173 * \note Called from the GL API dispatcher. 174 */ 175 void GLAPIENTRY 176 _mesa_GetProgramParameterfvNV(GLenum target, GLuint index, 177 GLenum pname, GLfloat *params) 178 { 179 GET_CURRENT_CONTEXT(ctx); 180 ASSERT_OUTSIDE_BEGIN_END(ctx); 181 182 if (target == GL_VERTEX_PROGRAM_NV) { 183 if (pname == GL_PROGRAM_PARAMETER_NV) { 184 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { 185 COPY_4V(params, ctx->VertexProgram.Parameters[index]); 186 } 187 else { 188 _mesa_error(ctx, GL_INVALID_VALUE, 189 "glGetProgramParameterfvNV(index)"); 190 return; 191 } 192 } 193 else { 194 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)"); 195 return; 196 } 197 } 198 else { 199 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)"); 200 return; 201 } 202 } 203 204 205 /** 206 * Get a program parameter register. 207 * \note Not compiled into display lists. 208 * \note Called from the GL API dispatcher. 209 */ 210 void GLAPIENTRY 211 _mesa_GetProgramParameterdvNV(GLenum target, GLuint index, 212 GLenum pname, GLdouble *params) 213 { 214 GET_CURRENT_CONTEXT(ctx); 215 ASSERT_OUTSIDE_BEGIN_END(ctx); 216 217 if (target == GL_VERTEX_PROGRAM_NV) { 218 if (pname == GL_PROGRAM_PARAMETER_NV) { 219 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { 220 COPY_4V(params, ctx->VertexProgram.Parameters[index]); 221 } 222 else { 223 _mesa_error(ctx, GL_INVALID_VALUE, 224 "glGetProgramParameterdvNV(index)"); 225 return; 226 } 227 } 228 else { 229 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)"); 230 return; 231 } 232 } 233 else { 234 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)"); 235 return; 236 } 237 } 238 239 240 /** 241 * Get a program attribute. 242 * \note Not compiled into display lists. 243 * \note Called from the GL API dispatcher. 244 */ 245 void GLAPIENTRY 246 _mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) 247 { 248 struct gl_program *prog; 249 GET_CURRENT_CONTEXT(ctx); 250 251 ASSERT_OUTSIDE_BEGIN_END(ctx); 252 253 prog = _mesa_lookup_program(ctx, id); 254 if (!prog) { 255 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); 256 return; 257 } 258 259 switch (pname) { 260 case GL_PROGRAM_TARGET_NV: 261 *params = prog->Target; 262 return; 263 case GL_PROGRAM_LENGTH_NV: 264 *params = prog->String ?(GLint) strlen((char *) prog->String) : 0; 265 return; 266 case GL_PROGRAM_RESIDENT_NV: 267 *params = prog->Resident; 268 return; 269 default: 270 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); 271 return; 272 } 273 } 274 275 276 /** 277 * Get the program source code. 278 * \note Not compiled into display lists. 279 * \note Called from the GL API dispatcher. 280 */ 281 void GLAPIENTRY 282 _mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) 283 { 284 struct gl_program *prog; 285 GET_CURRENT_CONTEXT(ctx); 286 287 ASSERT_OUTSIDE_BEGIN_END(ctx); 288 289 if (pname != GL_PROGRAM_STRING_NV) { 290 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)"); 291 return; 292 } 293 294 prog = _mesa_lookup_program(ctx, id); 295 if (!prog) { 296 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV"); 297 return; 298 } 299 300 if (prog->String) { 301 memcpy(program, prog->String, strlen((char *) prog->String)); 302 } 303 else { 304 program[0] = 0; 305 } 306 } 307 308 309 /** 310 * Get matrix tracking information. 311 * \note Not compiled into display lists. 312 * \note Called from the GL API dispatcher. 313 */ 314 void GLAPIENTRY 315 _mesa_GetTrackMatrixivNV(GLenum target, GLuint address, 316 GLenum pname, GLint *params) 317 { 318 GET_CURRENT_CONTEXT(ctx); 319 ASSERT_OUTSIDE_BEGIN_END(ctx); 320 321 if (target == GL_VERTEX_PROGRAM_NV 322 && ctx->Extensions.NV_vertex_program) { 323 GLuint i; 324 325 if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) { 326 _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)"); 327 return; 328 } 329 330 i = address / 4; 331 332 switch (pname) { 333 case GL_TRACK_MATRIX_NV: 334 params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i]; 335 return; 336 case GL_TRACK_MATRIX_TRANSFORM_NV: 337 params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i]; 338 return; 339 default: 340 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); 341 return; 342 } 343 } 344 else { 345 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); 346 return; 347 } 348 } 349 350 351 /** 352 * Get a vertex (or vertex array) attribute. 353 * \note Not compiled into display lists. 354 * \note Called from the GL API dispatcher. 355 */ 356 void GLAPIENTRY 357 _mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) 358 { 359 const struct gl_client_array *array; 360 GET_CURRENT_CONTEXT(ctx); 361 ASSERT_OUTSIDE_BEGIN_END(ctx); 362 363 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 364 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); 365 return; 366 } 367 368 array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; 369 370 switch (pname) { 371 case GL_ATTRIB_ARRAY_SIZE_NV: 372 params[0] = array->Size; 373 break; 374 case GL_ATTRIB_ARRAY_STRIDE_NV: 375 params[0] = array->Stride; 376 break; 377 case GL_ATTRIB_ARRAY_TYPE_NV: 378 params[0] = array->Type; 379 break; 380 case GL_CURRENT_ATTRIB_NV: 381 if (index == 0) { 382 _mesa_error(ctx, GL_INVALID_OPERATION, 383 "glGetVertexAttribdvNV(index == 0)"); 384 return; 385 } 386 FLUSH_CURRENT(ctx, 0); 387 COPY_4V(params, ctx->Current.Attrib[index]); 388 break; 389 default: 390 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); 391 return; 392 } 393 } 394 395 /** 396 * Get a vertex (or vertex array) attribute. 397 * \note Not compiled into display lists. 398 * \note Called from the GL API dispatcher. 399 */ 400 void GLAPIENTRY 401 _mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) 402 { 403 const struct gl_client_array *array; 404 GET_CURRENT_CONTEXT(ctx); 405 ASSERT_OUTSIDE_BEGIN_END(ctx); 406 407 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 408 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); 409 return; 410 } 411 412 array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; 413 414 switch (pname) { 415 case GL_ATTRIB_ARRAY_SIZE_NV: 416 params[0] = (GLfloat) array->Size; 417 break; 418 case GL_ATTRIB_ARRAY_STRIDE_NV: 419 params[0] = (GLfloat) array->Stride; 420 break; 421 case GL_ATTRIB_ARRAY_TYPE_NV: 422 params[0] = (GLfloat) array->Type; 423 break; 424 case GL_CURRENT_ATTRIB_NV: 425 if (index == 0) { 426 _mesa_error(ctx, GL_INVALID_OPERATION, 427 "glGetVertexAttribfvNV(index == 0)"); 428 return; 429 } 430 FLUSH_CURRENT(ctx, 0); 431 COPY_4V(params, ctx->Current.Attrib[index]); 432 break; 433 default: 434 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); 435 return; 436 } 437 } 438 439 /** 440 * Get a vertex (or vertex array) attribute. 441 * \note Not compiled into display lists. 442 * \note Called from the GL API dispatcher. 443 */ 444 void GLAPIENTRY 445 _mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) 446 { 447 const struct gl_client_array *array; 448 GET_CURRENT_CONTEXT(ctx); 449 ASSERT_OUTSIDE_BEGIN_END(ctx); 450 451 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 452 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); 453 return; 454 } 455 456 array = &ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)]; 457 458 switch (pname) { 459 case GL_ATTRIB_ARRAY_SIZE_NV: 460 params[0] = array->Size; 461 break; 462 case GL_ATTRIB_ARRAY_STRIDE_NV: 463 params[0] = array->Stride; 464 break; 465 case GL_ATTRIB_ARRAY_TYPE_NV: 466 params[0] = array->Type; 467 break; 468 case GL_CURRENT_ATTRIB_NV: 469 if (index == 0) { 470 _mesa_error(ctx, GL_INVALID_OPERATION, 471 "glGetVertexAttribivNV(index == 0)"); 472 return; 473 } 474 FLUSH_CURRENT(ctx, 0); 475 params[0] = (GLint) ctx->Current.Attrib[index][0]; 476 params[1] = (GLint) ctx->Current.Attrib[index][1]; 477 params[2] = (GLint) ctx->Current.Attrib[index][2]; 478 params[3] = (GLint) ctx->Current.Attrib[index][3]; 479 break; 480 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: 481 params[0] = array->BufferObj->Name; 482 break; 483 default: 484 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); 485 return; 486 } 487 } 488 489 490 /** 491 * Get a vertex array attribute pointer. 492 * \note Not compiled into display lists. 493 * \note Called from the GL API dispatcher. 494 */ 495 void GLAPIENTRY 496 _mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) 497 { 498 GET_CURRENT_CONTEXT(ctx); 499 ASSERT_OUTSIDE_BEGIN_END(ctx); 500 501 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 502 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)"); 503 return; 504 } 505 506 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) { 507 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)"); 508 return; 509 } 510 511 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[VERT_ATTRIB_GENERIC(index)].Ptr; 512 } 513 514 void 515 _mesa_emit_nv_temp_initialization(struct gl_context *ctx, 516 struct gl_program *program) 517 { 518 struct prog_instruction *inst; 519 GLuint i; 520 struct gl_shader_compiler_options* options = 521 &ctx->ShaderCompilerOptions[_mesa_program_target_to_index(program->Target)]; 522 523 if (!options->EmitNVTempInitialization) 524 return; 525 526 /* We'll swizzle up a zero temporary so we can use it for the 527 * ARL. 528 */ 529 if (program->NumTemporaries == 0) 530 program->NumTemporaries = 1; 531 532 _mesa_insert_instructions(program, 0, program->NumTemporaries + 1); 533 534 for (i = 0; i < program->NumTemporaries; i++) { 535 struct prog_instruction *inst = &program->Instructions[i]; 536 537 inst->Opcode = OPCODE_SWZ; 538 inst->DstReg.File = PROGRAM_TEMPORARY; 539 inst->DstReg.Index = i; 540 inst->DstReg.WriteMask = WRITEMASK_XYZW; 541 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 542 inst->SrcReg[0].Index = 0; 543 inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO, 544 SWIZZLE_ZERO, 545 SWIZZLE_ZERO, 546 SWIZZLE_ZERO); 547 } 548 549 inst = &program->Instructions[i]; 550 inst->Opcode = OPCODE_ARL; 551 inst->DstReg.File = PROGRAM_ADDRESS; 552 inst->DstReg.Index = 0; 553 inst->DstReg.WriteMask = WRITEMASK_XYZW; 554 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 555 inst->SrcReg[0].Index = 0; 556 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 557 558 if (program->NumAddressRegs == 0) 559 program->NumAddressRegs = 1; 560 } 561 562 void 563 _mesa_setup_nv_temporary_count(struct gl_program *program) 564 { 565 GLuint i; 566 567 program->NumTemporaries = 0; 568 for (i = 0; i < program->NumInstructions; i++) { 569 struct prog_instruction *inst = &program->Instructions[i]; 570 571 if (inst->DstReg.File == PROGRAM_TEMPORARY) { 572 program->NumTemporaries = MAX2(program->NumTemporaries, 573 inst->DstReg.Index + 1); 574 } 575 if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) { 576 program->NumTemporaries = MAX2((GLint)program->NumTemporaries, 577 inst->SrcReg[0].Index + 1); 578 } 579 if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) { 580 program->NumTemporaries = MAX2((GLint)program->NumTemporaries, 581 inst->SrcReg[1].Index + 1); 582 } 583 if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) { 584 program->NumTemporaries = MAX2((GLint)program->NumTemporaries, 585 inst->SrcReg[2].Index + 1); 586 } 587 } 588 } 589 590 /** 591 * Load/parse/compile a program. 592 * \note Called from the GL API dispatcher. 593 */ 594 void GLAPIENTRY 595 _mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, 596 const GLubyte *program) 597 { 598 struct gl_program *prog; 599 GET_CURRENT_CONTEXT(ctx); 600 ASSERT_OUTSIDE_BEGIN_END(ctx); 601 602 if (!ctx->Extensions.NV_vertex_program 603 && !ctx->Extensions.NV_fragment_program) { 604 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()"); 605 return; 606 } 607 608 if (id == 0) { 609 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)"); 610 return; 611 } 612 613 if (len < 0) { 614 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)"); 615 return; 616 } 617 618 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 619 620 prog = _mesa_lookup_program(ctx, id); 621 622 if (prog && prog->Target != 0 && prog->Target != target) { 623 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)"); 624 return; 625 } 626 627 if ((target == GL_VERTEX_PROGRAM_NV || 628 target == GL_VERTEX_STATE_PROGRAM_NV) 629 && ctx->Extensions.NV_vertex_program) { 630 struct gl_vertex_program *vprog = gl_vertex_program(prog); 631 if (!vprog || prog == &_mesa_DummyProgram) { 632 vprog = gl_vertex_program(ctx->Driver.NewProgram(ctx, target, id)); 633 if (!vprog) { 634 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); 635 return; 636 } 637 _mesa_HashInsert(ctx->Shared->Programs, id, vprog); 638 } 639 640 if (ctx->Extensions.ARB_vertex_program 641 && (strncmp((char *) program, "!!ARB", 5) == 0)) { 642 _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog); 643 } else { 644 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); 645 } 646 } 647 else if (target == GL_FRAGMENT_PROGRAM_NV 648 && ctx->Extensions.NV_fragment_program) { 649 struct gl_fragment_program *fprog = gl_fragment_program(prog); 650 if (!fprog || prog == &_mesa_DummyProgram) { 651 fprog = gl_fragment_program(ctx->Driver.NewProgram(ctx, target, id)); 652 if (!fprog) { 653 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); 654 return; 655 } 656 _mesa_HashInsert(ctx->Shared->Programs, id, fprog); 657 } 658 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog); 659 } 660 else if (target == GL_FRAGMENT_PROGRAM_ARB 661 && ctx->Extensions.ARB_fragment_program) { 662 struct gl_fragment_program *fprog = gl_fragment_program(prog); 663 if (!fprog || prog == &_mesa_DummyProgram) { 664 fprog = gl_fragment_program(ctx->Driver.NewProgram(ctx, target, id)); 665 if (!fprog) { 666 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); 667 return; 668 } 669 _mesa_HashInsert(ctx->Shared->Programs, id, fprog); 670 } 671 _mesa_parse_arb_fragment_program(ctx, target, program, len, fprog); 672 } 673 else { 674 _mesa_error(ctx, GL_INVALID_ENUM, "glLoadProgramNV(target)"); 675 } 676 } 677 678 679 680 /** 681 * Set a sequence of program parameter registers. 682 * \note Called from the GL API dispatcher. 683 */ 684 void GLAPIENTRY 685 _mesa_ProgramParameters4dvNV(GLenum target, GLuint index, 686 GLsizei num, const GLdouble *params) 687 { 688 GET_CURRENT_CONTEXT(ctx); 689 ASSERT_OUTSIDE_BEGIN_END(ctx); 690 691 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { 692 GLint i; 693 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { 694 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4dvNV"); 695 return; 696 } 697 for (i = 0; i < num; i++) { 698 ctx->VertexProgram.Parameters[index + i][0] = (GLfloat) params[0]; 699 ctx->VertexProgram.Parameters[index + i][1] = (GLfloat) params[1]; 700 ctx->VertexProgram.Parameters[index + i][2] = (GLfloat) params[2]; 701 ctx->VertexProgram.Parameters[index + i][3] = (GLfloat) params[3]; 702 params += 4; 703 }; 704 } 705 else { 706 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4dvNV"); 707 return; 708 } 709 } 710 711 712 /** 713 * Set a sequence of program parameter registers. 714 * \note Called from the GL API dispatcher. 715 */ 716 void GLAPIENTRY 717 _mesa_ProgramParameters4fvNV(GLenum target, GLuint index, 718 GLsizei num, const GLfloat *params) 719 { 720 GET_CURRENT_CONTEXT(ctx); 721 ASSERT_OUTSIDE_BEGIN_END(ctx); 722 723 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { 724 GLint i; 725 if (index + num > MAX_NV_VERTEX_PROGRAM_PARAMS) { 726 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramParameters4fvNV"); 727 return; 728 } 729 for (i = 0; i < num; i++) { 730 COPY_4V(ctx->VertexProgram.Parameters[index + i], params); 731 params += 4; 732 } 733 } 734 else { 735 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameters4fvNV"); 736 return; 737 } 738 } 739 740 741 742 /** 743 * Setup tracking of matrices into program parameter registers. 744 * \note Called from the GL API dispatcher. 745 */ 746 void GLAPIENTRY 747 _mesa_TrackMatrixNV(GLenum target, GLuint address, 748 GLenum matrix, GLenum transform) 749 { 750 GET_CURRENT_CONTEXT(ctx); 751 ASSERT_OUTSIDE_BEGIN_END(ctx); 752 753 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 754 755 if (target == GL_VERTEX_PROGRAM_NV && ctx->Extensions.NV_vertex_program) { 756 if (address & 0x3) { 757 /* addr must be multiple of four */ 758 _mesa_error(ctx, GL_INVALID_VALUE, "glTrackMatrixNV(address)"); 759 return; 760 } 761 762 switch (matrix) { 763 case GL_NONE: 764 case GL_MODELVIEW: 765 case GL_PROJECTION: 766 case GL_TEXTURE: 767 case GL_COLOR: 768 case GL_MODELVIEW_PROJECTION_NV: 769 case GL_MATRIX0_NV: 770 case GL_MATRIX1_NV: 771 case GL_MATRIX2_NV: 772 case GL_MATRIX3_NV: 773 case GL_MATRIX4_NV: 774 case GL_MATRIX5_NV: 775 case GL_MATRIX6_NV: 776 case GL_MATRIX7_NV: 777 /* OK, fallthrough */ 778 break; 779 default: 780 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(matrix)"); 781 return; 782 } 783 784 switch (transform) { 785 case GL_IDENTITY_NV: 786 case GL_INVERSE_NV: 787 case GL_TRANSPOSE_NV: 788 case GL_INVERSE_TRANSPOSE_NV: 789 /* OK, fallthrough */ 790 break; 791 default: 792 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(transform)"); 793 return; 794 } 795 796 ctx->VertexProgram.TrackMatrix[address / 4] = matrix; 797 ctx->VertexProgram.TrackMatrixTransform[address / 4] = transform; 798 } 799 else { 800 _mesa_error(ctx, GL_INVALID_ENUM, "glTrackMatrixNV(target)"); 801 return; 802 } 803 } 804 805 806 void GLAPIENTRY 807 _mesa_ProgramNamedParameter4fNV(GLuint id, GLsizei len, const GLubyte *name, 808 GLfloat x, GLfloat y, GLfloat z, GLfloat w) 809 { 810 struct gl_program *prog; 811 struct gl_fragment_program *fragProg; 812 gl_constant_value *v; 813 814 GET_CURRENT_CONTEXT(ctx); 815 ASSERT_OUTSIDE_BEGIN_END(ctx); 816 817 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 818 819 prog = _mesa_lookup_program(ctx, id); 820 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { 821 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramNamedParameterNV"); 822 return; 823 } 824 825 if (len <= 0) { 826 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(len)"); 827 return; 828 } 829 830 fragProg = gl_fragment_program(prog); 831 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len, 832 (char *) name); 833 if (v) { 834 v[0].f = x; 835 v[1].f = y; 836 v[2].f = z; 837 v[3].f = w; 838 return; 839 } 840 841 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)"); 842 } 843 844 845 void GLAPIENTRY 846 _mesa_ProgramNamedParameter4fvNV(GLuint id, GLsizei len, const GLubyte *name, 847 const float v[]) 848 { 849 _mesa_ProgramNamedParameter4fNV(id, len, name, v[0], v[1], v[2], v[3]); 850 } 851 852 853 void GLAPIENTRY 854 _mesa_ProgramNamedParameter4dNV(GLuint id, GLsizei len, const GLubyte *name, 855 GLdouble x, GLdouble y, GLdouble z, GLdouble w) 856 { 857 _mesa_ProgramNamedParameter4fNV(id, len, name, (GLfloat)x, (GLfloat)y, 858 (GLfloat)z, (GLfloat)w); 859 } 860 861 862 void GLAPIENTRY 863 _mesa_ProgramNamedParameter4dvNV(GLuint id, GLsizei len, const GLubyte *name, 864 const double v[]) 865 { 866 _mesa_ProgramNamedParameter4fNV(id, len, name, 867 (GLfloat)v[0], (GLfloat)v[1], 868 (GLfloat)v[2], (GLfloat)v[3]); 869 } 870 871 872 void GLAPIENTRY 873 _mesa_GetProgramNamedParameterfvNV(GLuint id, GLsizei len, const GLubyte *name, 874 GLfloat *params) 875 { 876 struct gl_program *prog; 877 struct gl_fragment_program *fragProg; 878 const gl_constant_value *v; 879 880 GET_CURRENT_CONTEXT(ctx); 881 882 ASSERT_OUTSIDE_BEGIN_END(ctx); 883 884 prog = _mesa_lookup_program(ctx, id); 885 if (!prog || prog->Target != GL_FRAGMENT_PROGRAM_NV) { 886 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramNamedParameterNV"); 887 return; 888 } 889 890 if (len <= 0) { 891 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); 892 return; 893 } 894 895 fragProg = gl_fragment_program(prog); 896 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, 897 len, (char *) name); 898 if (v) { 899 params[0] = v[0].f; 900 params[1] = v[1].f; 901 params[2] = v[2].f; 902 params[3] = v[3].f; 903 return; 904 } 905 906 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); 907 } 908 909 910 void GLAPIENTRY 911 _mesa_GetProgramNamedParameterdvNV(GLuint id, GLsizei len, const GLubyte *name, 912 GLdouble *params) 913 { 914 GLfloat floatParams[4]; 915 _mesa_GetProgramNamedParameterfvNV(id, len, name, floatParams); 916 COPY_4V(params, floatParams); 917 } 918