uniform_query.cpp revision 2f45ed393a40e914749ddb86d41e0f77b2cea3da
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, 2011 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#include "main/core.h" 26#include "main/context.h" 27#include "ir.h" 28#include "../glsl/program.h" 29 30extern "C" { 31#include "main/image.h" 32#include "main/shaderapi.h" 33#include "main/shaderobj.h" 34#include "uniforms.h" 35} 36 37extern "C" void GLAPIENTRY 38_mesa_GetActiveUniformARB(GLhandleARB program, GLuint index, 39 GLsizei maxLength, GLsizei *length, GLint *size, 40 GLenum *type, GLcharARB *nameOut) 41{ 42 GET_CURRENT_CONTEXT(ctx); 43 struct gl_shader_program *shProg = 44 _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); 45 const struct gl_program_parameter *param; 46 47 if (!shProg) 48 return; 49 50 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) { 51 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); 52 return; 53 } 54 55 param = get_uniform_parameter(shProg, index); 56 if (!param) 57 return; 58 59 const struct gl_uniform *const uni = &shProg->Uniforms->Uniforms[index]; 60 61 if (nameOut) { 62 _mesa_copy_string(nameOut, maxLength, length, param->Name); 63 } 64 65 if (size) { 66 GLint typeSize = _mesa_sizeof_glsl_type(uni->Type->gl_type); 67 if ((GLint) param->Size > typeSize) { 68 /* This is an array. 69 * Array elements are placed on vector[4] boundaries so they're 70 * a multiple of four floats. We round typeSize up to next multiple 71 * of four to get the right size below. 72 */ 73 typeSize = (typeSize + 3) & ~3; 74 } 75 /* Note that the returned size is in units of the <type>, not bytes */ 76 *size = param->Size / typeSize; 77 } 78 79 if (type) { 80 *type = uni->Type->gl_type; 81 } 82} 83 84static GLenum 85base_uniform_type(GLenum type) 86{ 87 switch (type) { 88 case GL_BOOL: 89 case GL_BOOL_VEC2: 90 case GL_BOOL_VEC3: 91 case GL_BOOL_VEC4: 92 return GL_BOOL; 93 case GL_FLOAT: 94 case GL_FLOAT_VEC2: 95 case GL_FLOAT_VEC3: 96 case GL_FLOAT_VEC4: 97 case GL_FLOAT_MAT2: 98 case GL_FLOAT_MAT2x3: 99 case GL_FLOAT_MAT2x4: 100 case GL_FLOAT_MAT3x2: 101 case GL_FLOAT_MAT3: 102 case GL_FLOAT_MAT3x4: 103 case GL_FLOAT_MAT4x2: 104 case GL_FLOAT_MAT4x3: 105 case GL_FLOAT_MAT4: 106 return GL_FLOAT; 107 case GL_UNSIGNED_INT: 108 case GL_UNSIGNED_INT_VEC2: 109 case GL_UNSIGNED_INT_VEC3: 110 case GL_UNSIGNED_INT_VEC4: 111 return GL_UNSIGNED_INT; 112 case GL_INT: 113 case GL_INT_VEC2: 114 case GL_INT_VEC3: 115 case GL_INT_VEC4: 116 return GL_INT; 117 default: 118 _mesa_problem(NULL, "Invalid type in base_uniform_type()"); 119 return GL_FLOAT; 120 } 121} 122 123static GLboolean 124is_boolean_type(GLenum type) 125{ 126 switch (type) { 127 case GL_BOOL: 128 case GL_BOOL_VEC2: 129 case GL_BOOL_VEC3: 130 case GL_BOOL_VEC4: 131 return GL_TRUE; 132 default: 133 return GL_FALSE; 134 } 135} 136 137static GLboolean 138is_sampler_type(GLenum type) 139{ 140 switch (type) { 141 case GL_SAMPLER_1D: 142 case GL_INT_SAMPLER_1D: 143 case GL_UNSIGNED_INT_SAMPLER_1D: 144 case GL_SAMPLER_2D: 145 case GL_INT_SAMPLER_2D: 146 case GL_UNSIGNED_INT_SAMPLER_2D: 147 case GL_SAMPLER_3D: 148 case GL_INT_SAMPLER_3D: 149 case GL_UNSIGNED_INT_SAMPLER_3D: 150 case GL_SAMPLER_CUBE: 151 case GL_INT_SAMPLER_CUBE: 152 case GL_UNSIGNED_INT_SAMPLER_CUBE: 153 case GL_SAMPLER_1D_SHADOW: 154 case GL_SAMPLER_2D_SHADOW: 155 case GL_SAMPLER_CUBE_SHADOW: 156 case GL_SAMPLER_2D_RECT_ARB: 157 case GL_INT_SAMPLER_2D_RECT: 158 case GL_UNSIGNED_INT_SAMPLER_2D_RECT: 159 case GL_SAMPLER_2D_RECT_SHADOW_ARB: 160 case GL_SAMPLER_1D_ARRAY_EXT: 161 case GL_INT_SAMPLER_1D_ARRAY: 162 case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY: 163 case GL_SAMPLER_2D_ARRAY_EXT: 164 case GL_INT_SAMPLER_2D_ARRAY: 165 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: 166 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: 167 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: 168 case GL_SAMPLER_CUBE_MAP_ARRAY: 169 case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW: 170 case GL_SAMPLER_BUFFER: 171 case GL_INT_SAMPLER_BUFFER: 172 case GL_UNSIGNED_INT_SAMPLER_BUFFER: 173 case GL_SAMPLER_2D_MULTISAMPLE: 174 case GL_INT_SAMPLER_2D_MULTISAMPLE: 175 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE: 176 case GL_SAMPLER_2D_MULTISAMPLE_ARRAY: 177 case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: 178 case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY: 179 case GL_SAMPLER_EXTERNAL_OES: 180 return GL_TRUE; 181 default: 182 return GL_FALSE; 183 } 184} 185 186/** 187 * Given a uniform index, return the vertex/geometry/fragment program 188 * that has that parameter, plus the position of the parameter in the 189 * parameter/constant buffer. 190 * \param shProg the shader program 191 * \param index the uniform index in [0, NumUniforms-1] 192 * \param progOut returns containing program 193 * \param posOut returns position of the uniform in the param/const buffer 194 * \return GL_TRUE for success, GL_FALSE for invalid index 195 */ 196static GLboolean 197find_uniform_parameter_pos(struct gl_shader_program *shProg, GLint index, 198 struct gl_program **progOut, GLint *posOut) 199{ 200 struct gl_program *prog = NULL; 201 GLint pos; 202 203 if (!shProg->Uniforms || 204 index < 0 || 205 index >= (GLint) shProg->Uniforms->NumUniforms) { 206 return GL_FALSE; 207 } 208 209 pos = shProg->Uniforms->Uniforms[index].VertPos; 210 if (pos >= 0) { 211 prog = shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program; 212 } 213 else { 214 pos = shProg->Uniforms->Uniforms[index].FragPos; 215 if (pos >= 0) { 216 prog = shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program; 217 } 218 else { 219 pos = shProg->Uniforms->Uniforms[index].GeomPos; 220 if (pos >= 0) { 221 prog = shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program; 222 } 223 } 224 } 225 226 if (!prog || pos < 0) 227 return GL_FALSE; /* should really never happen */ 228 229 *progOut = prog; 230 *posOut = pos; 231 232 return GL_TRUE; 233} 234 235/** 236 * Return pointer to a gl_program_parameter which corresponds to a uniform. 237 * \param shProg the shader program 238 * \param index the uniform index in [0, NumUniforms-1] 239 * \return gl_program_parameter point or NULL if index is invalid 240 */ 241const struct gl_program_parameter * 242get_uniform_parameter(struct gl_shader_program *shProg, GLint index) 243{ 244 struct gl_program *prog; 245 GLint progPos; 246 247 if (find_uniform_parameter_pos(shProg, index, &prog, &progPos)) 248 return &prog->Parameters->Parameters[progPos]; 249 else 250 return NULL; 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 * Determine the number of rows and columns occupied by a uniform 330 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4), 331 * the number of rows = 1 and cols = number of elements in the vector. 332 */ 333static void 334get_uniform_rows_cols(const struct gl_program_parameter *p, 335 GLint *rows, GLint *cols) 336{ 337 get_matrix_dims(p->DataType, rows, cols); 338 if (*rows == 0 && *cols == 0) { 339 /* not a matrix type, probably a float or vector */ 340 *rows = 1; 341 *cols = get_vector_elements(p->DataType); 342 } 343} 344 345static bool 346validate_uniform_parameters(struct gl_context *ctx, 347 struct gl_shader_program *shProg, 348 GLint location, GLsizei count, 349 unsigned *loc, 350 unsigned *array_index, 351 const char *caller, 352 bool negative_one_is_not_valid) 353{ 354 if (!shProg || !shProg->LinkStatus) { 355 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)", caller); 356 return false; 357 } 358 359 if (location == -1) { 360 /* For glGetUniform, page 264 (page 278 of the PDF) of the OpenGL 2.1 361 * spec says: 362 * 363 * "The error INVALID_OPERATION is generated if program has not been 364 * linked successfully, or if location is not a valid location for 365 * program." 366 * 367 * For glUniform, page 82 (page 96 of the PDF) of the OpenGL 2.1 spec 368 * says: 369 * 370 * "If the value of location is -1, the Uniform* commands will 371 * silently ignore the data passed in, and the current uniform 372 * values will not be changed." 373 * 374 * Allowing -1 for the location parameter of glUniform allows 375 * applications to avoid error paths in the case that, for example, some 376 * uniform variable is removed by the compiler / linker after 377 * optimization. In this case, the new value of the uniform is dropped 378 * on the floor. For the case of glGetUniform, there is nothing 379 * sensible to do for a location of -1. 380 * 381 * The negative_one_is_not_valid flag selects between the two behaviors. 382 */ 383 if (negative_one_is_not_valid) { 384 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", 385 caller, location); 386 } 387 388 return false; 389 } 390 391 /* From page 12 (page 26 of the PDF) of the OpenGL 2.1 spec: 392 * 393 * "If a negative number is provided where an argument of type sizei or 394 * sizeiptr is specified, the error INVALID_VALUE is generated." 395 */ 396 if (count < 0) { 397 _mesa_error(ctx, GL_INVALID_VALUE, "%s(count < 0)", caller); 398 return false; 399 } 400 401 /* Page 82 (page 96 of the PDF) of the OpenGL 2.1 spec says: 402 * 403 * "If any of the following conditions occur, an INVALID_OPERATION 404 * error is generated by the Uniform* commands, and no uniform values 405 * are changed: 406 * 407 * ... 408 * 409 * - if no variable with a location of location exists in the 410 * program object currently in use and location is not -1, 411 */ 412 if (location < -1) { 413 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", 414 caller, location); 415 return false; 416 } 417 418 _mesa_uniform_split_location_offset(location, loc, array_index); 419 420 if (*loc >= shProg->Uniforms->NumUniforms) { 421 _mesa_error(ctx, GL_INVALID_OPERATION, "%s(location=%d)", 422 caller, location); 423 return false; 424 } 425 426 return true; 427} 428 429/** 430 * Called via glGetUniform[fiui]v() to get the current value of a uniform. 431 */ 432extern "C" void 433_mesa_get_uniform(struct gl_context *ctx, GLuint program, GLint location, 434 GLsizei bufSize, GLenum returnType, GLvoid *paramsOut) 435{ 436 struct gl_shader_program *shProg = 437 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformfv"); 438 struct gl_program *prog; 439 GLint paramPos; 440 unsigned loc, offset; 441 442 if (!validate_uniform_parameters(ctx, shProg, location, 1, 443 &loc, &offset, "glGetUniform", true)) 444 return; 445 446 if (!find_uniform_parameter_pos(shProg, loc, &prog, ¶mPos)) { 447 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); 448 } 449 else { 450 const struct gl_program_parameter *p = 451 &prog->Parameters->Parameters[paramPos]; 452 gl_constant_value (*values)[4]; 453 GLint rows, cols, i, j, k; 454 GLsizei numBytes; 455 GLenum storage_type; 456 457 values = prog->Parameters->ParameterValues + paramPos + offset; 458 459 get_uniform_rows_cols(p, &rows, &cols); 460 461 numBytes = rows * cols * _mesa_sizeof_type(returnType); 462 if (bufSize < numBytes) { 463 _mesa_error( ctx, GL_INVALID_OPERATION, 464 "glGetnUniformfvARB(out of bounds: bufSize is %d," 465 " but %d bytes are required)", bufSize, numBytes ); 466 return; 467 } 468 469 if (ctx->Const.NativeIntegers) { 470 storage_type = base_uniform_type(p->DataType); 471 } else { 472 storage_type = GL_FLOAT; 473 } 474 475 k = 0; 476 for (i = 0; i < rows; i++) { 477 for (j = 0; j < cols; j++ ) { 478 void *out = (char *)paramsOut + 4 * k; 479 480 switch (returnType) { 481 case GL_FLOAT: 482 switch (storage_type) { 483 case GL_FLOAT: 484 *(float *)out = values[i][j].f; 485 break; 486 case GL_INT: 487 case GL_BOOL: /* boolean is just an integer 1 or 0. */ 488 *(float *)out = values[i][j].i; 489 break; 490 case GL_UNSIGNED_INT: 491 *(float *)out = values[i][j].u; 492 break; 493 } 494 break; 495 496 case GL_INT: 497 case GL_UNSIGNED_INT: 498 switch (storage_type) { 499 case GL_FLOAT: 500 /* While the GL 3.2 core spec doesn't explicitly 501 * state how conversion of float uniforms to integer 502 * values works, in section 6.2 "State Tables" on 503 * page 267 it says: 504 * 505 * "Unless otherwise specified, when floating 506 * point state is returned as integer values or 507 * integer state is returned as floating-point 508 * values it is converted in the fashion 509 * described in section 6.1.2" 510 * 511 * That section, on page 248, says: 512 * 513 * "If GetIntegerv or GetInteger64v are called, 514 * a floating-point value is rounded to the 515 * nearest integer..." 516 */ 517 *(int *)out = IROUND(values[i][j].f); 518 break; 519 520 case GL_INT: 521 case GL_UNSIGNED_INT: 522 case GL_BOOL: 523 /* type conversions for these to int/uint are just 524 * copying the data. 525 */ 526 *(int *)out = values[i][j].i; 527 break; 528 break; 529 } 530 break; 531 } 532 533 k++; 534 } 535 } 536 } 537} 538 539/** 540 * Check if the type given by userType is allowed to set a uniform of the 541 * target type. Generally, equivalence is required, but setting Boolean 542 * uniforms can be done with glUniformiv or glUniformfv. 543 */ 544static GLboolean 545compatible_types(GLenum userType, GLenum targetType) 546{ 547 if (userType == targetType) 548 return GL_TRUE; 549 550 if (targetType == GL_BOOL && (userType == GL_FLOAT || 551 userType == GL_UNSIGNED_INT || 552 userType == GL_INT)) 553 return GL_TRUE; 554 555 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 || 556 userType == GL_UNSIGNED_INT_VEC2 || 557 userType == GL_INT_VEC2)) 558 return GL_TRUE; 559 560 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 || 561 userType == GL_UNSIGNED_INT_VEC3 || 562 userType == GL_INT_VEC3)) 563 return GL_TRUE; 564 565 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 || 566 userType == GL_UNSIGNED_INT_VEC4 || 567 userType == GL_INT_VEC4)) 568 return GL_TRUE; 569 570 if (is_sampler_type(targetType) && userType == GL_INT) 571 return GL_TRUE; 572 573 return GL_FALSE; 574} 575 576/** 577 * Set the value of a program's uniform variable. 578 * \param program the program whose uniform to update 579 * \param index the index of the program parameter for the uniform 580 * \param offset additional parameter slot offset (for arrays) 581 * \param type the incoming datatype of 'values' 582 * \param count the number of uniforms to set 583 * \param elems number of elements per uniform (1, 2, 3 or 4) 584 * \param values the new values, of datatype 'type' 585 */ 586static void 587set_program_uniform(struct gl_context *ctx, struct gl_program *program, 588 GLint index, GLint offset, 589 GLenum type, GLsizei count, GLint elems, 590 const void *values) 591{ 592 const struct gl_program_parameter *param = 593 &program->Parameters->Parameters[index]; 594 595 assert(offset >= 0); 596 assert(elems >= 1); 597 assert(elems <= 4); 598 599 if (!compatible_types(type, param->DataType)) { 600 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)"); 601 return; 602 } 603 604 if (index + offset > (GLint) program->Parameters->Size) { 605 /* out of bounds! */ 606 return; 607 } 608 609 if (param->Type == PROGRAM_SAMPLER) { 610 /* This controls which texture unit which is used by a sampler */ 611 GLboolean changed = GL_FALSE; 612 GLint i; 613 614 /* this should have been caught by the compatible_types() check */ 615 ASSERT(type == GL_INT); 616 617 /* loop over number of samplers to change */ 618 for (i = 0; i < count; i++) { 619 GLuint sampler = (GLuint) 620 program->Parameters->ParameterValues[index+offset + i][0].f; 621 GLuint texUnit = ((GLuint *) values)[i]; 622 623 /* check that the sampler (tex unit index) is legal */ 624 if (texUnit >= ctx->Const.MaxCombinedTextureImageUnits) { 625 _mesa_error(ctx, GL_INVALID_VALUE, 626 "glUniform1(invalid sampler/tex unit index for '%s')", 627 param->Name); 628 return; 629 } 630 631 /* This maps a sampler to a texture unit: */ 632 if (sampler < MAX_SAMPLERS) { 633#if 0 634 printf("Set program %p sampler %d '%s' to unit %u\n", 635 program, sampler, param->Name, texUnit); 636#endif 637 if (program->SamplerUnits[sampler] != texUnit) { 638 program->SamplerUnits[sampler] = texUnit; 639 changed = GL_TRUE; 640 } 641 } 642 } 643 644 if (changed) { 645 /* When a sampler's value changes it usually requires rewriting 646 * a GPU program's TEX instructions since there may not be a 647 * sampler->texture lookup table. We signal this with the 648 * ProgramStringNotify() callback. 649 */ 650 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM); 651 _mesa_update_shader_textures_used(program); 652 /* Do we need to care about the return value here? 653 * This should not be the first time the driver was notified of 654 * this program. 655 */ 656 (void) ctx->Driver.ProgramStringNotify(ctx, program->Target, program); 657 } 658 } 659 else { 660 /* ordinary uniform variable */ 661 const GLboolean isUniformBool = is_boolean_type(param->DataType); 662 const GLenum basicType = base_uniform_type(type); 663 const GLint slots = (param->Size + 3) / 4; 664 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); 665 GLsizei k, i; 666 667 if ((GLint) param->Size > typeSize) { 668 /* an array */ 669 /* we'll ignore extra data below */ 670 } 671 else { 672 /* non-array: count must be at most one; count == 0 is handled 673 * by the loop below 674 */ 675 if (count > 1) { 676 _mesa_error(ctx, GL_INVALID_OPERATION, 677 "glUniform(uniform '%s' is not an array)", 678 param->Name); 679 return; 680 } 681 } 682 683 /* loop over number of array elements */ 684 for (k = 0; k < count; k++) { 685 gl_constant_value *uniformVal; 686 687 if (offset + k >= slots) { 688 /* Extra array data is ignored */ 689 break; 690 } 691 692 /* uniformVal (the destination) is always gl_constant_value[4] */ 693 uniformVal = program->Parameters->ParameterValues[index + offset + k]; 694 695 if (basicType == GL_INT) { 696 const GLint *iValues = ((const GLint *) values) + k * elems; 697 for (i = 0; i < elems; i++) { 698 if (!ctx->Const.NativeIntegers) 699 uniformVal[i].f = (GLfloat) iValues[i]; 700 else 701 uniformVal[i].i = iValues[i]; 702 } 703 } 704 else if (basicType == GL_UNSIGNED_INT) { 705 const GLuint *iValues = ((const GLuint *) values) + k * elems; 706 for (i = 0; i < elems; i++) { 707 if (!ctx->Const.NativeIntegers) 708 uniformVal[i].f = (GLfloat)(GLuint) iValues[i]; 709 else 710 uniformVal[i].u = iValues[i]; 711 } 712 } 713 else { 714 const GLfloat *fValues = ((const GLfloat *) values) + k * elems; 715 assert(basicType == GL_FLOAT); 716 for (i = 0; i < elems; i++) { 717 uniformVal[i].f = fValues[i]; 718 } 719 } 720 721 /* if the uniform is bool-valued, convert to 1 or 0 */ 722 if (isUniformBool) { 723 for (i = 0; i < elems; i++) { 724 if (basicType == GL_FLOAT) 725 uniformVal[i].b = uniformVal[i].f != 0.0f ? 1 : 0; 726 else 727 uniformVal[i].b = uniformVal[i].u ? 1 : 0; 728 729 if (ctx->Const.NativeIntegers) 730 uniformVal[i].u = 731 uniformVal[i].b ? ctx->Const.UniformBooleanTrue : 0; 732 else 733 uniformVal[i].f = uniformVal[i].b ? 1.0f : 0.0f; 734 } 735 } 736 } 737 } 738} 739 740/** 741 * Called via glUniform*() functions. 742 */ 743extern "C" void 744_mesa_uniform(struct gl_context *ctx, struct gl_shader_program *shProg, 745 GLint location, GLsizei count, 746 const GLvoid *values, GLenum type) 747{ 748 struct gl_uniform *uniform; 749 GLint elems; 750 unsigned loc, offset; 751 752 ASSERT_OUTSIDE_BEGIN_END(ctx); 753 754 if (!validate_uniform_parameters(ctx, shProg, location, count, 755 &loc, &offset, "glUniform", false)) 756 return; 757 758 elems = _mesa_sizeof_glsl_type(type); 759 760 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 761 762 uniform = &shProg->Uniforms->Uniforms[loc]; 763 764 if (ctx->Shader.Flags & GLSL_UNIFORMS) { 765 const GLenum basicType = base_uniform_type(type); 766 GLint i; 767 printf("Mesa: set program %u uniform %s (loc %d) to: ", 768 shProg->Name, uniform->Name, location); 769 if (basicType == GL_INT) { 770 const GLint *v = (const GLint *) values; 771 for (i = 0; i < count * elems; i++) { 772 printf("%d ", v[i]); 773 } 774 } 775 else if (basicType == GL_UNSIGNED_INT) { 776 const GLuint *v = (const GLuint *) values; 777 for (i = 0; i < count * elems; i++) { 778 printf("%u ", v[i]); 779 } 780 } 781 else { 782 const GLfloat *v = (const GLfloat *) values; 783 assert(basicType == GL_FLOAT); 784 for (i = 0; i < count * elems; i++) { 785 printf("%g ", v[i]); 786 } 787 } 788 printf("\n"); 789 } 790 791 /* A uniform var may be used by both a vertex shader and a fragment 792 * shader. We may need to update one or both shader's uniform here: 793 */ 794 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX]) { 795 /* convert uniform location to program parameter index */ 796 GLint index = uniform->VertPos; 797 if (index >= 0) { 798 set_program_uniform(ctx, 799 shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program, 800 index, offset, type, count, elems, values); 801 } 802 } 803 804 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { 805 /* convert uniform location to program parameter index */ 806 GLint index = uniform->FragPos; 807 if (index >= 0) { 808 set_program_uniform(ctx, 809 shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program, 810 index, offset, type, count, elems, values); 811 } 812 } 813 814 if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { 815 /* convert uniform location to program parameter index */ 816 GLint index = uniform->GeomPos; 817 if (index >= 0) { 818 set_program_uniform(ctx, 819 shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program, 820 index, offset, type, count, elems, values); 821 } 822 } 823 824 uniform->Initialized = GL_TRUE; 825} 826 827/** 828 * Set a matrix-valued program parameter. 829 */ 830static void 831set_program_uniform_matrix(struct gl_context *ctx, struct gl_program *program, 832 GLuint index, GLuint offset, 833 GLuint count, GLuint rows, GLuint cols, 834 GLboolean transpose, const GLfloat *values) 835{ 836 GLuint mat, row, col; 837 GLuint src = 0; 838 const struct gl_program_parameter *param = 839 &program->Parameters->Parameters[index]; 840 const GLuint slots = (param->Size + 3) / 4; 841 const GLint typeSize = _mesa_sizeof_glsl_type(param->DataType); 842 GLint nr, nc; 843 844 /* check that the number of rows, columns is correct */ 845 get_matrix_dims(param->DataType, &nr, &nc); 846 if (rows != nr || cols != nc) { 847 _mesa_error(ctx, GL_INVALID_OPERATION, 848 "glUniformMatrix(matrix size mismatch)"); 849 return; 850 } 851 852 if ((GLint) param->Size <= typeSize) { 853 /* non-array: count must be at most one; count == 0 is handled 854 * by the loop below 855 */ 856 if (count > 1) { 857 _mesa_error(ctx, GL_INVALID_OPERATION, 858 "glUniformMatrix(uniform is not an array)"); 859 return; 860 } 861 } 862 863 /* 864 * Note: the _columns_ of a matrix are stored in program registers, not 865 * the rows. So, the loops below look a little funny. 866 * XXX could optimize this a bit... 867 */ 868 869 /* loop over matrices */ 870 for (mat = 0; mat < count; mat++) { 871 872 /* each matrix: */ 873 for (col = 0; col < cols; col++) { 874 GLfloat *v; 875 if (offset >= slots) { 876 /* Ignore writes beyond the end of (the used part of) an array */ 877 return; 878 } 879 v = (GLfloat *) program->Parameters->ParameterValues[index + offset]; 880 for (row = 0; row < rows; row++) { 881 if (transpose) { 882 v[row] = values[src + row * cols + col]; 883 } 884 else { 885 v[row] = values[src + col * rows + row]; 886 } 887 } 888 889 offset++; 890 } 891 892 src += rows * cols; /* next matrix */ 893 } 894} 895 896/** 897 * Called by glUniformMatrix*() functions. 898 * Note: cols=2, rows=4 ==> array[2] of vec4 899 */ 900extern "C" void 901_mesa_uniform_matrix(struct gl_context *ctx, struct gl_shader_program *shProg, 902 GLint cols, GLint rows, 903 GLint location, GLsizei count, 904 GLboolean transpose, const GLfloat *values) 905{ 906 struct gl_uniform *uniform; 907 unsigned loc, offset; 908 909 ASSERT_OUTSIDE_BEGIN_END(ctx); 910 911 if (!validate_uniform_parameters(ctx, shProg, location, count, 912 &loc, &offset, "glUniformMatrix", false)) 913 return; 914 915 if (values == NULL) { 916 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix"); 917 return; 918 } 919 920 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS); 921 922 uniform = &shProg->Uniforms->Uniforms[loc]; 923 924 if (shProg->_LinkedShaders[MESA_SHADER_VERTEX]) { 925 /* convert uniform location to program parameter index */ 926 GLint index = uniform->VertPos; 927 if (index >= 0) { 928 set_program_uniform_matrix(ctx, 929 shProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program, 930 index, offset, 931 count, rows, cols, transpose, values); 932 } 933 } 934 935 if (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { 936 /* convert uniform location to program parameter index */ 937 GLint index = uniform->FragPos; 938 if (index >= 0) { 939 set_program_uniform_matrix(ctx, 940 shProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program, 941 index, offset, 942 count, rows, cols, transpose, values); 943 } 944 } 945 946 if (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { 947 /* convert uniform location to program parameter index */ 948 GLint index = uniform->GeomPos; 949 if (index >= 0) { 950 set_program_uniform_matrix(ctx, 951 shProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program, 952 index, offset, 953 count, rows, cols, transpose, values); 954 } 955 } 956 957 uniform->Initialized = GL_TRUE; 958} 959 960/** 961 * Called via glGetUniformLocation(). 962 * 963 * The return value will encode two values, the uniform location and an 964 * offset (used for arrays, structs). 965 */ 966extern "C" GLint 967_mesa_get_uniform_location(struct gl_context *ctx, 968 struct gl_shader_program *shProg, 969 const GLchar *name) 970{ 971 GLint offset = 0, location = -1; 972 973 /* XXX we should return -1 if the uniform was declared, but not 974 * actually used. 975 */ 976 977 /* XXX we need to be able to parse uniform names for structs and arrays 978 * such as: 979 * mymatrix[1] 980 * mystruct.field1 981 */ 982 983 { 984 /* handle 1-dimension arrays here... */ 985 char *c = strchr((char *)name, '['); 986 if (c) { 987 /* truncate name at [ */ 988 const GLint len = c - name; 989 GLchar *newName = (GLchar *) malloc(len + 1); 990 if (!newName) 991 return -1; /* out of mem */ 992 memcpy(newName, name, len); 993 newName[len] = 0; 994 995 location = _mesa_lookup_uniform(shProg->Uniforms, newName); 996 if (location >= 0) { 997 const GLint element = atoi(c + 1); 998 if (element > 0) { 999 /* get type of the uniform array element */ 1000 const struct gl_program_parameter *p = 1001 get_uniform_parameter(shProg, location); 1002 if (p) { 1003 GLint rows, cols; 1004 get_matrix_dims(p->DataType, &rows, &cols); 1005 if (rows < 1) 1006 rows = 1; 1007 offset = element * rows; 1008 } 1009 } 1010 } 1011 1012 free(newName); 1013 } 1014 } 1015 1016 if (location < 0) { 1017 location = _mesa_lookup_uniform(shProg->Uniforms, name); 1018 } 1019 1020 if (location < 0) { 1021 return -1; 1022 } 1023 1024 return _mesa_uniform_merge_location_offset(location, offset); 1025} 1026