nvprogram.c revision 21d0c70b4b1c18dc1c3ac7d0fbd8a903d60f8be7
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 "arbprogparse.h" 51#include "nvprogram.h" 52 53 54 55/** 56 * Execute a vertex state program. 57 * \note Called from the GL API dispatcher. 58 */ 59void GLAPIENTRY 60_mesa_ExecuteProgramNV(GLenum target, GLuint id, const GLfloat *params) 61{ 62 struct gl_vertex_program *vprog; 63 GET_CURRENT_CONTEXT(ctx); 64 ASSERT_OUTSIDE_BEGIN_END(ctx); 65 66 if (target != GL_VERTEX_STATE_PROGRAM_NV) { 67 _mesa_error(ctx, GL_INVALID_ENUM, "glExecuteProgramNV"); 68 return; 69 } 70 71 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 72 73 vprog = (struct gl_vertex_program *) _mesa_lookup_program(ctx, id); 74 75 if (!vprog || vprog->Base.Target != GL_VERTEX_STATE_PROGRAM_NV) { 76 _mesa_error(ctx, GL_INVALID_OPERATION, "glExecuteProgramNV"); 77 return; 78 } 79 80 _mesa_problem(ctx, "glExecuteProgramNV() not supported"); 81} 82 83 84/** 85 * Determine if a set of programs is resident in hardware. 86 * \note Not compiled into display lists. 87 * \note Called from the GL API dispatcher. 88 */ 89GLboolean GLAPIENTRY 90_mesa_AreProgramsResidentNV(GLsizei n, const GLuint *ids, 91 GLboolean *residences) 92{ 93 GLint i, j; 94 GLboolean allResident = GL_TRUE; 95 GET_CURRENT_CONTEXT(ctx); 96 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 97 98 if (n < 0) { 99 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV(n)"); 100 return GL_FALSE; 101 } 102 103 for (i = 0; i < n; i++) { 104 const struct gl_program *prog; 105 if (ids[i] == 0) { 106 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); 107 return GL_FALSE; 108 } 109 prog = _mesa_lookup_program(ctx, ids[i]); 110 if (!prog) { 111 _mesa_error(ctx, GL_INVALID_VALUE, "glAreProgramsResidentNV"); 112 return GL_FALSE; 113 } 114 if (prog->Resident) { 115 if (!allResident) 116 residences[i] = GL_TRUE; 117 } 118 else { 119 if (allResident) { 120 allResident = GL_FALSE; 121 for (j = 0; j < i; j++) 122 residences[j] = GL_TRUE; 123 } 124 residences[i] = GL_FALSE; 125 } 126 } 127 128 return allResident; 129} 130 131 132/** 133 * Request that a set of programs be resident in hardware. 134 * \note Called from the GL API dispatcher. 135 */ 136void GLAPIENTRY 137_mesa_RequestResidentProgramsNV(GLsizei n, const GLuint *ids) 138{ 139 GLint i; 140 GET_CURRENT_CONTEXT(ctx); 141 ASSERT_OUTSIDE_BEGIN_END(ctx); 142 143 if (n < 0) { 144 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(n)"); 145 return; 146 } 147 148 /* just error checking for now */ 149 for (i = 0; i < n; i++) { 150 struct gl_program *prog; 151 152 if (ids[i] == 0) { 153 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); 154 return; 155 } 156 157 prog = _mesa_lookup_program(ctx, ids[i]); 158 if (!prog) { 159 _mesa_error(ctx, GL_INVALID_VALUE, "glRequestResidentProgramsNV(id)"); 160 return; 161 } 162 163 /* XXX this is really a hardware thing we should hook out */ 164 prog->Resident = GL_TRUE; 165 } 166} 167 168 169/** 170 * Get a program parameter register. 171 * \note Not compiled into display lists. 172 * \note Called from the GL API dispatcher. 173 */ 174void GLAPIENTRY 175_mesa_GetProgramParameterfvNV(GLenum target, GLuint index, 176 GLenum pname, GLfloat *params) 177{ 178 GET_CURRENT_CONTEXT(ctx); 179 ASSERT_OUTSIDE_BEGIN_END(ctx); 180 181 if (target == GL_VERTEX_PROGRAM_NV) { 182 if (pname == GL_PROGRAM_PARAMETER_NV) { 183 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { 184 COPY_4V(params, ctx->VertexProgram.Parameters[index]); 185 } 186 else { 187 _mesa_error(ctx, GL_INVALID_VALUE, 188 "glGetProgramParameterfvNV(index)"); 189 return; 190 } 191 } 192 else { 193 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(pname)"); 194 return; 195 } 196 } 197 else { 198 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterfvNV(target)"); 199 return; 200 } 201} 202 203 204/** 205 * Get a program parameter register. 206 * \note Not compiled into display lists. 207 * \note Called from the GL API dispatcher. 208 */ 209void GLAPIENTRY 210_mesa_GetProgramParameterdvNV(GLenum target, GLuint index, 211 GLenum pname, GLdouble *params) 212{ 213 GET_CURRENT_CONTEXT(ctx); 214 ASSERT_OUTSIDE_BEGIN_END(ctx); 215 216 if (target == GL_VERTEX_PROGRAM_NV) { 217 if (pname == GL_PROGRAM_PARAMETER_NV) { 218 if (index < MAX_NV_VERTEX_PROGRAM_PARAMS) { 219 COPY_4V(params, ctx->VertexProgram.Parameters[index]); 220 } 221 else { 222 _mesa_error(ctx, GL_INVALID_VALUE, 223 "glGetProgramParameterdvNV(index)"); 224 return; 225 } 226 } 227 else { 228 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(pname)"); 229 return; 230 } 231 } 232 else { 233 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramParameterdvNV(target)"); 234 return; 235 } 236} 237 238 239/** 240 * Get a program attribute. 241 * \note Not compiled into display lists. 242 * \note Called from the GL API dispatcher. 243 */ 244void GLAPIENTRY 245_mesa_GetProgramivNV(GLuint id, GLenum pname, GLint *params) 246{ 247 struct gl_program *prog; 248 GET_CURRENT_CONTEXT(ctx); 249 250 ASSERT_OUTSIDE_BEGIN_END(ctx); 251 252 prog = _mesa_lookup_program(ctx, id); 253 if (!prog) { 254 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramivNV"); 255 return; 256 } 257 258 switch (pname) { 259 case GL_PROGRAM_TARGET_NV: 260 *params = prog->Target; 261 return; 262 case GL_PROGRAM_LENGTH_NV: 263 *params = prog->String ?(GLint) strlen((char *) prog->String) : 0; 264 return; 265 case GL_PROGRAM_RESIDENT_NV: 266 *params = prog->Resident; 267 return; 268 default: 269 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivNV(pname)"); 270 return; 271 } 272} 273 274 275/** 276 * Get the program source code. 277 * \note Not compiled into display lists. 278 * \note Called from the GL API dispatcher. 279 */ 280void GLAPIENTRY 281_mesa_GetProgramStringNV(GLuint id, GLenum pname, GLubyte *program) 282{ 283 struct gl_program *prog; 284 GET_CURRENT_CONTEXT(ctx); 285 286 ASSERT_OUTSIDE_BEGIN_END(ctx); 287 288 if (pname != GL_PROGRAM_STRING_NV) { 289 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringNV(pname)"); 290 return; 291 } 292 293 prog = _mesa_lookup_program(ctx, id); 294 if (!prog) { 295 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramStringNV"); 296 return; 297 } 298 299 if (prog->String) { 300 MEMCPY(program, prog->String, strlen((char *) prog->String)); 301 } 302 else { 303 program[0] = 0; 304 } 305} 306 307 308/** 309 * Get matrix tracking information. 310 * \note Not compiled into display lists. 311 * \note Called from the GL API dispatcher. 312 */ 313void GLAPIENTRY 314_mesa_GetTrackMatrixivNV(GLenum target, GLuint address, 315 GLenum pname, GLint *params) 316{ 317 GET_CURRENT_CONTEXT(ctx); 318 ASSERT_OUTSIDE_BEGIN_END(ctx); 319 320 if (target == GL_VERTEX_PROGRAM_NV 321 && ctx->Extensions.NV_vertex_program) { 322 GLuint i; 323 324 if ((address & 0x3) || address >= MAX_NV_VERTEX_PROGRAM_PARAMS) { 325 _mesa_error(ctx, GL_INVALID_VALUE, "glGetTrackMatrixivNV(address)"); 326 return; 327 } 328 329 i = address / 4; 330 331 switch (pname) { 332 case GL_TRACK_MATRIX_NV: 333 params[0] = (GLint) ctx->VertexProgram.TrackMatrix[i]; 334 return; 335 case GL_TRACK_MATRIX_TRANSFORM_NV: 336 params[0] = (GLint) ctx->VertexProgram.TrackMatrixTransform[i]; 337 return; 338 default: 339 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); 340 return; 341 } 342 } 343 else { 344 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTrackMatrixivNV"); 345 return; 346 } 347} 348 349 350/** 351 * Get a vertex (or vertex array) attribute. 352 * \note Not compiled into display lists. 353 * \note Called from the GL API dispatcher. 354 */ 355void GLAPIENTRY 356_mesa_GetVertexAttribdvNV(GLuint index, GLenum pname, GLdouble *params) 357{ 358 const struct gl_client_array *array; 359 GET_CURRENT_CONTEXT(ctx); 360 ASSERT_OUTSIDE_BEGIN_END(ctx); 361 362 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 363 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); 364 return; 365 } 366 367 array = &ctx->Array.ArrayObj->VertexAttrib[index]; 368 369 switch (pname) { 370 case GL_ATTRIB_ARRAY_SIZE_NV: 371 params[0] = array->Size; 372 break; 373 case GL_ATTRIB_ARRAY_STRIDE_NV: 374 params[0] = array->Stride; 375 break; 376 case GL_ATTRIB_ARRAY_TYPE_NV: 377 params[0] = array->Type; 378 break; 379 case GL_CURRENT_ATTRIB_NV: 380 if (index == 0) { 381 _mesa_error(ctx, GL_INVALID_OPERATION, 382 "glGetVertexAttribdvNV(index == 0)"); 383 return; 384 } 385 FLUSH_CURRENT(ctx, 0); 386 COPY_4V(params, ctx->Current.Attrib[index]); 387 break; 388 default: 389 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); 390 return; 391 } 392} 393 394/** 395 * Get a vertex (or vertex array) attribute. 396 * \note Not compiled into display lists. 397 * \note Called from the GL API dispatcher. 398 */ 399void GLAPIENTRY 400_mesa_GetVertexAttribfvNV(GLuint index, GLenum pname, GLfloat *params) 401{ 402 const struct gl_client_array *array; 403 GET_CURRENT_CONTEXT(ctx); 404 ASSERT_OUTSIDE_BEGIN_END(ctx); 405 406 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 407 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); 408 return; 409 } 410 411 array = &ctx->Array.ArrayObj->VertexAttrib[index]; 412 413 switch (pname) { 414 case GL_ATTRIB_ARRAY_SIZE_NV: 415 params[0] = (GLfloat) array->Size; 416 break; 417 case GL_ATTRIB_ARRAY_STRIDE_NV: 418 params[0] = (GLfloat) array->Stride; 419 break; 420 case GL_ATTRIB_ARRAY_TYPE_NV: 421 params[0] = (GLfloat) array->Type; 422 break; 423 case GL_CURRENT_ATTRIB_NV: 424 if (index == 0) { 425 _mesa_error(ctx, GL_INVALID_OPERATION, 426 "glGetVertexAttribfvNV(index == 0)"); 427 return; 428 } 429 FLUSH_CURRENT(ctx, 0); 430 COPY_4V(params, ctx->Current.Attrib[index]); 431 break; 432 default: 433 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); 434 return; 435 } 436} 437 438/** 439 * Get a vertex (or vertex array) attribute. 440 * \note Not compiled into display lists. 441 * \note Called from the GL API dispatcher. 442 */ 443void GLAPIENTRY 444_mesa_GetVertexAttribivNV(GLuint index, GLenum pname, GLint *params) 445{ 446 const struct gl_client_array *array; 447 GET_CURRENT_CONTEXT(ctx); 448 ASSERT_OUTSIDE_BEGIN_END(ctx); 449 450 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 451 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribdvNV(index)"); 452 return; 453 } 454 455 array = &ctx->Array.ArrayObj->VertexAttrib[index]; 456 457 switch (pname) { 458 case GL_ATTRIB_ARRAY_SIZE_NV: 459 params[0] = array->Size; 460 break; 461 case GL_ATTRIB_ARRAY_STRIDE_NV: 462 params[0] = array->Stride; 463 break; 464 case GL_ATTRIB_ARRAY_TYPE_NV: 465 params[0] = array->Type; 466 break; 467 case GL_CURRENT_ATTRIB_NV: 468 if (index == 0) { 469 _mesa_error(ctx, GL_INVALID_OPERATION, 470 "glGetVertexAttribivNV(index == 0)"); 471 return; 472 } 473 FLUSH_CURRENT(ctx, 0); 474 params[0] = (GLint) ctx->Current.Attrib[index][0]; 475 params[1] = (GLint) ctx->Current.Attrib[index][1]; 476 params[2] = (GLint) ctx->Current.Attrib[index][2]; 477 params[3] = (GLint) ctx->Current.Attrib[index][3]; 478 break; 479 case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB: 480 params[0] = array->BufferObj->Name; 481 break; 482 default: 483 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribdvNV"); 484 return; 485 } 486} 487 488 489/** 490 * Get a vertex array attribute pointer. 491 * \note Not compiled into display lists. 492 * \note Called from the GL API dispatcher. 493 */ 494void GLAPIENTRY 495_mesa_GetVertexAttribPointervNV(GLuint index, GLenum pname, GLvoid **pointer) 496{ 497 GET_CURRENT_CONTEXT(ctx); 498 ASSERT_OUTSIDE_BEGIN_END(ctx); 499 500 if (index >= MAX_NV_VERTEX_PROGRAM_INPUTS) { 501 _mesa_error(ctx, GL_INVALID_VALUE, "glGetVertexAttribPointerNV(index)"); 502 return; 503 } 504 505 if (pname != GL_ATTRIB_ARRAY_POINTER_NV) { 506 _mesa_error(ctx, GL_INVALID_ENUM, "glGetVertexAttribPointerNV(pname)"); 507 return; 508 } 509 510 *pointer = (GLvoid *) ctx->Array.ArrayObj->VertexAttrib[index].Ptr; 511} 512 513void 514_mesa_emit_nv_temp_initialization(GLcontext *ctx, 515 struct gl_program *program) 516{ 517 struct prog_instruction *inst; 518 GLuint i; 519 520 if (!ctx->Shader.EmitNVTempInitialization) 521 return; 522 523 /* We'll swizzle up a zero temporary so we can use it for the 524 * ARL. 525 */ 526 if (program->NumTemporaries == 0) 527 program->NumTemporaries = 1; 528 529 _mesa_insert_instructions(program, 0, program->NumTemporaries + 1); 530 531 for (i = 0; i < program->NumTemporaries; i++) { 532 struct prog_instruction *inst = &program->Instructions[i]; 533 534 inst->Opcode = OPCODE_SWZ; 535 inst->DstReg.File = PROGRAM_TEMPORARY; 536 inst->DstReg.Index = i; 537 inst->DstReg.WriteMask = WRITEMASK_XYZW; 538 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 539 inst->SrcReg[0].Index = 0; 540 inst->SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_ZERO, 541 SWIZZLE_ZERO, 542 SWIZZLE_ZERO, 543 SWIZZLE_ZERO); 544 } 545 546 inst = &program->Instructions[i]; 547 inst->Opcode = OPCODE_ARL; 548 inst->DstReg.File = PROGRAM_ADDRESS; 549 inst->DstReg.Index = 0; 550 inst->DstReg.WriteMask = WRITEMASK_XYZW; 551 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 552 inst->SrcReg[0].Index = 0; 553 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 554 555 if (program->NumAddressRegs == 0) 556 program->NumAddressRegs = 1; 557} 558 559void 560_mesa_setup_nv_temporary_count(GLcontext *ctx, struct gl_program *program) 561{ 562 GLuint i; 563 564 program->NumTemporaries = 0; 565 for (i = 0; i < program->NumInstructions; i++) { 566 struct prog_instruction *inst = &program->Instructions[i]; 567 568 if (inst->DstReg.File == PROGRAM_TEMPORARY) { 569 program->NumTemporaries = MAX2(program->NumTemporaries, 570 inst->DstReg.Index + 1); 571 } 572 if (inst->SrcReg[0].File == PROGRAM_TEMPORARY) { 573 program->NumTemporaries = MAX2((GLint)program->NumTemporaries, 574 inst->SrcReg[0].Index + 1); 575 } 576 if (inst->SrcReg[1].File == PROGRAM_TEMPORARY) { 577 program->NumTemporaries = MAX2((GLint)program->NumTemporaries, 578 inst->SrcReg[1].Index + 1); 579 } 580 if (inst->SrcReg[2].File == PROGRAM_TEMPORARY) { 581 program->NumTemporaries = MAX2((GLint)program->NumTemporaries, 582 inst->SrcReg[2].Index + 1); 583 } 584 } 585} 586 587/** 588 * Load/parse/compile a program. 589 * \note Called from the GL API dispatcher. 590 */ 591void GLAPIENTRY 592_mesa_LoadProgramNV(GLenum target, GLuint id, GLsizei len, 593 const GLubyte *program) 594{ 595 struct gl_program *prog; 596 GET_CURRENT_CONTEXT(ctx); 597 ASSERT_OUTSIDE_BEGIN_END(ctx); 598 599 if (!ctx->Extensions.NV_vertex_program 600 && !ctx->Extensions.NV_fragment_program) { 601 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV()"); 602 return; 603 } 604 605 if (id == 0) { 606 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(id)"); 607 return; 608 } 609 610 if (len < 0) { 611 _mesa_error(ctx, GL_INVALID_VALUE, "glLoadProgramNV(len)"); 612 return; 613 } 614 615 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 616 617 prog = _mesa_lookup_program(ctx, id); 618 619 if (prog && prog->Target != 0 && prog->Target != target) { 620 _mesa_error(ctx, GL_INVALID_OPERATION, "glLoadProgramNV(target)"); 621 return; 622 } 623 624 if ((target == GL_VERTEX_PROGRAM_NV || 625 target == GL_VERTEX_STATE_PROGRAM_NV) 626 && ctx->Extensions.NV_vertex_program) { 627 struct gl_vertex_program *vprog = (struct gl_vertex_program *) prog; 628 if (!vprog || prog == &_mesa_DummyProgram) { 629 vprog = (struct gl_vertex_program *) 630 ctx->Driver.NewProgram(ctx, target, id); 631 if (!vprog) { 632 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); 633 return; 634 } 635 _mesa_HashInsert(ctx->Shared->Programs, id, vprog); 636 } 637 638 if (ctx->Extensions.ARB_vertex_program 639 && (strncmp((char *) program, "!!ARB", 5) == 0)) { 640 _mesa_parse_arb_vertex_program(ctx, target, program, len, vprog); 641 } else { 642 _mesa_parse_nv_vertex_program(ctx, target, program, len, vprog); 643 } 644 } 645 else if (target == GL_FRAGMENT_PROGRAM_NV 646 && ctx->Extensions.NV_fragment_program) { 647 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; 648 if (!fprog || prog == &_mesa_DummyProgram) { 649 fprog = (struct gl_fragment_program *) 650 ctx->Driver.NewProgram(ctx, target, id); 651 if (!fprog) { 652 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glLoadProgramNV"); 653 return; 654 } 655 _mesa_HashInsert(ctx->Shared->Programs, id, fprog); 656 } 657 _mesa_parse_nv_fragment_program(ctx, target, program, len, fprog); 658 } 659 else if (target == GL_FRAGMENT_PROGRAM_ARB 660 && ctx->Extensions.ARB_fragment_program) { 661 struct gl_fragment_program *fprog = (struct gl_fragment_program *) prog; 662 if (!fprog || prog == &_mesa_DummyProgram) { 663 fprog = (struct gl_fragment_program *) 664 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 */ 684void GLAPIENTRY 685_mesa_ProgramParameters4dvNV(GLenum target, GLuint index, 686 GLuint 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 GLuint 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 */ 716void GLAPIENTRY 717_mesa_ProgramParameters4fvNV(GLenum target, GLuint index, 718 GLuint 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 GLuint 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 */ 746void 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 806void 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 GLfloat *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 = (struct gl_fragment_program *) prog; 831 v = _mesa_lookup_parameter_value(fragProg->Base.Parameters, len, 832 (char *) name); 833 if (v) { 834 v[0] = x; 835 v[1] = y; 836 v[2] = z; 837 v[3] = w; 838 return; 839 } 840 841 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramNamedParameterNV(name)"); 842} 843 844 845void 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 853void 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 862void 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 872void 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 GLfloat *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 = (struct 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]; 900 params[1] = v[1]; 901 params[2] = v[2]; 902 params[3] = v[3]; 903 return; 904 } 905 906 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramNamedParameterNV"); 907} 908 909 910void 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