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/draw_validate.h" 35#include "main/hash.h" 36 37#include "main/macros.h" 38#include "main/mtypes.h" 39#include "main/shaderapi.h" 40#include "main/state.h" 41#include "program/arbprogparse.h" 42#include "program/program.h" 43#include "program/prog_print.h" 44#include "api_exec_decl.h" 45 46#include "state_tracker/st_program.h" 47 48static void 49flush_vertices_for_program_constants(struct gl_context *ctx, GLenum target) 50{ 51 uint64_t new_driver_state; 52 53 if (target == GL_FRAGMENT_PROGRAM_ARB) { 54 new_driver_state = 55 ctx->DriverFlags.NewShaderConstants[MESA_SHADER_FRAGMENT]; 56 } else { 57 new_driver_state = 58 ctx->DriverFlags.NewShaderConstants[MESA_SHADER_VERTEX]; 59 } 60 61 FLUSH_VERTICES(ctx, new_driver_state ? 0 : _NEW_PROGRAM_CONSTANTS, 0); 62 ctx->NewDriverState |= new_driver_state; 63} 64 65static struct gl_program* 66lookup_or_create_program(GLuint id, GLenum target, const char* caller) 67{ 68 GET_CURRENT_CONTEXT(ctx); 69 struct gl_program* newProg; 70 71 if (id == 0) { 72 /* Bind a default program */ 73 if (target == GL_VERTEX_PROGRAM_ARB) 74 newProg = ctx->Shared->DefaultVertexProgram; 75 else 76 newProg = ctx->Shared->DefaultFragmentProgram; 77 } 78 else { 79 /* Bind a user program */ 80 newProg = _mesa_lookup_program(ctx, id); 81 if (!newProg || newProg == &_mesa_DummyProgram) { 82 bool isGenName = newProg != NULL; 83 /* allocate a new program now */ 84 newProg = ctx->Driver.NewProgram(ctx, _mesa_program_enum_to_shader_stage(target), 85 id, true); 86 if (!newProg) { 87 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 88 return NULL; 89 } 90 _mesa_HashInsert(ctx->Shared->Programs, id, newProg, isGenName); 91 } 92 else if (newProg->Target != target) { 93 _mesa_error(ctx, GL_INVALID_OPERATION, 94 "%s(target mismatch)", caller); 95 return NULL; 96 } 97 } 98 return newProg; 99} 100 101/** 102 * Bind a program (make it current) 103 * \note Called from the GL API dispatcher by both glBindProgramNV 104 * and glBindProgramARB. 105 */ 106void GLAPIENTRY 107_mesa_BindProgramARB(GLenum target, GLuint id) 108{ 109 struct gl_program *curProg, *newProg; 110 GET_CURRENT_CONTEXT(ctx); 111 112 /* Error-check target and get curProg */ 113 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { 114 curProg = ctx->VertexProgram.Current; 115 } 116 else if (target == GL_FRAGMENT_PROGRAM_ARB 117 && ctx->Extensions.ARB_fragment_program) { 118 curProg = ctx->FragmentProgram.Current; 119 } 120 else { 121 _mesa_error(ctx, GL_INVALID_ENUM, "glBindProgramARB(target)"); 122 return; 123 } 124 125 /* 126 * Get pointer to new program to bind. 127 * NOTE: binding to a non-existant program is not an error. 128 * That's supposed to be caught in glBegin. 129 */ 130 newProg = lookup_or_create_program(id, target, "glBindProgram"); 131 if (!newProg) 132 return; 133 134 /** All error checking is complete now **/ 135 136 if (curProg->Id == id) { 137 /* binding same program - no change */ 138 return; 139 } 140 141 /* signal new program (and its new constants) */ 142 FLUSH_VERTICES(ctx, _NEW_PROGRAM, 0); 143 flush_vertices_for_program_constants(ctx, target); 144 145 /* bind newProg */ 146 if (target == GL_VERTEX_PROGRAM_ARB) { 147 _mesa_reference_program(ctx, &ctx->VertexProgram.Current, newProg); 148 } 149 else if (target == GL_FRAGMENT_PROGRAM_ARB) { 150 _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, newProg); 151 } 152 153 _mesa_update_vertex_processing_mode(ctx); 154 _mesa_update_valid_to_render_state(ctx); 155 156 /* Never null pointers */ 157 assert(ctx->VertexProgram.Current); 158 assert(ctx->FragmentProgram.Current); 159} 160 161 162/** 163 * Delete a list of programs. 164 * \note Not compiled into display lists. 165 * \note Called by both glDeleteProgramsNV and glDeleteProgramsARB. 166 */ 167void GLAPIENTRY 168_mesa_DeleteProgramsARB(GLsizei n, const GLuint *ids) 169{ 170 GLint i; 171 GET_CURRENT_CONTEXT(ctx); 172 173 FLUSH_VERTICES(ctx, 0, 0); 174 175 if (n < 0) { 176 _mesa_error( ctx, GL_INVALID_VALUE, "glDeleteProgramsNV" ); 177 return; 178 } 179 180 for (i = 0; i < n; i++) { 181 if (ids[i] != 0) { 182 struct gl_program *prog = _mesa_lookup_program(ctx, ids[i]); 183 if (prog == &_mesa_DummyProgram) { 184 _mesa_HashRemove(ctx->Shared->Programs, ids[i]); 185 } 186 else if (prog) { 187 /* Unbind program if necessary */ 188 switch (prog->Target) { 189 case GL_VERTEX_PROGRAM_ARB: 190 if (ctx->VertexProgram.Current && 191 ctx->VertexProgram.Current->Id == ids[i]) { 192 /* unbind this currently bound program */ 193 _mesa_BindProgramARB(prog->Target, 0); 194 } 195 break; 196 case GL_FRAGMENT_PROGRAM_ARB: 197 if (ctx->FragmentProgram.Current && 198 ctx->FragmentProgram.Current->Id == ids[i]) { 199 /* unbind this currently bound program */ 200 _mesa_BindProgramARB(prog->Target, 0); 201 } 202 break; 203 default: 204 _mesa_problem(ctx, "bad target in glDeleteProgramsNV"); 205 return; 206 } 207 /* The ID is immediately available for re-use now */ 208 _mesa_HashRemove(ctx->Shared->Programs, ids[i]); 209 _mesa_reference_program(ctx, &prog, NULL); 210 } 211 } 212 } 213} 214 215 216/** 217 * Generate a list of new program identifiers. 218 * \note Not compiled into display lists. 219 * \note Called by both glGenProgramsNV and glGenProgramsARB. 220 */ 221void GLAPIENTRY 222_mesa_GenProgramsARB(GLsizei n, GLuint *ids) 223{ 224 GLuint i; 225 GET_CURRENT_CONTEXT(ctx); 226 227 if (n < 0) { 228 _mesa_error(ctx, GL_INVALID_VALUE, "glGenPrograms"); 229 return; 230 } 231 232 if (!ids) 233 return; 234 235 _mesa_HashLockMutex(ctx->Shared->Programs); 236 237 _mesa_HashFindFreeKeys(ctx->Shared->Programs, ids, n); 238 239 /* Insert pointer to dummy program as placeholder */ 240 for (i = 0; i < (GLuint) n; i++) { 241 _mesa_HashInsertLocked(ctx->Shared->Programs, ids[i], 242 &_mesa_DummyProgram, true); 243 } 244 245 _mesa_HashUnlockMutex(ctx->Shared->Programs); 246} 247 248 249/** 250 * Determine if id names a vertex or fragment program. 251 * \note Not compiled into display lists. 252 * \note Called from both glIsProgramNV and glIsProgramARB. 253 * \param id is the program identifier 254 * \return GL_TRUE if id is a program, else GL_FALSE. 255 */ 256GLboolean GLAPIENTRY 257_mesa_IsProgramARB(GLuint id) 258{ 259 struct gl_program *prog = NULL; 260 GET_CURRENT_CONTEXT(ctx); 261 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 262 263 if (id == 0) 264 return GL_FALSE; 265 266 prog = _mesa_lookup_program(ctx, id); 267 if (prog && (prog != &_mesa_DummyProgram)) 268 return GL_TRUE; 269 else 270 return GL_FALSE; 271} 272 273static struct gl_program* 274get_current_program(struct gl_context* ctx, GLenum target, const char* caller) 275{ 276 if (target == GL_VERTEX_PROGRAM_ARB 277 && ctx->Extensions.ARB_vertex_program) { 278 return ctx->VertexProgram.Current; 279 } 280 else if (target == GL_FRAGMENT_PROGRAM_ARB 281 && ctx->Extensions.ARB_fragment_program) { 282 return ctx->FragmentProgram.Current; 283 } 284 else { 285 _mesa_error(ctx, GL_INVALID_ENUM, 286 "%s(target)", caller); 287 return NULL; 288 } 289} 290 291static GLboolean 292get_local_param_pointer(struct gl_context *ctx, const char *func, 293 struct gl_program* prog, GLenum target, 294 GLuint index, unsigned count, GLfloat **param) 295{ 296 if (unlikely(index + count > prog->arb.MaxLocalParams)) { 297 /* If arb.MaxLocalParams == 0, we need to do initialization. */ 298 if (!prog->arb.MaxLocalParams) { 299 unsigned max; 300 301 if (target == GL_VERTEX_PROGRAM_ARB) 302 max = ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams; 303 else 304 max = ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams; 305 306 /* Allocate LocalParams. */ 307 if (!prog->arb.LocalParams) { 308 prog->arb.LocalParams = rzalloc_array_size(prog, sizeof(float[4]), 309 max); 310 if (!prog->arb.LocalParams) { 311 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", func); 312 return GL_FALSE; 313 } 314 } 315 316 /* Initialize MaxLocalParams. */ 317 prog->arb.MaxLocalParams = max; 318 } 319 320 /* Check again after initializing MaxLocalParams. */ 321 if (index + count > prog->arb.MaxLocalParams) { 322 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 323 return GL_FALSE; 324 } 325 } 326 327 *param = prog->arb.LocalParams[index]; 328 return GL_TRUE; 329} 330 331 332static GLboolean 333get_env_param_pointer(struct gl_context *ctx, const char *func, 334 GLenum target, GLuint index, GLfloat **param) 335{ 336 if (target == GL_FRAGMENT_PROGRAM_ARB 337 && ctx->Extensions.ARB_fragment_program) { 338 if (index >= ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) { 339 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 340 return GL_FALSE; 341 } 342 *param = ctx->FragmentProgram.Parameters[index]; 343 return GL_TRUE; 344 } 345 else if (target == GL_VERTEX_PROGRAM_ARB && 346 ctx->Extensions.ARB_vertex_program) { 347 if (index >= ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) { 348 _mesa_error(ctx, GL_INVALID_VALUE, "%s(index)", func); 349 return GL_FALSE; 350 } 351 *param = ctx->VertexProgram.Parameters[index]; 352 return GL_TRUE; 353 } else { 354 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func); 355 return GL_FALSE; 356 } 357} 358 359static void 360set_program_string(struct gl_program *prog, GLenum target, GLenum format, GLsizei len, 361 const GLvoid *string) 362{ 363 bool failed; 364 GET_CURRENT_CONTEXT(ctx); 365 366 FLUSH_VERTICES(ctx, _NEW_PROGRAM, 0); 367 368 if (!ctx->Extensions.ARB_vertex_program 369 && !ctx->Extensions.ARB_fragment_program) { 370 _mesa_error(ctx, GL_INVALID_OPERATION, "glProgramStringARB()"); 371 return; 372 } 373 374 if (format != GL_PROGRAM_FORMAT_ASCII_ARB) { 375 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(format)"); 376 return; 377 } 378 379#ifdef ENABLE_SHADER_CACHE 380 GLcharARB *replacement; 381 382 gl_shader_stage stage = _mesa_program_enum_to_shader_stage(target); 383 384 uint8_t sha1[SHA1_DIGEST_LENGTH]; 385 _mesa_sha1_compute(string, strlen(string), sha1); 386 387 /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace 388 * if corresponding entry found from MESA_SHADER_READ_PATH. 389 */ 390 _mesa_dump_shader_source(stage, string, sha1); 391 392 replacement = _mesa_read_shader_source(stage, string, sha1); 393 if (replacement) 394 string = replacement; 395#endif /* ENABLE_SHADER_CACHE */ 396 397 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { 398 _mesa_parse_arb_vertex_program(ctx, target, string, len, prog); 399 } 400 else if (target == GL_FRAGMENT_PROGRAM_ARB 401 && ctx->Extensions.ARB_fragment_program) { 402 _mesa_parse_arb_fragment_program(ctx, target, string, len, prog); 403 } 404 else { 405 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)"); 406 return; 407 } 408 409 failed = ctx->Program.ErrorPos != -1; 410 411 if (!failed) { 412 /* finally, give the program to the driver for translation/checking */ 413 if (!st_program_string_notify(ctx, target, prog)) { 414 failed = true; 415 _mesa_error(ctx, GL_INVALID_OPERATION, 416 "glProgramStringARB(rejected by driver"); 417 } 418 } 419 420 _mesa_update_vertex_processing_mode(ctx); 421 _mesa_update_valid_to_render_state(ctx); 422 423 if (ctx->_Shader->Flags & GLSL_DUMP) { 424 const char *shader_type = 425 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex"; 426 427 fprintf(stderr, "ARB_%s_program source for program %d:\n", 428 shader_type, prog->Id); 429 fprintf(stderr, "%s\n", (const char *) string); 430 431 if (failed) { 432 fprintf(stderr, "ARB_%s_program %d failed to compile.\n", 433 shader_type, prog->Id); 434 } else { 435 fprintf(stderr, "Mesa IR for ARB_%s_program %d:\n", 436 shader_type, prog->Id); 437 _mesa_print_program(prog); 438 fprintf(stderr, "\n"); 439 } 440 fflush(stderr); 441 } 442 443 /* Capture vp-*.shader_test/fp-*.shader_test files. */ 444 const char *capture_path = _mesa_get_shader_capture_path(); 445 if (capture_path != NULL) { 446 FILE *file; 447 const char *shader_type = 448 target == GL_FRAGMENT_PROGRAM_ARB ? "fragment" : "vertex"; 449 char *filename = 450 ralloc_asprintf(NULL, "%s/%cp-%u.shader_test", 451 capture_path, shader_type[0], prog->Id); 452 453 file = fopen(filename, "w"); 454 if (file) { 455 fprintf(file, 456 "[require]\nGL_ARB_%s_program\n\n[%s program]\n%s\n", 457 shader_type, shader_type, (const char *) string); 458 fclose(file); 459 } else { 460 _mesa_warning(ctx, "Failed to open %s", filename); 461 } 462 ralloc_free(filename); 463 } 464} 465 466void GLAPIENTRY 467_mesa_ProgramStringARB(GLenum target, GLenum format, GLsizei len, 468 const GLvoid *string) 469{ 470 GET_CURRENT_CONTEXT(ctx); 471 if (target == GL_VERTEX_PROGRAM_ARB && ctx->Extensions.ARB_vertex_program) { 472 set_program_string(ctx->VertexProgram.Current, target, format, len, string); 473 } 474 else if (target == GL_FRAGMENT_PROGRAM_ARB 475 && ctx->Extensions.ARB_fragment_program) { 476 set_program_string(ctx->FragmentProgram.Current, target, format, len, string); 477 } 478 else { 479 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramStringARB(target)"); 480 return; 481 } 482} 483 484void GLAPIENTRY 485_mesa_NamedProgramStringEXT(GLuint program, GLenum target, GLenum format, GLsizei len, 486 const GLvoid *string) 487{ 488 struct gl_program* prog = lookup_or_create_program(program, target, "glNamedProgramStringEXT"); 489 490 if (!prog) { 491 return; 492 } 493 set_program_string(prog, target, format, len, string); 494} 495 496 497/** 498 * Set a program env parameter register. 499 * \note Called from the GL API dispatcher. 500 */ 501void GLAPIENTRY 502_mesa_ProgramEnvParameter4dARB(GLenum target, GLuint index, 503 GLdouble x, GLdouble y, GLdouble z, GLdouble w) 504{ 505 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, 506 (GLfloat) z, (GLfloat) w); 507} 508 509 510/** 511 * Set a program env parameter register. 512 * \note Called from the GL API dispatcher. 513 */ 514void GLAPIENTRY 515_mesa_ProgramEnvParameter4dvARB(GLenum target, GLuint index, 516 const GLdouble *params) 517{ 518 _mesa_ProgramEnvParameter4fARB(target, index, (GLfloat) params[0], 519 (GLfloat) params[1], (GLfloat) params[2], 520 (GLfloat) params[3]); 521} 522 523 524/** 525 * Set a program env parameter register. 526 * \note Called from the GL API dispatcher. 527 */ 528void GLAPIENTRY 529_mesa_ProgramEnvParameter4fARB(GLenum target, GLuint index, 530 GLfloat x, GLfloat y, GLfloat z, GLfloat w) 531{ 532 GLfloat *param; 533 534 GET_CURRENT_CONTEXT(ctx); 535 536 flush_vertices_for_program_constants(ctx, target); 537 538 if (get_env_param_pointer(ctx, "glProgramEnvParameter", 539 target, index, ¶m)) { 540 ASSIGN_4V(param, x, y, z, w); 541 } 542} 543 544 545 546/** 547 * Set a program env parameter register. 548 * \note Called from the GL API dispatcher. 549 */ 550void GLAPIENTRY 551_mesa_ProgramEnvParameter4fvARB(GLenum target, GLuint index, 552 const GLfloat *params) 553{ 554 GLfloat *param; 555 556 GET_CURRENT_CONTEXT(ctx); 557 558 flush_vertices_for_program_constants(ctx, target); 559 560 if (get_env_param_pointer(ctx, "glProgramEnvParameter4fv", 561 target, index, ¶m)) { 562 memcpy(param, params, 4 * sizeof(GLfloat)); 563 } 564} 565 566 567void GLAPIENTRY 568_mesa_ProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, 569 const GLfloat *params) 570{ 571 GET_CURRENT_CONTEXT(ctx); 572 GLfloat * dest; 573 574 flush_vertices_for_program_constants(ctx, target); 575 576 if (count <= 0) { 577 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(count)"); 578 } 579 580 if (target == GL_FRAGMENT_PROGRAM_ARB 581 && ctx->Extensions.ARB_fragment_program) { 582 if ((index + count) > ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxEnvParams) { 583 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)"); 584 return; 585 } 586 dest = ctx->FragmentProgram.Parameters[index]; 587 } 588 else if (target == GL_VERTEX_PROGRAM_ARB 589 && ctx->Extensions.ARB_vertex_program) { 590 if ((index + count) > ctx->Const.Program[MESA_SHADER_VERTEX].MaxEnvParams) { 591 _mesa_error(ctx, GL_INVALID_VALUE, "glProgramEnvParameters4fv(index + count)"); 592 return; 593 } 594 dest = ctx->VertexProgram.Parameters[index]; 595 } 596 else { 597 _mesa_error(ctx, GL_INVALID_ENUM, "glProgramEnvParameters4fv(target)"); 598 return; 599 } 600 601 memcpy(dest, params, count * 4 * sizeof(GLfloat)); 602} 603 604 605void GLAPIENTRY 606_mesa_GetProgramEnvParameterdvARB(GLenum target, GLuint index, 607 GLdouble *params) 608{ 609 GET_CURRENT_CONTEXT(ctx); 610 GLfloat *fparam; 611 612 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterdv", 613 target, index, &fparam)) { 614 COPY_4V(params, fparam); 615 } 616} 617 618 619void GLAPIENTRY 620_mesa_GetProgramEnvParameterfvARB(GLenum target, GLuint index, 621 GLfloat *params) 622{ 623 GLfloat *param; 624 625 GET_CURRENT_CONTEXT(ctx); 626 627 if (get_env_param_pointer(ctx, "glGetProgramEnvParameterfv", 628 target, index, ¶m)) { 629 COPY_4V(params, param); 630 } 631} 632 633 634void GLAPIENTRY 635_mesa_ProgramLocalParameter4fARB(GLenum target, GLuint index, 636 GLfloat x, GLfloat y, GLfloat z, GLfloat w) 637{ 638 GET_CURRENT_CONTEXT(ctx); 639 GLfloat *param; 640 struct gl_program* prog = get_current_program(ctx, target, "glProgramLocalParameterARB"); 641 if (!prog) { 642 return; 643 } 644 645 flush_vertices_for_program_constants(ctx, target); 646 647 if (get_local_param_pointer(ctx, "glProgramLocalParameterARB", 648 prog, target, index, 1, ¶m)) { 649 assert(index < MAX_PROGRAM_LOCAL_PARAMS); 650 ASSIGN_4V(param, x, y, z, w); 651 } 652} 653 654void GLAPIENTRY 655_mesa_NamedProgramLocalParameter4fEXT(GLuint program, GLenum target, GLuint index, 656 GLfloat x, GLfloat y, GLfloat z, GLfloat w) 657{ 658 GET_CURRENT_CONTEXT(ctx); 659 GLfloat *param; 660 struct gl_program* prog = lookup_or_create_program(program, target, 661 "glNamedProgramLocalParameter4fEXT"); 662 663 if (!prog) { 664 return; 665 } 666 667 if ((target == GL_VERTEX_PROGRAM_ARB && prog == ctx->VertexProgram.Current) || 668 (target == GL_FRAGMENT_PROGRAM_ARB && prog == ctx->FragmentProgram.Current)) { 669 flush_vertices_for_program_constants(ctx, target); 670 } 671 672 if (get_local_param_pointer(ctx, "glNamedProgramLocalParameter4fEXT", 673 prog, target, index, 1, ¶m)) { 674 assert(index < MAX_PROGRAM_LOCAL_PARAMS); 675 ASSIGN_4V(param, x, y, z, w); 676 } 677} 678 679 680void GLAPIENTRY 681_mesa_ProgramLocalParameter4fvARB(GLenum target, GLuint index, 682 const GLfloat *params) 683{ 684 _mesa_ProgramLocalParameter4fARB(target, index, params[0], params[1], 685 params[2], params[3]); 686} 687 688 689void GLAPIENTRY 690_mesa_NamedProgramLocalParameter4fvEXT(GLuint program, GLenum target, GLuint index, 691 const GLfloat *params) 692{ 693 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, params[0], 694 params[1], params[2], params[3]); 695} 696 697 698static void 699program_local_parameters4fv(struct gl_program* prog, GLuint index, GLsizei count, 700 const GLfloat *params, const char* caller) 701{ 702 GET_CURRENT_CONTEXT(ctx); 703 GLfloat *dest; 704 flush_vertices_for_program_constants(ctx, prog->Target); 705 706 if (count <= 0) { 707 _mesa_error(ctx, GL_INVALID_VALUE, "%s(count)", caller); 708 } 709 710 if (get_local_param_pointer(ctx, caller, 711 prog, prog->Target, index, count, &dest)) 712 memcpy(dest, params, count * 4 * sizeof(GLfloat)); 713} 714 715 716void GLAPIENTRY 717_mesa_ProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, 718 const GLfloat *params) 719{ 720 GET_CURRENT_CONTEXT(ctx); 721 struct gl_program* prog = get_current_program(ctx, target, 722 "glProgramLocalParameters4fv"); 723 if (!prog) { 724 return; 725 } 726 727 program_local_parameters4fv(prog, index, count, params, 728 "glProgramLocalParameters4fv"); 729} 730 731void GLAPIENTRY 732_mesa_NamedProgramLocalParameters4fvEXT(GLuint program, GLenum target, GLuint index, 733 GLsizei count, const GLfloat *params) 734{ 735 struct gl_program* prog = 736 lookup_or_create_program(program, target, 737 "glNamedProgramLocalParameters4fvEXT"); 738 if (!prog) { 739 return; 740 } 741 742 program_local_parameters4fv(prog, index, count, params, 743 "glNamedProgramLocalParameters4fvEXT"); 744} 745 746 747void GLAPIENTRY 748_mesa_ProgramLocalParameter4dARB(GLenum target, GLuint index, 749 GLdouble x, GLdouble y, 750 GLdouble z, GLdouble w) 751{ 752 _mesa_ProgramLocalParameter4fARB(target, index, (GLfloat) x, (GLfloat) y, 753 (GLfloat) z, (GLfloat) w); 754} 755 756 757void GLAPIENTRY 758_mesa_NamedProgramLocalParameter4dEXT(GLuint program, GLenum target, GLuint index, 759 GLdouble x, GLdouble y, 760 GLdouble z, GLdouble w) 761{ 762 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, (GLfloat) x, (GLfloat) y, 763 (GLfloat) z, (GLfloat) w); 764} 765 766 767void GLAPIENTRY 768_mesa_ProgramLocalParameter4dvARB(GLenum target, GLuint index, 769 const GLdouble *params) 770{ 771 _mesa_ProgramLocalParameter4fARB(target, index, 772 (GLfloat) params[0], (GLfloat) params[1], 773 (GLfloat) params[2], (GLfloat) params[3]); 774} 775 776 777void GLAPIENTRY 778_mesa_NamedProgramLocalParameter4dvEXT(GLuint program, GLenum target, GLuint index, 779 const GLdouble *params) 780{ 781 _mesa_NamedProgramLocalParameter4fEXT(program, target, index, 782 (GLfloat) params[0], (GLfloat) params[1], 783 (GLfloat) params[2], (GLfloat) params[3]); 784} 785 786 787void GLAPIENTRY 788_mesa_GetProgramLocalParameterfvARB(GLenum target, GLuint index, 789 GLfloat *params) 790{ 791 GLfloat *param; 792 GET_CURRENT_CONTEXT(ctx); 793 struct gl_program* prog = get_current_program(ctx, target, "glGetProgramLocalParameterfvARB"); 794 if (!prog) { 795 return; 796 } 797 798 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT", 799 prog, target, index, 1, ¶m)) { 800 COPY_4V(params, param); 801 } 802} 803 804 805void GLAPIENTRY 806_mesa_GetNamedProgramLocalParameterfvEXT(GLuint program, GLenum target, GLuint index, 807 GLfloat *params) 808{ 809 GLfloat *param; 810 GET_CURRENT_CONTEXT(ctx); 811 struct gl_program* prog = lookup_or_create_program(program, target, 812 "glGetNamedProgramLocalParameterfvEXT"); 813 if (!prog) { 814 return; 815 } 816 817 if (get_local_param_pointer(ctx, "glGetNamedProgramLocalParameterfvEXT", 818 prog, target, index, 1, ¶m)) { 819 COPY_4V(params, param); 820 } 821} 822 823 824void GLAPIENTRY 825_mesa_GetProgramLocalParameterdvARB(GLenum target, GLuint index, 826 GLdouble *params) 827{ 828 GLfloat *param; 829 GET_CURRENT_CONTEXT(ctx); 830 struct gl_program* prog = get_current_program(ctx, target, "glGetProgramLocalParameterdvARB"); 831 if (!prog) { 832 return; 833 } 834 835 if (get_local_param_pointer(ctx, "glProgramLocalParameters4fvEXT", 836 prog, target, index, 1, ¶m)) { 837 COPY_4V(params, param); 838 } 839} 840 841 842void GLAPIENTRY 843_mesa_GetNamedProgramLocalParameterdvEXT(GLuint program, GLenum target, GLuint index, 844 GLdouble *params) 845{ 846 GLfloat *param; 847 GET_CURRENT_CONTEXT(ctx); 848 struct gl_program* prog = lookup_or_create_program(program, target, 849 "glGetNamedProgramLocalParameterdvEXT"); 850 if (!prog) { 851 return; 852 } 853 854 if (get_local_param_pointer(ctx, "glGetNamedProgramLocalParameterdvEXT", 855 prog, target, index, 1, ¶m)) { 856 COPY_4V(params, param); 857 } 858} 859 860 861static void 862get_program_iv(struct gl_program *prog, GLenum target, GLenum pname, 863 GLint *params) 864{ 865 const struct gl_program_constants *limits; 866 867 GET_CURRENT_CONTEXT(ctx); 868 869 if (target == GL_VERTEX_PROGRAM_ARB) { 870 limits = &ctx->Const.Program[MESA_SHADER_VERTEX]; 871 } 872 else { 873 limits = &ctx->Const.Program[MESA_SHADER_FRAGMENT]; 874 } 875 876 assert(prog); 877 assert(limits); 878 879 /* Queries supported for both vertex and fragment programs */ 880 switch (pname) { 881 case GL_PROGRAM_LENGTH_ARB: 882 *params 883 = prog->String ? (GLint) strlen((char *) prog->String) : 0; 884 return; 885 case GL_PROGRAM_FORMAT_ARB: 886 *params = prog->Format; 887 return; 888 case GL_PROGRAM_BINDING_ARB: 889 *params = prog->Id; 890 return; 891 case GL_PROGRAM_INSTRUCTIONS_ARB: 892 *params = prog->arb.NumInstructions; 893 return; 894 case GL_MAX_PROGRAM_INSTRUCTIONS_ARB: 895 *params = limits->MaxInstructions; 896 return; 897 case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB: 898 *params = prog->arb.NumNativeInstructions; 899 return; 900 case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB: 901 *params = limits->MaxNativeInstructions; 902 return; 903 case GL_PROGRAM_TEMPORARIES_ARB: 904 *params = prog->arb.NumTemporaries; 905 return; 906 case GL_MAX_PROGRAM_TEMPORARIES_ARB: 907 *params = limits->MaxTemps; 908 return; 909 case GL_PROGRAM_NATIVE_TEMPORARIES_ARB: 910 *params = prog->arb.NumNativeTemporaries; 911 return; 912 case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB: 913 *params = limits->MaxNativeTemps; 914 return; 915 case GL_PROGRAM_PARAMETERS_ARB: 916 *params = prog->arb.NumParameters; 917 return; 918 case GL_MAX_PROGRAM_PARAMETERS_ARB: 919 *params = limits->MaxParameters; 920 return; 921 case GL_PROGRAM_NATIVE_PARAMETERS_ARB: 922 *params = prog->arb.NumNativeParameters; 923 return; 924 case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB: 925 *params = limits->MaxNativeParameters; 926 return; 927 case GL_PROGRAM_ATTRIBS_ARB: 928 *params = prog->arb.NumAttributes; 929 return; 930 case GL_MAX_PROGRAM_ATTRIBS_ARB: 931 *params = limits->MaxAttribs; 932 return; 933 case GL_PROGRAM_NATIVE_ATTRIBS_ARB: 934 *params = prog->arb.NumNativeAttributes; 935 return; 936 case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB: 937 *params = limits->MaxNativeAttribs; 938 return; 939 case GL_PROGRAM_ADDRESS_REGISTERS_ARB: 940 *params = prog->arb.NumAddressRegs; 941 return; 942 case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB: 943 *params = limits->MaxAddressRegs; 944 return; 945 case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: 946 *params = prog->arb.NumNativeAddressRegs; 947 return; 948 case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB: 949 *params = limits->MaxNativeAddressRegs; 950 return; 951 case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB: 952 *params = limits->MaxLocalParams; 953 return; 954 case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB: 955 *params = limits->MaxEnvParams; 956 return; 957 case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB: 958 /* 959 * XXX we may not really need a driver callback here. 960 * If the number of native instructions, registers, etc. used 961 * are all below the maximums, we could return true. 962 * The spec says that even if this query returns true, there's 963 * no guarantee that the program will run in hardware. 964 */ 965 if (prog->Id == 0) { 966 /* default/null program */ 967 *params = GL_FALSE; 968 } 969 else { 970 /* probably running in software */ 971 *params = GL_TRUE; 972 } 973 return; 974 default: 975 /* continue with fragment-program only queries below */ 976 break; 977 } 978 979 /* 980 * The following apply to fragment programs only (at this time) 981 */ 982 if (target == GL_FRAGMENT_PROGRAM_ARB) { 983 const struct gl_program *fp = ctx->FragmentProgram.Current; 984 switch (pname) { 985 case GL_PROGRAM_ALU_INSTRUCTIONS_ARB: 986 *params = fp->arb.NumNativeAluInstructions; 987 return; 988 case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: 989 *params = fp->arb.NumAluInstructions; 990 return; 991 case GL_PROGRAM_TEX_INSTRUCTIONS_ARB: 992 *params = fp->arb.NumTexInstructions; 993 return; 994 case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: 995 *params = fp->arb.NumNativeTexInstructions; 996 return; 997 case GL_PROGRAM_TEX_INDIRECTIONS_ARB: 998 *params = fp->arb.NumTexIndirections; 999 return; 1000 case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: 1001 *params = fp->arb.NumNativeTexIndirections; 1002 return; 1003 case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB: 1004 *params = limits->MaxAluInstructions; 1005 return; 1006 case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB: 1007 *params = limits->MaxNativeAluInstructions; 1008 return; 1009 case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB: 1010 *params = limits->MaxTexInstructions; 1011 return; 1012 case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB: 1013 *params = limits->MaxNativeTexInstructions; 1014 return; 1015 case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB: 1016 *params = limits->MaxTexIndirections; 1017 return; 1018 case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB: 1019 *params = limits->MaxNativeTexIndirections; 1020 return; 1021 default: 1022 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); 1023 return; 1024 } 1025 } else { 1026 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramivARB(pname)"); 1027 return; 1028 } 1029} 1030 1031 1032void GLAPIENTRY 1033_mesa_GetProgramivARB(GLenum target, GLenum pname, GLint *params) 1034{ 1035 GET_CURRENT_CONTEXT(ctx); 1036 struct gl_program* prog = get_current_program(ctx, target, 1037 "glGetProgramivARB"); 1038 if (!prog) { 1039 return; 1040 } 1041 get_program_iv(prog, target, pname, params); 1042} 1043 1044void GLAPIENTRY 1045_mesa_GetNamedProgramivEXT(GLuint program, GLenum target, GLenum pname, 1046 GLint *params) 1047{ 1048 struct gl_program* prog; 1049 if (pname == GL_PROGRAM_BINDING_ARB) { 1050 _mesa_GetProgramivARB(target, pname, params); 1051 return; 1052 } 1053 prog = lookup_or_create_program(program, target, 1054 "glGetNamedProgramivEXT"); 1055 if (!prog) { 1056 return; 1057 } 1058 get_program_iv(prog, target, pname, params); 1059} 1060 1061 1062void GLAPIENTRY 1063_mesa_GetProgramStringARB(GLenum target, GLenum pname, GLvoid *string) 1064{ 1065 const struct gl_program *prog; 1066 char *dst = (char *) string; 1067 GET_CURRENT_CONTEXT(ctx); 1068 1069 if (target == GL_VERTEX_PROGRAM_ARB) { 1070 prog = ctx->VertexProgram.Current; 1071 } 1072 else if (target == GL_FRAGMENT_PROGRAM_ARB) { 1073 prog = ctx->FragmentProgram.Current; 1074 } 1075 else { 1076 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(target)"); 1077 return; 1078 } 1079 1080 assert(prog); 1081 1082 if (pname != GL_PROGRAM_STRING_ARB) { 1083 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramStringARB(pname)"); 1084 return; 1085 } 1086 1087 if (prog->String) 1088 memcpy(dst, prog->String, strlen((char *) prog->String)); 1089 else 1090 *dst = '\0'; 1091} 1092 1093 1094void GLAPIENTRY 1095_mesa_GetNamedProgramStringEXT(GLuint program, GLenum target, 1096 GLenum pname, GLvoid *string) { 1097 char *dst = (char *) string; 1098 GET_CURRENT_CONTEXT(ctx); 1099 struct gl_program* prog = lookup_or_create_program(program, target, 1100 "glGetNamedProgramStringEXT"); 1101 if (!prog) 1102 return; 1103 1104 if (pname != GL_PROGRAM_STRING_ARB) { 1105 _mesa_error(ctx, GL_INVALID_ENUM, "glGetNamedProgramStringEXT(pname)"); 1106 return; 1107 } 1108 1109 if (prog->String) 1110 memcpy(dst, prog->String, strlen((char *) prog->String)); 1111 else 1112 *dst = '\0'; 1113} 1114