uniforms.c revision 2f5bf20e44d509fa3afbe2cfbb9bb65347daea6a
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009-2010 VMware, Inc. 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 uniforms.c 27 * Functions related to GLSL uniform variables. 28 * \author Brian Paul 29 */ 30 31/** 32 * XXX things to do: 33 * 1. Check that the right error code is generated for all _mesa_error() calls. 34 * 2. Insert FLUSH_VERTICES calls in various places 35 */ 36 37 38#include "main/glheader.h" 39#include "main/context.h" 40#include "main/dispatch.h" 41#include "main/shaderapi.h" 42#include "main/shaderobj.h" 43#include "main/uniforms.h" 44#include "program/prog_parameter.h" 45#include "program/prog_statevars.h" 46#include "program/prog_uniform.h" 47 48 49 50static GLenum 51base_uniform_type(GLenum type) 52{ 53 switch (type) { 54#if 0 /* not needed, for now */ 55 case GL_BOOL: 56 case GL_BOOL_VEC2: 57 case GL_BOOL_VEC3: 58 case GL_BOOL_VEC4: 59 return GL_BOOL; 60#endif 61 case GL_FLOAT: 62 case GL_FLOAT_VEC2: 63 case GL_FLOAT_VEC3: 64 case GL_FLOAT_VEC4: 65 return GL_FLOAT; 66 case GL_UNSIGNED_INT: 67 case GL_UNSIGNED_INT_VEC2: 68 case GL_UNSIGNED_INT_VEC3: 69 case GL_UNSIGNED_INT_VEC4: 70 return GL_UNSIGNED_INT; 71 case GL_INT: 72 case GL_INT_VEC2: 73 case GL_INT_VEC3: 74 case GL_INT_VEC4: 75 return GL_INT; 76 default: 77 _mesa_problem(NULL, "Invalid type in base_uniform_type()"); 78 return GL_FLOAT; 79 } 80} 81 82 83static GLboolean 84is_boolean_type(GLenum type) 85{ 86 switch (type) { 87 case GL_BOOL: 88 case GL_BOOL_VEC2: 89 case GL_BOOL_VEC3: 90 case GL_BOOL_VEC4: 91 return GL_TRUE; 92 default: 93 return GL_FALSE; 94 } 95} 96 97 98static GLboolean 99is_sampler_type(GLenum type) 100{ 101 switch (type) { 102 case GL_SAMPLER_1D: 103 case GL_SAMPLER_2D: 104 case GL_SAMPLER_3D: 105 case GL_SAMPLER_CUBE: 106 case GL_SAMPLER_1D_SHADOW: 107 case GL_SAMPLER_2D_SHADOW: 108 case GL_SAMPLER_2D_RECT_ARB: 109 case GL_SAMPLER_2D_RECT_SHADOW_ARB: 110 case GL_SAMPLER_1D_ARRAY_EXT: 111 case GL_SAMPLER_2D_ARRAY_EXT: 112 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: 113 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: 114 return GL_TRUE; 115 default: 116 return GL_FALSE; 117 } 118} 119 120 121static struct gl_program_parameter * 122get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index) 123{ 124 const struct gl_program *prog = NULL; 125 GLint progPos; 126 127 progPos = shProg->Uniforms->Uniforms[index].VertPos; 128 if (progPos >= 0) { 129 prog = &shProg->VertexProgram->Base; 130 } 131 else { 132 progPos = shProg->Uniforms->Uniforms[index].FragPos; 133 if (progPos >= 0) { 134 prog = &shProg->FragmentProgram->Base; 135 } else { 136 progPos = shProg->Uniforms->Uniforms[index].GeomPos; 137 if (progPos >= 0) { 138 prog = &shProg->GeometryProgram->Base; 139 } 140 } 141 } 142 143 if (!prog || progPos < 0) 144 return NULL; /* should never happen */ 145 146 return &prog->Parameters->Parameters[progPos]; 147} 148 149 150/** 151 * Called by glGetActiveUniform(). 152 */ 153static void 154_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, 155 GLsizei maxLength, GLsizei *length, GLint *size, 156 GLenum *type, GLchar *nameOut) 157{ 158 const struct gl_shader_program *shProg; 159 const struct gl_program *prog = NULL; 160 const struct gl_program_parameter *param; 161 GLint progPos; 162 163 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); 164 if (!shProg) 165 return; 166 167 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) { 168 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); 169 return; 170 } 171 172 progPos = shProg->Uniforms->Uniforms[index].VertPos; 173 if (progPos >= 0) { 174 prog = &shProg->VertexProgram->Base; 175 } 176 else { 177 progPos = shProg->Uniforms->Uniforms[index].FragPos; 178 if (progPos >= 0) { 179 prog = &shProg->FragmentProgram->Base; 180 } else { 181 progPos = shProg->Uniforms->Uniforms[index].GeomPos; 182 if (progPos >= 0) { 183 prog = &shProg->GeometryProgram->Base; 184 } 185 } 186 } 187 188 if (!prog || progPos < 0) 189 return; /* should never happen */ 190 191 ASSERT(progPos < prog->Parameters->NumParameters); 192 param = &prog->Parameters->Parameters[progPos]; 193 194 if (nameOut) { 195 _mesa_copy_string(nameOut, maxLength, length, param->Name); 196 } 197 198 if (size) { 199 GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); 200 if ((GLint) param->Size > typeSize) { 201 /* This is an array. 202 * Array elements are placed on vector[4] boundaries so they're 203 * a multiple of four floats. We round typeSize up to next multiple 204 * of four to get the right size below. 205 */ 206 typeSize = (typeSize + 3) & ~3; 207 } 208 /* Note that the returned size is in units of the <type>, not bytes */ 209 *size = param->Size / typeSize; 210 } 211 212 if (type) { 213 *type = param->DataType; 214 } 215} 216 217 218 219static void 220get_matrix_dims(GLenum type, GLint *rows, GLint *cols) 221{ 222 switch (type) { 223 case GL_FLOAT_MAT2: 224 *rows = *cols = 2; 225 break; 226 case GL_FLOAT_MAT2x3: 227 *rows = 3; 228 *cols = 2; 229 break; 230 case GL_FLOAT_MAT2x4: 231 *rows = 4; 232 *cols = 2; 233 break; 234 case GL_FLOAT_MAT3: 235 *rows = 3; 236 *cols = 3; 237 break; 238 case GL_FLOAT_MAT3x2: 239 *rows = 2; 240 *cols = 3; 241 break; 242 case GL_FLOAT_MAT3x4: 243 *rows = 4; 244 *cols = 3; 245 break; 246 case GL_FLOAT_MAT4: 247 *rows = 4; 248 *cols = 4; 249 break; 250 case GL_FLOAT_MAT4x2: 251 *rows = 2; 252 *cols = 4; 253 break; 254 case GL_FLOAT_MAT4x3: 255 *rows = 3; 256 *cols = 4; 257 break; 258 default: 259 *rows = *cols = 0; 260 } 261} 262 263 264/** 265 * Determine the number of rows and columns occupied by a uniform 266 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4), 267 * the number of rows = 1 and cols = number of elements in the vector. 268 */ 269static void 270get_uniform_rows_cols(const struct gl_program_parameter *p, 271 GLint *rows, GLint *cols) 272{ 273 get_matrix_dims(p->DataType, rows, cols); 274 if (*rows == 0 && *cols == 0) { 275 /* not a matrix type, probably a float or vector */ 276 if (p->Size <= 4) { 277 *rows = 1; 278 *cols = p->Size; 279 } 280 else { 281 *rows = p->Size / 4 + 1; 282 if (p->Size % 4 == 0) 283 *cols = 4; 284 else 285 *cols = p->Size % 4; 286 } 287 } 288} 289 290 291/** 292 * Helper for get_uniform[fi]v() functions. 293 * Given a shader program name and uniform location, return a pointer 294 * to the shader program and return the program parameter position. 295 */ 296static void 297lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location, 298 struct gl_program **progOut, GLint *paramPosOut) 299{ 300 struct gl_shader_program *shProg 301 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v"); 302 struct gl_program *prog = NULL; 303 GLint progPos = -1; 304 305 /* if shProg is NULL, we'll have already recorded an error */ 306 307 if (shProg) { 308 if (!shProg->Uniforms || 309 location < 0 || 310 location >= (GLint) shProg->Uniforms->NumUniforms) { 311 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); 312 } 313 else { 314 /* OK, find the gl_program and program parameter location */ 315 progPos = shProg->Uniforms->Uniforms[location].VertPos; 316 if (progPos >= 0) { 317 prog = &shProg->VertexProgram->Base; 318 } 319 else { 320 progPos = shProg->Uniforms->Uniforms[location].FragPos; 321 if (progPos >= 0) { 322 prog = &shProg->FragmentProgram->Base; 323 } else { 324 progPos = shProg->Uniforms->Uniforms[location].GeomPos; 325 if (progPos >= 0) { 326 prog = &shProg->GeometryProgram->Base; 327 } 328 } 329 } 330 } 331 } 332 333 *progOut = prog; 334 *paramPosOut = progPos; 335} 336 337 338/** 339 * GLGL uniform arrays and structs require special handling. 340 * 341 * The GL_ARB_shader_objects spec says that if you use 342 * glGetUniformLocation to get the location of an array, you CANNOT 343 * access other elements of the array by adding an offset to the 344 * returned location. For example, you must call 345 * glGetUniformLocation("foo[16]") if you want to set the 16th element 346 * of the array with glUniform(). 347 * 348 * HOWEVER, some other OpenGL drivers allow accessing array elements 349 * by adding an offset to the returned array location. And some apps 350 * seem to depend on that behaviour. 351 * 352 * Mesa's gl_uniform_list doesn't directly support this since each 353 * entry in the list describes one uniform variable, not one uniform 354 * element. We could insert dummy entries in the list for each array 355 * element after [0] but that causes complications elsewhere. 356 * 357 * We solve this problem by encoding two values in the location that's 358 * returned by glGetUniformLocation(): 359 * a) index into gl_uniform_list::Uniforms[] for the uniform 360 * b) an array/field offset (0 for simple types) 361 * 362 * These two values are encoded in the high and low halves of a GLint. 363 * By putting the uniform number in the high part and the offset in the 364 * low part, we can support the unofficial ability to index into arrays 365 * by adding offsets to the location value. 366 */ 367static void 368merge_location_offset(GLint *location, GLint offset) 369{ 370 *location = (*location << 16) | offset; 371} 372 373 374/** 375 * Separate the uniform location and parameter offset. See above. 376 */ 377static void 378split_location_offset(GLint *location, GLint *offset) 379{ 380 *offset = *location & 0xffff; 381 *location = *location >> 16; 382} 383 384 385 386/** 387 * Called via glGetUniformfv(). 388 */ 389static void 390_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, 391 GLfloat *params) 392{ 393 struct gl_program *prog; 394 GLint paramPos; 395 GLint offset; 396 397 split_location_offset(&location, &offset); 398 399 lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); 400 401 if (prog) { 402 const struct gl_program_parameter *p = 403 &prog->Parameters->Parameters[paramPos]; 404 GLint rows, cols, i, j, k; 405 406 get_uniform_rows_cols(p, &rows, &cols); 407 408 k = 0; 409 for (i = 0; i < rows; i++) { 410 for (j = 0; j < cols; j++ ) { 411 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j]; 412 } 413 } 414 } 415} 416 417 418/** 419 * Called via glGetUniformiv(). 420 * \sa _mesa_get_uniformfv, only difference is a cast. 421 */ 422static void 423_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location, 424 GLint *params) 425{ 426 struct gl_program *prog; 427 GLint paramPos; 428 GLint offset; 429 430 split_location_offset(&location, &offset); 431 432 lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); 433 434 if (prog) { 435 const struct gl_program_parameter *p = 436 &prog->Parameters->Parameters[paramPos]; 437 GLint rows, cols, i, j, k; 438 439 get_uniform_rows_cols(p, &rows, &cols); 440 441 k = 0; 442 for (i = 0; i < rows; i++) { 443 for (j = 0; j < cols; j++ ) { 444 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j]; 445 } 446 } 447 } 448} 449 450 451/** 452 * Called via glGetUniformLocation(). 453 * 454 * The return value will encode two values, the uniform location and an 455 * offset (used for arrays, structs). 456 */ 457GLint 458_mesa_get_uniform_location(GLcontext *ctx, struct gl_shader_program *shProg, 459 const GLchar *name) 460{ 461 GLint offset = 0, location = -1; 462 463 if (shProg->LinkStatus == GL_FALSE) { 464 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)"); 465 return -1; 466 } 467 468 /* XXX we should return -1 if the uniform was declared, but not 469 * actually used. 470 */ 471 472 /* XXX we need to be able to parse uniform names for structs and arrays 473 * such as: 474 * mymatrix[1] 475 * mystruct.field1 476 */ 477 478 { 479 /* handle 1-dimension arrays here... */ 480 char *c = strchr(name, '['); 481 if (c) { 482 /* truncate name at [ */ 483 const GLint len = c - name; 484 GLchar *newName = malloc(len + 1); 485 if (!newName) 486 return -1; /* out of mem */ 487 memcpy(newName, name, len); 488 newName[len] = 0; 489 490 location = _mesa_lookup_uniform(shProg->Uniforms, newName); 491 if (location >= 0) { 492 const GLint element = atoi(c + 1); 493 if (element > 0) { 494 /* get type of the uniform array element */ 495 struct gl_program_parameter *p; 496 p = get_uniform_parameter(shProg, location); 497 if (p) { 498 GLint rows, cols; 499 get_matrix_dims(p->DataType, &rows, &cols); 500 if (rows < 1) 501 rows = 1; 502 offset = element * rows; 503 } 504 } 505 } 506 507 free(newName); 508 } 509 } 510 511 if (location < 0) { 512 location = _mesa_lookup_uniform(shProg->Uniforms, name); 513 } 514 515 if (location >= 0) { 516 merge_location_offset(&location, offset); 517 } 518 519 return location; 520} 521 522 523 524/** 525 * Update the vertex/fragment program's TexturesUsed array. 526 * 527 * This needs to be called after glUniform(set sampler var) is called. 528 * A call to glUniform(samplerVar, value) causes a sampler to point to a 529 * particular texture unit. We know the sampler's texture target 530 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is 531 * set by glUniform() calls. 532 * 533 * So, scan the program->SamplerUnits[] and program->SamplerTargets[] 534 * information to update the prog->TexturesUsed[] values. 535 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX, 536 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc. 537 * We'll use that info for state validation before rendering. 538 */ 539void 540_mesa_update_shader_textures_used(struct gl_program *prog) 541{ 542 GLuint s; 543 544 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed)); 545 546 for (s = 0; s < MAX_SAMPLERS; s++) { 547 if (prog->SamplersUsed & (1 << s)) { 548 GLuint unit = prog->SamplerUnits[s]; 549 GLuint tgt = prog->SamplerTargets[s]; 550 assert(unit < MAX_TEXTURE_IMAGE_UNITS); 551 assert(tgt < NUM_TEXTURE_TARGETS); 552 prog->TexturesUsed[unit] |= (1 << tgt); 553 } 554 } 555} 556 557 558/** 559 * Check if the type given by userType is allowed to set a uniform of the 560 * target type. Generally, equivalence is required, but setting Boolean 561 * uniforms can be done with glUniformiv or glUniformfv. 562 */ 563static GLboolean 564compatible_types(GLenum userType, GLenum targetType) 565{ 566 if (userType == targetType) 567 return GL_TRUE; 568 569 if (targetType == GL_BOOL && (userType == GL_FLOAT || 570 userType == GL_UNSIGNED_INT || 571 userType == GL_INT)) 572 return GL_TRUE; 573 574 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 || 575 userType == GL_UNSIGNED_INT_VEC2 || 576 userType == GL_INT_VEC2)) 577 return GL_TRUE; 578 579 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 || 580 userType == GL_UNSIGNED_INT_VEC3 || 581 userType == GL_INT_VEC3)) 582 return GL_TRUE; 583 584 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 || 585 userType == GL_UNSIGNED_INT_VEC4 || 586 userType == GL_INT_VEC4)) 587 return GL_TRUE; 588 589 if (is_sampler_type(targetType) && userType == GL_INT) 590 return GL_TRUE; 591 592 return GL_FALSE; 593} 594 595 596/** 597 * Set the value of a program's uniform variable. 598 * \param program the program whose uniform to update 599 * \param index the index of the program parameter for the uniform 600 * \param offset additional parameter slot offset (for arrays) 601 * \param type the incoming datatype of 'values' 602 * \param count the number of uniforms to set 603 * \param elems number of elements per uniform (1, 2, 3 or 4) 604 * \param values the new values, of datatype 'type' 605 */ 606static void 607set_program_uniform(GLcontext *ctx, struct gl_program *program, 608 GLint index, GLint offset, 609 GLenum type, GLsizei count, GLint elems, 610 const void *values) 611{ 612 const struct gl_program_parameter *param = 613 &program->Parameters->Parameters[index]; 614 615 assert(offset >= 0); 616 assert(elems >= 1); 617 assert(elems <= 4); 618 619 if (!compatible_types(type, param->DataType)) { 620 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)"); 621 return; 622 } 623 624 if (index + offset > (GLint) program->Parameters->Size) { 625 /* out of bounds! */ 626 return; 627 } 628 629 if (param->Type == PROGRAM_SAMPLER) { 630 /* This controls which texture unit which is used by a sampler */ 631 GLboolean changed = GL_FALSE; 632 GLint i; 633 634 /* this should have been caught by the compatible_types() check */ 635 ASSERT(type == GL_INT); 636 637 /* loop over number of samplers to change */ 638 for (i = 0; i < count; i++) { 639 GLuint sampler = 640 (GLuint) program->Parameters->ParameterValues[index + offset + i][0]; 641 GLuint texUnit = ((GLuint *) values)[i]; 642 643 /* check that the sampler (tex unit index) is legal */ 644 if (texUnit >= ctx->Const.MaxTextureImageUnits) { 645 _mesa_error(ctx, GL_INVALID_VALUE, 646 "glUniform1(invalid sampler/tex unit index for '%s')", 647 param->Name); 648 return; 649 } 650 651 /* This maps a sampler to a texture unit: */ 652 if (sampler < MAX_SAMPLERS) { 653#if 0 654 printf("Set program %p sampler %d '%s' to unit %u\n", 655 program, sampler, param->Name, texUnit); 656#endif 657 if (program->SamplerUnits[sampler] != texUnit) { 658 program->SamplerUnits[sampler] = texUnit; 659 changed = GL_TRUE; 660 } 661 } 662 } 663 664 if (changed) { 665 /* When a sampler's value changes it usually requires rewriting 666 * a GPU program's TEX instructions since there may not be a 667 * sampler->texture lookup table. We signal this with the 668 * ProgramStringNotify() callback. 669 */ 670 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM); 671 _mesa_update_shader_textures_used(program); 672 /* Do we need to care about the return value here? 673 * This should not be the first time the driver was notified of 674 * this program. 675 */ 676 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program); 677 } 678 } 679 else { 680 /* ordinary uniform variable */ 681 const GLboolean isUniformBool = is_boolean_type(param->DataType); 682 const GLenum basicType = base_uniform_type(type); 683 const GLint slots = (param->Size + 3) / 4; 684 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); 685 GLsizei k, i; 686 687 if ((GLint) param->Size > typeSize) { 688 /* an array */ 689 /* we'll ignore extra data below */ 690 } 691 else { 692 /* non-array: count must be at most one; count == 0 is handled by the loop below */ 693 if (count > 1) { 694 _mesa_error(ctx, GL_INVALID_OPERATION, 695 "glUniform(uniform '%s' is not an array)", 696 param->Name); 697 return; 698 } 699 } 700 701 /* loop over number of array elements */ 702 for (k = 0; k < count; k++) { 703 GLfloat *uniformVal; 704 705 if (offset + k >= slots) { 706 /* Extra array data is ignored */ 707 break; 708 } 709 710 /* uniformVal (the destination) is always float[4] */ 711 uniformVal = program->Parameters->ParameterValues[index + offset + k]; 712 713 if (basicType == GL_INT) { 714 /* convert user's ints to floats */ 715 const GLint *iValues = ((const GLint *) values) + k * elems; 716 for (i = 0; i < elems; i++) { 717 uniformVal[i] = (GLfloat) iValues[i]; 718 } 719 } 720 else if (basicType == GL_UNSIGNED_INT) { 721 /* convert user's uints to floats */ 722 const GLuint *iValues = ((const GLuint *) values) + k * elems; 723 for (i = 0; i < elems; i++) { 724 uniformVal[i] = (GLfloat) iValues[i]; 725 } 726 } 727 else { 728 const GLfloat *fValues = ((const GLfloat *) values) + k * elems; 729 assert(basicType == GL_FLOAT); 730 for (i = 0; i < elems; i++) { 731 uniformVal[i] = fValues[i]; 732 } 733 } 734 735 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */ 736 if (isUniformBool) { 737 for (i = 0; i < elems; i++) { 738 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f; 739 } 740 } 741 } 742 } 743} 744 745 746/** 747 * Called via glUniform*() functions. 748 */ 749void 750_mesa_uniform(GLcontext *ctx, struct gl_shader_program *shProg, 751 GLint location, GLsizei count, 752 const GLvoid *values, GLenum type) 753{ 754 struct gl_uniform *uniform; 755 GLint elems, offset; 756 757 if (!shProg || !shProg->LinkStatus) { 758 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)"); 759 return; 760 } 761 762 if (location == -1) 763 return; /* The standard specifies this as a no-op */ 764 765 if (location < -1) { 766 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location=%d)", 767 location); 768 return; 769 } 770 771 split_location_offset(&location, &offset); 772 773 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { 774 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location=%d)", location); 775 return; 776 } 777 778 if (count < 0) { 779 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)"); 780 return; 781 } 782 783 elems = _mesa_sizeof_glsl_type(type); 784 785 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 786 787 uniform = &shProg->Uniforms->Uniforms[location]; 788 789 if (ctx->Shader.Flags & GLSL_UNIFORMS) { 790 const GLenum basicType = base_uniform_type(type); 791 GLint i; 792 printf("Mesa: set program %u uniform %s (loc %d) to: ", 793 shProg->Name, uniform->Name, location); 794 if (basicType == GL_INT) { 795 const GLint *v = (const GLint *) values; 796 for (i = 0; i < count * elems; i++) { 797 printf("%d ", v[i]); 798 } 799 } 800 else if (basicType == GL_UNSIGNED_INT) { 801 const GLuint *v = (const GLuint *) values; 802 for (i = 0; i < count * elems; i++) { 803 printf("%u ", v[i]); 804 } 805 } 806 else { 807 const GLfloat *v = (const GLfloat *) values; 808 assert(basicType == GL_FLOAT); 809 for (i = 0; i < count * elems; i++) { 810 printf("%g ", v[i]); 811 } 812 } 813 printf("\n"); 814 } 815 816 /* A uniform var may be used by both a vertex shader and a fragment 817 * shader. We may need to update one or both shader's uniform here: 818 */ 819 if (shProg->VertexProgram) { 820 /* convert uniform location to program parameter index */ 821 GLint index = uniform->VertPos; 822 if (index >= 0) { 823 set_program_uniform(ctx, &shProg->VertexProgram->Base, 824 index, offset, type, count, elems, values); 825 } 826 } 827 828 if (shProg->FragmentProgram) { 829 /* convert uniform location to program parameter index */ 830 GLint index = uniform->FragPos; 831 if (index >= 0) { 832 set_program_uniform(ctx, &shProg->FragmentProgram->Base, 833 index, offset, type, count, elems, values); 834 } 835 } 836 837 if (shProg->GeometryProgram) { 838 /* convert uniform location to program parameter index */ 839 GLint index = uniform->GeomPos; 840 if (index >= 0) { 841 set_program_uniform(ctx, &shProg->GeometryProgram->Base, 842 index, offset, type, count, elems, values); 843 } 844 } 845 846 uniform->Initialized = GL_TRUE; 847} 848 849 850/** 851 * Set a matrix-valued program parameter. 852 */ 853static void 854set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program, 855 GLuint index, GLuint offset, 856 GLuint count, GLuint rows, GLuint cols, 857 GLboolean transpose, const GLfloat *values) 858{ 859 GLuint mat, row, col; 860 GLuint src = 0; 861 const struct gl_program_parameter * param = &program->Parameters->Parameters[index]; 862 const GLuint slots = (param->Size + 3) / 4; 863 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); 864 GLint nr, nc; 865 866 /* check that the number of rows, columns is correct */ 867 get_matrix_dims(param->DataType, &nr, &nc); 868 if (rows != nr || cols != nc) { 869 _mesa_error(ctx, GL_INVALID_OPERATION, 870 "glUniformMatrix(matrix size mismatch)"); 871 return; 872 } 873 874 if ((GLint) param->Size <= typeSize) { 875 /* non-array: count must be at most one; count == 0 is handled by the loop below */ 876 if (count > 1) { 877 _mesa_error(ctx, GL_INVALID_OPERATION, 878 "glUniformMatrix(uniform is not an array)"); 879 return; 880 } 881 } 882 883 /* 884 * Note: the _columns_ of a matrix are stored in program registers, not 885 * the rows. So, the loops below look a little funny. 886 * XXX could optimize this a bit... 887 */ 888 889 /* loop over matrices */ 890 for (mat = 0; mat < count; mat++) { 891 892 /* each matrix: */ 893 for (col = 0; col < cols; col++) { 894 GLfloat *v; 895 if (offset >= slots) { 896 /* Ignore writes beyond the end of (the used part of) an array */ 897 return; 898 } 899 v = program->Parameters->ParameterValues[index + offset]; 900 for (row = 0; row < rows; row++) { 901 if (transpose) { 902 v[row] = values[src + row * cols + col]; 903 } 904 else { 905 v[row] = values[src + col * rows + row]; 906 } 907 } 908 909 offset++; 910 } 911 912 src += rows * cols; /* next matrix */ 913 } 914} 915 916 917/** 918 * Called by glUniformMatrix*() functions. 919 * Note: cols=2, rows=4 ==> array[2] of vec4 920 */ 921void 922_mesa_uniform_matrix(GLcontext *ctx, struct gl_shader_program *shProg, 923 GLint cols, GLint rows, 924 GLint location, GLsizei count, 925 GLboolean transpose, const GLfloat *values) 926{ 927 struct gl_uniform *uniform; 928 GLint offset; 929 930 if (!shProg || !shProg->LinkStatus) { 931 _mesa_error(ctx, GL_INVALID_OPERATION, 932 "glUniformMatrix(program not linked)"); 933 return; 934 } 935 936 if (location == -1) 937 return; /* The standard specifies this as a no-op */ 938 939 if (location < -1) { 940 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)"); 941 return; 942 } 943 944 split_location_offset(&location, &offset); 945 946 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { 947 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)"); 948 return; 949 } 950 if (values == NULL) { 951 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix"); 952 return; 953 } 954 955 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 956 957 uniform = &shProg->Uniforms->Uniforms[location]; 958 959 if (shProg->VertexProgram) { 960 /* convert uniform location to program parameter index */ 961 GLint index = uniform->VertPos; 962 if (index >= 0) { 963 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base, 964 index, offset, 965 count, rows, cols, transpose, values); 966 } 967 } 968 969 if (shProg->FragmentProgram) { 970 /* convert uniform location to program parameter index */ 971 GLint index = uniform->FragPos; 972 if (index >= 0) { 973 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base, 974 index, offset, 975 count, rows, cols, transpose, values); 976 } 977 } 978 979 if (shProg->GeometryProgram) { 980 /* convert uniform location to program parameter index */ 981 GLint index = uniform->GeomPos; 982 if (index >= 0) { 983 set_program_uniform_matrix(ctx, &shProg->GeometryProgram->Base, 984 index, offset, 985 count, rows, cols, transpose, values); 986 } 987 } 988 989 uniform->Initialized = GL_TRUE; 990} 991 992 993void GLAPIENTRY 994_mesa_Uniform1fARB(GLint location, GLfloat v0) 995{ 996 GET_CURRENT_CONTEXT(ctx); 997 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_FLOAT); 998} 999 1000void GLAPIENTRY 1001_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1) 1002{ 1003 GET_CURRENT_CONTEXT(ctx); 1004 GLfloat v[2]; 1005 v[0] = v0; 1006 v[1] = v1; 1007 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC2); 1008} 1009 1010void GLAPIENTRY 1011_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) 1012{ 1013 GET_CURRENT_CONTEXT(ctx); 1014 GLfloat v[3]; 1015 v[0] = v0; 1016 v[1] = v1; 1017 v[2] = v2; 1018 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC3); 1019} 1020 1021void GLAPIENTRY 1022_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, 1023 GLfloat v3) 1024{ 1025 GET_CURRENT_CONTEXT(ctx); 1026 GLfloat v[4]; 1027 v[0] = v0; 1028 v[1] = v1; 1029 v[2] = v2; 1030 v[3] = v3; 1031 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_FLOAT_VEC4); 1032} 1033 1034void GLAPIENTRY 1035_mesa_Uniform1iARB(GLint location, GLint v0) 1036{ 1037 GET_CURRENT_CONTEXT(ctx); 1038 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_INT); 1039} 1040 1041void GLAPIENTRY 1042_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1) 1043{ 1044 GET_CURRENT_CONTEXT(ctx); 1045 GLint v[2]; 1046 v[0] = v0; 1047 v[1] = v1; 1048 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC2); 1049} 1050 1051void GLAPIENTRY 1052_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2) 1053{ 1054 GET_CURRENT_CONTEXT(ctx); 1055 GLint v[3]; 1056 v[0] = v0; 1057 v[1] = v1; 1058 v[2] = v2; 1059 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC3); 1060} 1061 1062void GLAPIENTRY 1063_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3) 1064{ 1065 GET_CURRENT_CONTEXT(ctx); 1066 GLint v[4]; 1067 v[0] = v0; 1068 v[1] = v1; 1069 v[2] = v2; 1070 v[3] = v3; 1071 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_INT_VEC4); 1072} 1073 1074void GLAPIENTRY 1075_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value) 1076{ 1077 GET_CURRENT_CONTEXT(ctx); 1078 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT); 1079} 1080 1081void GLAPIENTRY 1082_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value) 1083{ 1084 GET_CURRENT_CONTEXT(ctx); 1085 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC2); 1086} 1087 1088void GLAPIENTRY 1089_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value) 1090{ 1091 GET_CURRENT_CONTEXT(ctx); 1092 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC3); 1093} 1094 1095void GLAPIENTRY 1096_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value) 1097{ 1098 GET_CURRENT_CONTEXT(ctx); 1099 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_FLOAT_VEC4); 1100} 1101 1102void GLAPIENTRY 1103_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value) 1104{ 1105 GET_CURRENT_CONTEXT(ctx); 1106 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT); 1107} 1108 1109void GLAPIENTRY 1110_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value) 1111{ 1112 GET_CURRENT_CONTEXT(ctx); 1113 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC2); 1114} 1115 1116void GLAPIENTRY 1117_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value) 1118{ 1119 GET_CURRENT_CONTEXT(ctx); 1120 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC3); 1121} 1122 1123void GLAPIENTRY 1124_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value) 1125{ 1126 GET_CURRENT_CONTEXT(ctx); 1127 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_INT_VEC4); 1128} 1129 1130 1131/** OpenGL 3.0 GLuint-valued functions **/ 1132void GLAPIENTRY 1133_mesa_Uniform1ui(GLint location, GLuint v0) 1134{ 1135 GET_CURRENT_CONTEXT(ctx); 1136 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, &v0, GL_UNSIGNED_INT); 1137} 1138 1139void GLAPIENTRY 1140_mesa_Uniform2ui(GLint location, GLuint v0, GLuint v1) 1141{ 1142 GET_CURRENT_CONTEXT(ctx); 1143 GLuint v[2]; 1144 v[0] = v0; 1145 v[1] = v1; 1146 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC2); 1147} 1148 1149void GLAPIENTRY 1150_mesa_Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) 1151{ 1152 GET_CURRENT_CONTEXT(ctx); 1153 GLuint v[3]; 1154 v[0] = v0; 1155 v[1] = v1; 1156 v[2] = v2; 1157 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC3); 1158} 1159 1160void GLAPIENTRY 1161_mesa_Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) 1162{ 1163 GET_CURRENT_CONTEXT(ctx); 1164 GLuint v[4]; 1165 v[0] = v0; 1166 v[1] = v1; 1167 v[2] = v2; 1168 v[3] = v3; 1169 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, 1, v, GL_UNSIGNED_INT_VEC4); 1170} 1171 1172void GLAPIENTRY 1173_mesa_Uniform1uiv(GLint location, GLsizei count, const GLuint *value) 1174{ 1175 GET_CURRENT_CONTEXT(ctx); 1176 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT); 1177} 1178 1179void GLAPIENTRY 1180_mesa_Uniform2uiv(GLint location, GLsizei count, const GLuint *value) 1181{ 1182 GET_CURRENT_CONTEXT(ctx); 1183 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC2); 1184} 1185 1186void GLAPIENTRY 1187_mesa_Uniform3uiv(GLint location, GLsizei count, const GLuint *value) 1188{ 1189 GET_CURRENT_CONTEXT(ctx); 1190 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC3); 1191} 1192 1193void GLAPIENTRY 1194_mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value) 1195{ 1196 GET_CURRENT_CONTEXT(ctx); 1197 _mesa_uniform(ctx, ctx->Shader.CurrentProgram, location, count, value, GL_UNSIGNED_INT_VEC4); 1198} 1199 1200 1201 1202void GLAPIENTRY 1203_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose, 1204 const GLfloat * value) 1205{ 1206 GET_CURRENT_CONTEXT(ctx); 1207 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1208 2, 2, location, count, transpose, value); 1209} 1210 1211void GLAPIENTRY 1212_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose, 1213 const GLfloat * value) 1214{ 1215 GET_CURRENT_CONTEXT(ctx); 1216 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1217 3, 3, location, count, transpose, value); 1218} 1219 1220void GLAPIENTRY 1221_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose, 1222 const GLfloat * value) 1223{ 1224 GET_CURRENT_CONTEXT(ctx); 1225 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1226 4, 4, location, count, transpose, value); 1227} 1228 1229 1230/** 1231 * Non-square UniformMatrix are OpenGL 2.1 1232 */ 1233void GLAPIENTRY 1234_mesa_UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, 1235 const GLfloat *value) 1236{ 1237 GET_CURRENT_CONTEXT(ctx); 1238 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1239 2, 3, location, count, transpose, value); 1240} 1241 1242void GLAPIENTRY 1243_mesa_UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, 1244 const GLfloat *value) 1245{ 1246 GET_CURRENT_CONTEXT(ctx); 1247 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1248 3, 2, location, count, transpose, value); 1249} 1250 1251void GLAPIENTRY 1252_mesa_UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, 1253 const GLfloat *value) 1254{ 1255 GET_CURRENT_CONTEXT(ctx); 1256 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1257 2, 4, location, count, transpose, value); 1258} 1259 1260void GLAPIENTRY 1261_mesa_UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, 1262 const GLfloat *value) 1263{ 1264 GET_CURRENT_CONTEXT(ctx); 1265 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1266 4, 2, location, count, transpose, value); 1267} 1268 1269void GLAPIENTRY 1270_mesa_UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, 1271 const GLfloat *value) 1272{ 1273 GET_CURRENT_CONTEXT(ctx); 1274 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1275 3, 4, location, count, transpose, value); 1276} 1277 1278void GLAPIENTRY 1279_mesa_UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, 1280 const GLfloat *value) 1281{ 1282 GET_CURRENT_CONTEXT(ctx); 1283 _mesa_uniform_matrix(ctx, ctx->Shader.CurrentProgram, 1284 4, 3, location, count, transpose, value); 1285} 1286 1287 1288void GLAPIENTRY 1289_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params) 1290{ 1291 GET_CURRENT_CONTEXT(ctx); 1292 _mesa_get_uniformfv(ctx, program, location, params); 1293} 1294 1295 1296void GLAPIENTRY 1297_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params) 1298{ 1299 GET_CURRENT_CONTEXT(ctx); 1300 _mesa_get_uniformiv(ctx, program, location, params); 1301} 1302 1303 1304GLint GLAPIENTRY 1305_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name) 1306{ 1307 struct gl_shader_program *shProg; 1308 1309 GET_CURRENT_CONTEXT(ctx); 1310 1311 shProg = _mesa_lookup_shader_program_err(ctx, programObj, 1312 "glGetUniformLocation"); 1313 if (!shProg) 1314 return -1; 1315 1316 return _mesa_get_uniform_location(ctx, shProg, name); 1317} 1318 1319 1320void GLAPIENTRY 1321_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index, 1322 GLsizei maxLength, GLsizei * length, GLint * size, 1323 GLenum * type, GLcharARB * name) 1324{ 1325 GET_CURRENT_CONTEXT(ctx); 1326 _mesa_get_active_uniform(ctx, program, index, maxLength, length, size, 1327 type, name); 1328} 1329 1330 1331/** 1332 * Plug in shader uniform-related functions into API dispatch table. 1333 */ 1334void 1335_mesa_init_shader_uniform_dispatch(struct _glapi_table *exec) 1336{ 1337#if FEATURE_GL 1338 SET_Uniform1fARB(exec, _mesa_Uniform1fARB); 1339 SET_Uniform2fARB(exec, _mesa_Uniform2fARB); 1340 SET_Uniform3fARB(exec, _mesa_Uniform3fARB); 1341 SET_Uniform4fARB(exec, _mesa_Uniform4fARB); 1342 SET_Uniform1iARB(exec, _mesa_Uniform1iARB); 1343 SET_Uniform2iARB(exec, _mesa_Uniform2iARB); 1344 SET_Uniform3iARB(exec, _mesa_Uniform3iARB); 1345 SET_Uniform4iARB(exec, _mesa_Uniform4iARB); 1346 SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB); 1347 SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB); 1348 SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB); 1349 SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB); 1350 SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB); 1351 SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB); 1352 SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB); 1353 SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB); 1354 SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB); 1355 SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB); 1356 SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB); 1357 1358 SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB); 1359 SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB); 1360 SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB); 1361 SET_GetUniformivARB(exec, _mesa_GetUniformivARB); 1362 1363 /* OpenGL 2.1 */ 1364 SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv); 1365 SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv); 1366 SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv); 1367 SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv); 1368 SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv); 1369 SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv); 1370 1371 /* OpenGL 3.0 */ 1372 /* XXX finish dispatch */ 1373 (void) _mesa_Uniform1ui; 1374 (void) _mesa_Uniform2ui; 1375 (void) _mesa_Uniform3ui; 1376 (void) _mesa_Uniform4ui; 1377 (void) _mesa_Uniform1uiv; 1378 (void) _mesa_Uniform2uiv; 1379 (void) _mesa_Uniform3uiv; 1380 (void) _mesa_Uniform4uiv; 1381#endif /* FEATURE_GL */ 1382} 1383