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