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