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