arbprogram.c revision af69d88d
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * \file arbprogram.c 27 * ARB_vertex/fragment_program state management functions. 28 * \author Brian Paul 29 */ 30 31 32#include "main/glheader.h" 33#include "main/context.h" 34#include "main/hash.h" 35#include "main/imports.h" 36#include "main/macros.h" 37#include "main/mtypes.h" 38#include "main/arbprogram.h" 39#include "program/arbprogparse.h" 40#include "program/program.h" 41#include "program/prog_print.h" 42 43 44/** 45 * Bind a program (make it current) 46 * \note Called from the GL API dispatcher by both glBindProgramNV 47 * and glBindProgramARB. 48 */ 49void GLAPIENTRY 50_mesa_BindProgramARB(GLenum target, GLuint id) 51{ 52 struct gl_program *curProg, *newProg; 53 GET_CURRENT_CONTEXT(ctx); 54 55 /* Error-check target and get curProg */ 56 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { 57 curProg = &ctx->VertexProgram.Current->Base; 58 } 59 else if (target == GL_FRAGMENT_PROGRAM_ARB 60 && ctx->Extensions.ARB_fragment_program) { 61 curProg = &ctx->FragmentProgram.Current->Base; 62 } 63 else { 64 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)"); 65 return; 66 } 67 68 /* 69 * Get pointer to new program to bind. 70 * NOTE: binding to a non-existant program is not an error. 71 * That's supposed to be caught in glBegin. 72 */ 73 if (id == 0) { 74 /* Bind a default program */ 75 newProg = NULL; 76 if (target == GL_VERTEX_PROGRAM_ARB) 77 newProg = &ctx->Shared->DefaultVertexProgram->Base; 78 else 79 newProg = &ctx->Shared->DefaultFragmentProgram->Base; 80 } 81 else { 82 /* Bind a user program */ 83 newProg = _mesa_lookup_program(ctx, id); 84 if (!newProg || newProg == &_mesa_DummyProgram) { 85 /* allocate a new program now */ 86 newProg = ctx->Driver.NewProgram(ctx, target, id); 87 if (!newProg) { 88 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindProgramARB"); 89 return; 90 } 91 _mesa_HashInsert(ctx->Shared->Programs, id, newProg); 92 } 93 else if (newProg->Target != target) { 94 _mesa_error(ctx, GL_INVALID_OPERATION, 95 "glBindProgramARB(target mismatch)"); 96 return; 97 } 98 } 99 100 /** All error checking is complete now **/ 101 102 if (curProg->Id == id) { 103 /* binding same program - no change */ 104 return; 105 } 106 107 /* signal new program (and its new constants) */ 108 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); 109 110 /* bind newProg */ 111 if (target == GL_VERTEX_PROGRAM_ARB) { 112 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 113 gl_vertex_program(newProg)); 114 } 115 else if (target == GL_FRAGMENT_PROGRAM_ARB) { 116 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 117 gl_fragment_program(newProg)); 118 } 119 120 /* Never null pointers */ 121 ASSERT(ctx->VertexProgram.Current); 122 ASSERT(ctx->FragmentProgram.Current); 123 124 if (ctx->Driver.BindProgram) 125 ctx->Driver.BindProgram(ctx, target, newProg); 126} 127 128 129/** 130 * Delete a list of programs. 131 * \note Not compiled into display lists. 132 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB. 133 */ 134void GLAPIENTRY 135_mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids) 136{ 137 GLint i; 138 GET_CURRENT_CONTEXT(ctx); 139 140 FLUSH_VERTICES(ctx, 0); 141 142 if (n < 0) { 143 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" ); 144 return; 145 } 146 147 for (i = 0; i < n; i++) { 148 if (ids[i] != 0) { 149 struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]); 150 if (prog == &_mesa_DummyProgram) { 151 _mesa_HashRemove(ctx->Shared->Programs, ids[i]); 152 } 153 else if (prog) { 154 /* Unbind program if necessary */ 155 switch (prog->Target) { 156 case GL_VERTEX_PROGRAM_ARB: 157 if (ctx->VertexProgram.Current && 158 ctx->VertexProgram.Current->Base.Id == ids[i]) { 159 /* unbind this currently bound program */ 160 _mesa_BindProgramARB(prog->Target, 0); 161 } 162 break; 163 case GL_FRAGMENT_PROGRAM_ARB: 164 if (ctx->FragmentProgram.Current && 165 ctx->FragmentProgram.Current->Base.Id == ids[i]) { 166 /* unbind this currently bound program */ 167 _mesa_BindProgramARB(prog->Target, 0); 168 } 169 break; 170 default: 171 _mesa_problem(ctx, "bad target in glDeleteProgramsNV"); 172 return; 173 } 174 /* The ID is immediately available for re-use now */ 175 _mesa_HashRemove(ctx->Shared->Programs, ids[i]); 176 _mesa_reference_program(ctx, &prog, NULL); 177 } 178 } 179 } 180} 181 182 183/** 184 * Generate a list of new program identifiers. 185 * \note Not compiled into display lists. 186 * \note Called by both glGenProgramsNV and glGenProgramsARB. 187 */ 188void GLAPIENTRY 189_mesa_GenProgramsARB(GLsizei n, GLuint *ids) 190{ 191 GLuint first; 192 GLuint i; 193 GET_CURRENT_CONTEXT(ctx); 194 195 if (n < 0) { 196 _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms"); 197 return; 198 } 199 200 if (!ids) 201 return; 202 203 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->Programs, n); 204 205 /* Insert pointer to dummy program as placeholder */ 206 for (i = 0; i < (GLuint) n; i++) { 207 _mesa_HashInsert(ctx->Shared->Programs, first + i, &_mesa_DummyProgram); 208 } 209 210 /* Return the program names */ 211 for (i = 0; i < (GLuint) n; i++) { 212 ids[i] = first + i; 213 } 214} 215 216 217/** 218 * Determine if id names a vertex or fragment program. 219 * \note Not compiled into display lists. 220 * \note Called from both glIsProgramNV and glIsProgramARB. 221 * \param id is the program identifier 222 * \return GL_TRUE if id is a program, else GL_FALSE. 223 */ 224GLboolean GLAPIENTRY 225_mesa_IsProgramARB(GLuint id) 226{ 227 struct gl_program *prog = NULL; 228 GET_CURRENT_CONTEXT(ctx); 229 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 230 231 if (id == 0) 232 return GL_FALSE; 233 234 prog = _mesa_lookup_program(ctx, id); 235 if (prog && (prog != &_mesa_DummyProgram)) 236 return GL_TRUE; 237 else 238 return GL_FALSE; 239} 240 241static GLboolean 242get_local_param_pointer(struct gl_context *ctx, const char *func, 243 GLenum target, GLuint index, GLfloat **param) 244{ 245 struct gl_program *prog; 246 GLuint maxParams; 247 248 if (target == GL_VERTEX_PROGRAM_ARB 249 && ctx->Extensions.ARB_vertex_program) { 250 prog = &(ctx->VertexProgram.Current->Base); 251 maxParams = ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams; 252 } 253 else if (target == GL_FRAGMENT_PROGRAM_ARB 254 && ctx->Extensions.ARB_fragment_program) { 255 prog = &(ctx->FragmentProgram.Current->Base); 256 maxParams = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams; 257 } 258 else { 259 _mesa_error(ctx, GL_INVALID_ENUM, 260 "%s(target)", func); 261 return GL_FALSE; 262 } 263 264 if (index >= maxParams) { 265 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 266 return GL_FALSE; 267 } 268 269 if (!prog->LocalParams) { 270 prog->LocalParams = calloc(maxParams, sizeof(float[4])); 271 if (!prog->LocalParams) 272 return GL_FALSE; 273 } 274 275 *param = prog->LocalParams[index]; 276 return GL_TRUE; 277} 278 279 280static GLboolean 281get_env_param_pointer(struct gl_context *ctx, const char *func, 282 GLenum target, GLuint index, GLfloat **param) 283{ 284 if (target == GL_FRAGMENT_PROGRAM_ARB 285 && ctx->Extensions.ARB_fragment_program) { 286 if (index >= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) { 287 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 288 return GL_FALSE; 289 } 290 *param = ctx->FragmentProgram.Parameters[index]; 291 return GL_TRUE; 292 } 293 else if (target == GL_VERTEX_PROGRAM_ARB && 294 ctx->Extensions.ARB_vertex_program) { 295 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) { 296 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 297 return GL_FALSE; 298 } 299 *param = ctx->VertexProgram.Parameters[index]; 300 return GL_TRUE; 301 } else { 302 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); 303 return GL_FALSE; 304 } 305} 306 307void GLAPIENTRY 308_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, 309 const GLvoid *string) 310{ 311 struct gl_program *base; 312 bool failed; 313 GET_CURRENT_CONTEXT(ctx); 314 315 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 316 317 if (!ctx->Extensions.ARB_vertex_program 318 && !ctx->Extensions.ARB_fragment_program) { 319 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()"); 320 return; 321 } 322 323 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) { 324 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)"); 325 return; 326 } 327 328 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { 329 struct gl_vertex_program *prog = ctx->VertexProgram.Current; 330 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog); 331 332 base = & prog->Base; 333 } 334 else if (target == GL_FRAGMENT_PROGRAM_ARB 335 && ctx->Extensions.ARB_fragment_program) { 336 struct gl_fragment_program *prog = ctx->FragmentProgram.Current; 337 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog); 338 339 base = & prog->Base; 340 } 341 else { 342 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)"); 343 return; 344 } 345 346 failed = ctx->Program.ErrorPos != -1; 347 348 if (!failed) { 349 /* finally, give the program to the driver for translation/checking */ 350 if (!ctx->Driver.ProgramStringNotify(ctx, target, base)) { 351 failed = true; 352 _mesa_error(ctx, GL_INVALID_OPERATION, 353 "glProgramStringARB(rejected by driver"); 354 } 355 } 356 357 if (ctx->_Shader->Flags & GLSL_DUMP) { 358 const char *shader_type = 359 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex"; 360 361 fprintf(stderr, "ARB_%s_program source for program %d:\n", 362 shader_type, base->Id); 363 fprintf(stderr, "%s\n", (const char *) string); 364 365 if (failed) { 366 fprintf(stderr, "ARB_%s_program %d failed to compile.\n", 367 shader_type, base->Id); 368 } else { 369 fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n", 370 shader_type, base->Id); 371 _mesa_print_program(base); 372 fprintf(stderr, "\n"); 373 } 374 fflush(stderr); 375 } 376} 377 378 379/** 380 * Set a program env parameter register. 381 * \note Called from the GL API dispatcher. 382 */ 383void GLAPIENTRY 384_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index, 385 GLdouble x, GLdouble y, GLdouble z, GLdouble w) 386{ 387 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, 388 (GLfloat) z, (GLfloat) w); 389} 390 391 392/** 393 * Set a program env parameter register. 394 * \note Called from the GL API dispatcher. 395 */ 396void GLAPIENTRY 397_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index, 398 const GLdouble *params) 399{ 400 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0], 401 (GLfloat) params[1], (GLfloat) params[2], 402 (GLfloat) params[3]); 403} 404 405 406/** 407 * Set a program env parameter register. 408 * \note Called from the GL API dispatcher. 409 */ 410void GLAPIENTRY 411_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, 412 GLfloat x, GLfloat y, GLfloat z, GLfloat w) 413{ 414 GLfloat *param; 415 416 GET_CURRENT_CONTEXT(ctx); 417 418 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 419 420 if (get_env_param_pointer(ctx, "glProgramEnvParameter", 421 target, index, ¶m)) { 422 ASSIGN_4V(param, x, y, z, w); 423 } 424} 425 426 427 428/** 429 * Set a program env parameter register. 430 * \note Called from the GL API dispatcher. 431 */ 432void GLAPIENTRY 433_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index, 434 const GLfloat *params) 435{ 436 GLfloat *param; 437 438 GET_CURRENT_CONTEXT(ctx); 439 440 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 441 442 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv", 443 target, index, ¶m)) { 444 memcpy(param, params, 4 * sizeof(GLfloat)); 445 } 446} 447 448 449void GLAPIENTRY 450_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, 451 const GLfloat *params) 452{ 453 GET_CURRENT_CONTEXT(ctx); 454 GLfloat * dest; 455 456 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 457 458 if (count <= 0) { 459 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)"); 460 } 461 462 if (target == GL_FRAGMENT_PROGRAM_ARB 463 && ctx->Extensions.ARB_fragment_program) { 464 if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) { 465 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)"); 466 return; 467 } 468 dest = ctx->FragmentProgram.Parameters[index]; 469 } 470 else if (target == GL_VERTEX_PROGRAM_ARB 471 && ctx->Extensions.ARB_vertex_program) { 472 if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) { 473 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)"); 474 return; 475 } 476 dest = ctx->VertexProgram.Parameters[index]; 477 } 478 else { 479 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)"); 480 return; 481 } 482 483 memcpy(dest, params, count * 4 * sizeof(GLfloat)); 484} 485 486 487void GLAPIENTRY 488_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index, 489 GLdouble *params) 490{ 491 GET_CURRENT_CONTEXT(ctx); 492 GLfloat *fparam; 493 494 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv", 495 target, index, &fparam)) { 496 COPY_4V(params, fparam); 497 } 498} 499 500 501void GLAPIENTRY 502_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index, 503 GLfloat *params) 504{ 505 GLfloat *param; 506 507 GET_CURRENT_CONTEXT(ctx); 508 509 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv", 510 target, index, ¶m)) { 511 COPY_4V(params, param); 512 } 513} 514 515 516void GLAPIENTRY 517_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index, 518 GLfloat x, GLfloat y, GLfloat z, GLfloat w) 519{ 520 GET_CURRENT_CONTEXT(ctx); 521 GLfloat *param; 522 523 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 524 525 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB", 526 target, index, ¶m)) { 527 ASSERT(index < MAX_PROGRAM_LOCAL_PARAMS); 528 ASSIGN_4V(param, x, y, z, w); 529 } 530} 531 532 533void GLAPIENTRY 534_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index, 535 const GLfloat *params) 536{ 537 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1], 538 params[2], params[3]); 539} 540 541 542void GLAPIENTRY 543_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, 544 const GLfloat *params) 545{ 546 GET_CURRENT_CONTEXT(ctx); 547 GLfloat *dest; 548 549 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 550 551 if (count <= 0) { 552 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramLocalParameters4fv(count)"); 553 } 554 555 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT", 556 target, index, &dest)) { 557 GLuint maxParams = target == GL_FRAGMENT_PROGRAM_ARB ? 558 ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams : 559 ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams; 560 561 if ((index + count) > maxParams) { 562 _mesa_error(ctx, GL_INVALID_VALUE, 563 "glProgramLocalParameters4fvEXT(index + count)"); 564 return; 565 } 566 567 memcpy(dest, params, count * 4 * sizeof(GLfloat)); 568 } 569} 570 571 572void GLAPIENTRY 573_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index, 574 GLdouble x, GLdouble y, 575 GLdouble z, GLdouble w) 576{ 577 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, 578 (GLfloat) z, (GLfloat) w); 579} 580 581 582void GLAPIENTRY 583_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index, 584 const GLdouble *params) 585{ 586 _mesa_ProgramLocalParameter4fARB(target, index, 587 (GLfloat) params[0], (GLfloat) params[1], 588 (GLfloat) params[2], (GLfloat) params[3]); 589} 590 591 592void GLAPIENTRY 593_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index, 594 GLfloat *params) 595{ 596 GLfloat *param; 597 GET_CURRENT_CONTEXT(ctx); 598 599 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT", 600 target, index, ¶m)) { 601 COPY_4V(params, param); 602 } 603} 604 605 606void GLAPIENTRY 607_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index, 608 GLdouble *params) 609{ 610 GLfloat *param; 611 GET_CURRENT_CONTEXT(ctx); 612 613 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT", 614 target, index, ¶m)) { 615 COPY_4V(params, param); 616 } 617} 618 619 620void GLAPIENTRY 621_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params) 622{ 623 const struct gl_program_constants *limits; 624 struct gl_program *prog; 625 GET_CURRENT_CONTEXT(ctx); 626 627 if (target == GL_VERTEX_PROGRAM_ARB 628 && ctx->Extensions.ARB_vertex_program) { 629 prog = &(ctx->VertexProgram.Current->Base); 630 limits = &ctx->Const.Program[MESA_SHADER_VERTEX]; 631 } 632 else if (target == GL_FRAGMENT_PROGRAM_ARB 633 && ctx->Extensions.ARB_fragment_program) { 634 prog = &(ctx->FragmentProgram.Current->Base); 635 limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT]; 636 } 637 else { 638 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(target)"); 639 return; 640 } 641 642 ASSERT(prog); 643 ASSERT(limits); 644 645 /* Queries supported for both vertex and fragment programs */ 646 switch (pname) { 647 case GL_PROGRAM_LENGTH_ARB: 648 *params 649 = prog->String ? (GLint) strlen((char *) prog->String) : 0; 650 return; 651 case GL_PROGRAM_FORMAT_ARB: 652 *params = prog->Format; 653 return; 654 case GL_PROGRAM_BINDING_ARB: 655 *params = prog->Id; 656 return; 657 case GL_PROGRAM_INSTRUCTIONS_ARB: 658 *params = prog->NumInstructions; 659 return; 660 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB: 661 *params = limits->MaxInstructions; 662 return; 663 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB: 664 *params = prog->NumNativeInstructions; 665 return; 666 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB: 667 *params = limits->MaxNativeInstructions; 668 return; 669 case GL_PROGRAM_TEMPORARIES_ARB: 670 *params = prog->NumTemporaries; 671 return; 672 case GL_MAX_PROGRAM_TEMPORARIES_ARB: 673 *params = limits->MaxTemps; 674 return; 675 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB: 676 *params = prog->NumNativeTemporaries; 677 return; 678 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB: 679 *params = limits->MaxNativeTemps; 680 return; 681 case GL_PROGRAM_PARAMETERS_ARB: 682 *params = prog->NumParameters; 683 return; 684 case GL_MAX_PROGRAM_PARAMETERS_ARB: 685 *params = limits->MaxParameters; 686 return; 687 case GL_PROGRAM_NATIVE_PARAMETERS_ARB: 688 *params = prog->NumNativeParameters; 689 return; 690 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB: 691 *params = limits->MaxNativeParameters; 692 return; 693 case GL_PROGRAM_ATTRIBS_ARB: 694 *params = prog->NumAttributes; 695 return; 696 case GL_MAX_PROGRAM_ATTRIBS_ARB: 697 *params = limits->MaxAttribs; 698 return; 699 case GL_PROGRAM_NATIVE_ATTRIBS_ARB: 700 *params = prog->NumNativeAttributes; 701 return; 702 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB: 703 *params = limits->MaxNativeAttribs; 704 return; 705 case GL_PROGRAM_ADDRESS_REGISTERS_ARB: 706 *params = prog->NumAddressRegs; 707 return; 708 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB: 709 *params = limits->MaxAddressRegs; 710 return; 711 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: 712 *params = prog->NumNativeAddressRegs; 713 return; 714 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: 715 *params = limits->MaxNativeAddressRegs; 716 return; 717 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB: 718 *params = limits->MaxLocalParams; 719 return; 720 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB: 721 *params = limits->MaxEnvParams; 722 return; 723 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: 724 /* 725 * XXX we may not really need a driver callback here. 726 * If the number of native instructions, registers, etc. used 727 * are all below the maximums, we could return true. 728 * The spec says that even if this query returns true, there's 729 * no guarantee that the program will run in hardware. 730 */ 731 if (prog->Id == 0) { 732 /* default/null program */ 733 *params = GL_FALSE; 734 } 735 else if (ctx->Driver.IsProgramNative) { 736 /* ask the driver */ 737 *params = ctx->Driver.IsProgramNative( ctx, target, prog ); 738 } 739 else { 740 /* probably running in software */ 741 *params = GL_TRUE; 742 } 743 return; 744 default: 745 /* continue with fragment-program only queries below */ 746 break; 747 } 748 749 /* 750 * The following apply to fragment programs only (at this time) 751 */ 752 if (target == GL_FRAGMENT_PROGRAM_ARB) { 753 const struct gl_fragment_program *fp = ctx->FragmentProgram.Current; 754 switch (pname) { 755 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB: 756 *params = fp->Base.NumNativeAluInstructions; 757 return; 758 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: 759 *params = fp->Base.NumAluInstructions; 760 return; 761 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB: 762 *params = fp->Base.NumTexInstructions; 763 return; 764 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: 765 *params = fp->Base.NumNativeTexInstructions; 766 return; 767 case GL_PROGRAM_TEX_INDIRECTIONS_ARB: 768 *params = fp->Base.NumTexIndirections; 769 return; 770 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: 771 *params = fp->Base.NumNativeTexIndirections; 772 return; 773 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB: 774 *params = limits->MaxAluInstructions; 775 return; 776 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: 777 *params = limits->MaxNativeAluInstructions; 778 return; 779 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB: 780 *params = limits->MaxTexInstructions; 781 return; 782 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: 783 *params = limits->MaxNativeTexInstructions; 784 return; 785 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB: 786 *params = limits->MaxTexIndirections; 787 return; 788 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: 789 *params = limits->MaxNativeTexIndirections; 790 return; 791 default: 792 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); 793 return; 794 } 795 } else { 796 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); 797 return; 798 } 799} 800 801 802void GLAPIENTRY 803_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string) 804{ 805 const struct gl_program *prog; 806 char *dst = (char *) string; 807 GET_CURRENT_CONTEXT(ctx); 808 809 if (target == GL_VERTEX_PROGRAM_ARB) { 810 prog = &(ctx->VertexProgram.Current->Base); 811 } 812 else if (target == GL_FRAGMENT_PROGRAM_ARB) { 813 prog = &(ctx->FragmentProgram.Current->Base); 814 } 815 else { 816 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)"); 817 return; 818 } 819 820 ASSERT(prog); 821 822 if (pname != GL_PROGRAM_STRING_ARB) { 823 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)"); 824 return; 825 } 826 827 if (prog->String) 828 memcpy(dst, prog->String, strlen((char *) prog->String)); 829 else 830 *dst = '\0'; 831} 832