Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenshader_api.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.5 00004 * 00005 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved. 00006 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 00007 * 00008 * Permission is hereby granted, free of charge, to any person obtaining a 00009 * copy of this software and associated documentation files (the "Software"), 00010 * to deal in the Software without restriction, including without limitation 00011 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00012 * and/or sell copies of the Software, and to permit persons to whom the 00013 * Software is furnished to do so, subject to the following conditions: 00014 * 00015 * The above copyright notice and this permission notice shall be included 00016 * in all copies or substantial portions of the Software. 00017 * 00018 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00019 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00020 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00021 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00022 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00023 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00024 */ 00025 00039 #include "main/glheader.h" 00040 #include "main/context.h" 00041 #include "main/hash.h" 00042 #include "main/macros.h" 00043 #include "shader/program.h" 00044 #include "shader/prog_parameter.h" 00045 #include "shader/prog_print.h" 00046 #include "shader/prog_statevars.h" 00047 #include "shader/prog_uniform.h" 00048 #include "shader/shader_api.h" 00049 #include "shader/slang/slang_compile.h" 00050 #include "shader/slang/slang_link.h" 00051 #include "glapi/dispatch.h" 00052 00053 00054 #ifndef GL_PROGRAM_BINARY_LENGTH_OES 00055 #define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 00056 #endif 00057 00058 00062 static struct gl_shader_program * 00063 _mesa_new_shader_program(GLcontext *ctx, GLuint name) 00064 { 00065 struct gl_shader_program *shProg; 00066 shProg = CALLOC_STRUCT(gl_shader_program); 00067 if (shProg) { 00068 shProg->Type = GL_SHADER_PROGRAM_MESA; 00069 shProg->Name = name; 00070 shProg->RefCount = 1; 00071 shProg->Attributes = _mesa_new_parameter_list(); 00072 } 00073 return shProg; 00074 } 00075 00076 00080 void 00081 _mesa_clear_shader_program_data(GLcontext *ctx, 00082 struct gl_shader_program *shProg) 00083 { 00084 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL); 00085 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL); 00086 00087 if (shProg->Uniforms) { 00088 _mesa_free_uniform_list(shProg->Uniforms); 00089 shProg->Uniforms = NULL; 00090 } 00091 00092 if (shProg->Varying) { 00093 _mesa_free_parameter_list(shProg->Varying); 00094 shProg->Varying = NULL; 00095 } 00096 } 00097 00098 00103 void 00104 _mesa_free_shader_program_data(GLcontext *ctx, 00105 struct gl_shader_program *shProg) 00106 { 00107 GLuint i; 00108 00109 assert(shProg->Type == GL_SHADER_PROGRAM_MESA); 00110 00111 _mesa_clear_shader_program_data(ctx, shProg); 00112 00113 if (shProg->Attributes) { 00114 _mesa_free_parameter_list(shProg->Attributes); 00115 shProg->Attributes = NULL; 00116 } 00117 00118 /* detach shaders */ 00119 for (i = 0; i < shProg->NumShaders; i++) { 00120 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); 00121 } 00122 shProg->NumShaders = 0; 00123 00124 if (shProg->Shaders) { 00125 _mesa_free(shProg->Shaders); 00126 shProg->Shaders = NULL; 00127 } 00128 00129 if (shProg->InfoLog) { 00130 _mesa_free(shProg->InfoLog); 00131 shProg->InfoLog = NULL; 00132 } 00133 } 00134 00135 00139 void 00140 _mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg) 00141 { 00142 _mesa_free_shader_program_data(ctx, shProg); 00143 00144 _mesa_free(shProg); 00145 } 00146 00147 00154 /* XXX this could be static */ 00155 void 00156 _mesa_reference_shader_program(GLcontext *ctx, 00157 struct gl_shader_program **ptr, 00158 struct gl_shader_program *shProg) 00159 { 00160 assert(ptr); 00161 if (*ptr == shProg) { 00162 /* no-op */ 00163 return; 00164 } 00165 if (*ptr) { 00166 /* Unreference the old shader program */ 00167 GLboolean deleteFlag = GL_FALSE; 00168 struct gl_shader_program *old = *ptr; 00169 00170 ASSERT(old->RefCount > 0); 00171 old->RefCount--; 00172 #if 0 00173 printf("ShaderProgram %p ID=%u RefCount-- to %d\n", 00174 (void *) old, old->Name, old->RefCount); 00175 #endif 00176 deleteFlag = (old->RefCount == 0); 00177 00178 if (deleteFlag) { 00179 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); 00180 _mesa_free_shader_program(ctx, old); 00181 } 00182 00183 *ptr = NULL; 00184 } 00185 assert(!*ptr); 00186 00187 if (shProg) { 00188 shProg->RefCount++; 00189 #if 0 00190 printf("ShaderProgram %p ID=%u RefCount++ to %d\n", 00191 (void *) shProg, shProg->Name, shProg->RefCount); 00192 #endif 00193 *ptr = shProg; 00194 } 00195 } 00196 00197 00201 struct gl_shader_program * 00202 _mesa_lookup_shader_program(GLcontext *ctx, GLuint name) 00203 { 00204 struct gl_shader_program *shProg; 00205 if (name) { 00206 shProg = (struct gl_shader_program *) 00207 _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 00208 /* Note that both gl_shader and gl_shader_program objects are kept 00209 * in the same hash table. Check the object's type to be sure it's 00210 * what we're expecting. 00211 */ 00212 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) { 00213 return NULL; 00214 } 00215 return shProg; 00216 } 00217 return NULL; 00218 } 00219 00220 00224 static struct gl_shader_program * 00225 _mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name, 00226 const char *caller) 00227 { 00228 if (!name) { 00229 _mesa_error(ctx, GL_INVALID_VALUE, caller); 00230 return NULL; 00231 } 00232 else { 00233 struct gl_shader_program *shProg = (struct gl_shader_program *) 00234 _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 00235 if (!shProg) { 00236 _mesa_error(ctx, GL_INVALID_VALUE, caller); 00237 return NULL; 00238 } 00239 if (shProg->Type != GL_SHADER_PROGRAM_MESA) { 00240 _mesa_error(ctx, GL_INVALID_OPERATION, caller); 00241 return NULL; 00242 } 00243 return shProg; 00244 } 00245 } 00246 00247 00248 00249 00253 struct gl_shader * 00254 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type) 00255 { 00256 struct gl_shader *shader; 00257 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER); 00258 shader = CALLOC_STRUCT(gl_shader); 00259 if (shader) { 00260 shader->Type = type; 00261 shader->Name = name; 00262 shader->RefCount = 1; 00263 } 00264 return shader; 00265 } 00266 00267 00268 void 00269 _mesa_free_shader(GLcontext *ctx, struct gl_shader *sh) 00270 { 00271 if (sh->Source) 00272 _mesa_free((void *) sh->Source); 00273 if (sh->InfoLog) 00274 _mesa_free(sh->InfoLog); 00275 _mesa_reference_program(ctx, &sh->Program, NULL); 00276 _mesa_free(sh); 00277 } 00278 00279 00286 /* XXX this could be static */ 00287 void 00288 _mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr, 00289 struct gl_shader *sh) 00290 { 00291 assert(ptr); 00292 if (*ptr == sh) { 00293 /* no-op */ 00294 return; 00295 } 00296 if (*ptr) { 00297 /* Unreference the old shader */ 00298 GLboolean deleteFlag = GL_FALSE; 00299 struct gl_shader *old = *ptr; 00300 00301 ASSERT(old->RefCount > 0); 00302 old->RefCount--; 00303 /*printf("SHADER DECR %p (%d) to %d\n", 00304 (void*) old, old->Name, old->RefCount);*/ 00305 deleteFlag = (old->RefCount == 0); 00306 00307 if (deleteFlag) { 00308 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name); 00309 _mesa_free_shader(ctx, old); 00310 } 00311 00312 *ptr = NULL; 00313 } 00314 assert(!*ptr); 00315 00316 if (sh) { 00317 /* reference new */ 00318 sh->RefCount++; 00319 /*printf("SHADER INCR %p (%d) to %d\n", 00320 (void*) sh, sh->Name, sh->RefCount);*/ 00321 *ptr = sh; 00322 } 00323 } 00324 00325 00329 struct gl_shader * 00330 _mesa_lookup_shader(GLcontext *ctx, GLuint name) 00331 { 00332 if (name) { 00333 struct gl_shader *sh = (struct gl_shader *) 00334 _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 00335 /* Note that both gl_shader and gl_shader_program objects are kept 00336 * in the same hash table. Check the object's type to be sure it's 00337 * what we're expecting. 00338 */ 00339 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) { 00340 return NULL; 00341 } 00342 return sh; 00343 } 00344 return NULL; 00345 } 00346 00347 00351 static struct gl_shader * 00352 _mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller) 00353 { 00354 if (!name) { 00355 _mesa_error(ctx, GL_INVALID_VALUE, caller); 00356 return NULL; 00357 } 00358 else { 00359 struct gl_shader *sh = (struct gl_shader *) 00360 _mesa_HashLookup(ctx->Shared->ShaderObjects, name); 00361 if (!sh) { 00362 _mesa_error(ctx, GL_INVALID_VALUE, caller); 00363 return NULL; 00364 } 00365 if (sh->Type == GL_SHADER_PROGRAM_MESA) { 00366 _mesa_error(ctx, GL_INVALID_OPERATION, caller); 00367 return NULL; 00368 } 00369 return sh; 00370 } 00371 } 00372 00373 00374 00378 void 00379 _mesa_init_shader_state(GLcontext * ctx) 00380 { 00381 /* Device drivers may override these to control what kind of instructions 00382 * are generated by the GLSL compiler. 00383 */ 00384 ctx->Shader.EmitHighLevelInstructions = GL_TRUE; 00385 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */ 00386 ctx->Shader.EmitComments = GL_FALSE; 00387 } 00388 00389 00393 void 00394 _mesa_free_shader_state(GLcontext *ctx) 00395 { 00396 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL); 00397 } 00398 00399 00408 static void 00409 copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src) 00410 { 00411 GLsizei len; 00412 for (len = 0; len < maxLength - 1 && src && src[len]; len++) 00413 dst[len] = src[len]; 00414 if (maxLength > 0) 00415 dst[len] = 0; 00416 if (length) 00417 *length = len; 00418 } 00419 00420 00421 static GLboolean 00422 _mesa_is_program(GLcontext *ctx, GLuint name) 00423 { 00424 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name); 00425 return shProg ? GL_TRUE : GL_FALSE; 00426 } 00427 00428 00429 static GLboolean 00430 _mesa_is_shader(GLcontext *ctx, GLuint name) 00431 { 00432 struct gl_shader *shader = _mesa_lookup_shader(ctx, name); 00433 return shader ? GL_TRUE : GL_FALSE; 00434 } 00435 00436 00440 static void 00441 _mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader) 00442 { 00443 struct gl_shader_program *shProg; 00444 struct gl_shader *sh; 00445 GLuint i, n; 00446 00447 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); 00448 if (!shProg) 00449 return; 00450 00451 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); 00452 if (!sh) { 00453 return; 00454 } 00455 00456 n = shProg->NumShaders; 00457 for (i = 0; i < n; i++) { 00458 if (shProg->Shaders[i] == sh) { 00459 /* The shader is already attched to this program. The 00460 * GL_ARB_shader_objects spec says: 00461 * 00462 * "The error INVALID_OPERATION is generated by AttachObjectARB 00463 * if <obj> is already attached to <containerObj>." 00464 */ 00465 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); 00466 return; 00467 } 00468 } 00469 00470 /* grow list */ 00471 shProg->Shaders = (struct gl_shader **) 00472 _mesa_realloc(shProg->Shaders, 00473 n * sizeof(struct gl_shader *), 00474 (n + 1) * sizeof(struct gl_shader *)); 00475 if (!shProg->Shaders) { 00476 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); 00477 return; 00478 } 00479 00480 /* append */ 00481 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ 00482 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); 00483 shProg->NumShaders++; 00484 } 00485 00486 00487 static GLint 00488 _mesa_get_attrib_location(GLcontext *ctx, GLuint program, 00489 const GLchar *name) 00490 { 00491 struct gl_shader_program *shProg 00492 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); 00493 00494 if (!shProg) { 00495 return -1; 00496 } 00497 00498 if (!shProg->LinkStatus) { 00499 _mesa_error(ctx, GL_INVALID_OPERATION, 00500 "glGetAttribLocation(program not linked)"); 00501 return -1; 00502 } 00503 00504 if (!name) 00505 return -1; 00506 00507 if (shProg->VertexProgram) { 00508 const struct gl_program_parameter_list *attribs = 00509 shProg->VertexProgram->Base.Attributes; 00510 if (attribs) { 00511 GLint i = _mesa_lookup_parameter_index(attribs, -1, name); 00512 if (i >= 0) { 00513 return attribs->Parameters[i].StateIndexes[0]; 00514 } 00515 } 00516 } 00517 return -1; 00518 } 00519 00520 00521 static void 00522 _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, 00523 const GLchar *name) 00524 { 00525 struct gl_shader_program *shProg; 00526 const GLint size = -1; /* unknown size */ 00527 GLint i, oldIndex; 00528 GLenum datatype = GL_FLOAT_VEC4; 00529 00530 shProg = _mesa_lookup_shader_program_err(ctx, program, 00531 "glBindAttribLocation"); 00532 if (!shProg) { 00533 return; 00534 } 00535 00536 if (!name) 00537 return; 00538 00539 if (strncmp(name, "gl_", 3) == 0) { 00540 _mesa_error(ctx, GL_INVALID_OPERATION, 00541 "glBindAttribLocation(illegal name)"); 00542 return; 00543 } 00544 00545 if (index >= ctx->Const.VertexProgram.MaxAttribs) { 00546 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)"); 00547 return; 00548 } 00549 00550 if (shProg->LinkStatus) { 00551 /* get current index/location for the attribute */ 00552 oldIndex = _mesa_get_attrib_location(ctx, program, name); 00553 } 00554 else { 00555 oldIndex = -1; 00556 } 00557 00558 /* this will replace the current value if it's already in the list */ 00559 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index); 00560 if (i < 0) { 00561 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation"); 00562 return; 00563 } 00564 00565 /* 00566 * Note that this attribute binding won't go into effect until 00567 * glLinkProgram is called again. 00568 */ 00569 } 00570 00571 00572 static GLuint 00573 _mesa_create_shader(GLcontext *ctx, GLenum type) 00574 { 00575 struct gl_shader *sh; 00576 GLuint name; 00577 00578 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); 00579 00580 switch (type) { 00581 case GL_FRAGMENT_SHADER: 00582 case GL_VERTEX_SHADER: 00583 sh = _mesa_new_shader(ctx, name, type); 00584 break; 00585 default: 00586 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); 00587 return 0; 00588 } 00589 00590 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); 00591 00592 return name; 00593 } 00594 00595 00596 static GLuint 00597 _mesa_create_program(GLcontext *ctx) 00598 { 00599 GLuint name; 00600 struct gl_shader_program *shProg; 00601 00602 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); 00603 shProg = _mesa_new_shader_program(ctx, name); 00604 00605 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); 00606 00607 assert(shProg->RefCount == 1); 00608 00609 return name; 00610 } 00611 00612 00617 static void 00618 _mesa_delete_program2(GLcontext *ctx, GLuint name) 00619 { 00620 /* 00621 * NOTE: deleting shaders/programs works a bit differently than 00622 * texture objects (and buffer objects, etc). Shader/program 00623 * handles/IDs exist in the hash table until the object is really 00624 * deleted (refcount==0). With texture objects, the handle/ID is 00625 * removed from the hash table in glDeleteTextures() while the tex 00626 * object itself might linger until its refcount goes to zero. 00627 */ 00628 struct gl_shader_program *shProg; 00629 00630 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram"); 00631 if (!shProg) 00632 return; 00633 00634 shProg->DeletePending = GL_TRUE; 00635 00636 /* effectively, decr shProg's refcount */ 00637 _mesa_reference_shader_program(ctx, &shProg, NULL); 00638 } 00639 00640 00641 static void 00642 _mesa_delete_shader(GLcontext *ctx, GLuint shader) 00643 { 00644 struct gl_shader *sh; 00645 00646 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader"); 00647 if (!sh) 00648 return; 00649 00650 sh->DeletePending = GL_TRUE; 00651 00652 /* effectively, decr sh's refcount */ 00653 _mesa_reference_shader(ctx, &sh, NULL); 00654 } 00655 00656 00657 static void 00658 _mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader) 00659 { 00660 struct gl_shader_program *shProg; 00661 GLuint n; 00662 GLuint i, j; 00663 00664 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader"); 00665 if (!shProg) 00666 return; 00667 00668 n = shProg->NumShaders; 00669 00670 for (i = 0; i < n; i++) { 00671 if (shProg->Shaders[i]->Name == shader) { 00672 /* found it */ 00673 struct gl_shader **newList; 00674 00675 /* release */ 00676 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); 00677 00678 /* alloc new, smaller array */ 00679 newList = (struct gl_shader **) 00680 _mesa_malloc((n - 1) * sizeof(struct gl_shader *)); 00681 if (!newList) { 00682 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); 00683 return; 00684 } 00685 for (j = 0; j < i; j++) { 00686 newList[j] = shProg->Shaders[j]; 00687 } 00688 while (++i < n) 00689 newList[j++] = shProg->Shaders[i]; 00690 _mesa_free(shProg->Shaders); 00691 00692 shProg->Shaders = newList; 00693 shProg->NumShaders = n - 1; 00694 00695 #ifdef DEBUG 00696 /* sanity check */ 00697 { 00698 for (j = 0; j < shProg->NumShaders; j++) { 00699 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || 00700 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); 00701 assert(shProg->Shaders[j]->RefCount > 0); 00702 } 00703 } 00704 #endif 00705 00706 return; 00707 } 00708 } 00709 00710 /* not found */ 00711 { 00712 GLenum err; 00713 if (_mesa_is_shader(ctx, shader)) 00714 err = GL_INVALID_OPERATION; 00715 else if (_mesa_is_program(ctx, shader)) 00716 err = GL_INVALID_OPERATION; 00717 else 00718 err = GL_INVALID_VALUE; 00719 _mesa_error(ctx, err, "glDetachProgram(shader)"); 00720 return; 00721 } 00722 } 00723 00724 00725 static GLint 00726 sizeof_glsl_type(GLenum type) 00727 { 00728 switch (type) { 00729 case GL_FLOAT: 00730 case GL_INT: 00731 case GL_BOOL: 00732 case GL_SAMPLER_1D: 00733 case GL_SAMPLER_2D: 00734 case GL_SAMPLER_3D: 00735 case GL_SAMPLER_CUBE: 00736 case GL_SAMPLER_1D_SHADOW: 00737 case GL_SAMPLER_2D_SHADOW: 00738 case GL_SAMPLER_2D_RECT_ARB: 00739 case GL_SAMPLER_2D_RECT_SHADOW_ARB: 00740 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: 00741 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: 00742 case GL_SAMPLER_CUBE_SHADOW_EXT: 00743 return 1; 00744 case GL_FLOAT_VEC2: 00745 case GL_INT_VEC2: 00746 case GL_BOOL_VEC2: 00747 return 2; 00748 case GL_FLOAT_VEC3: 00749 case GL_INT_VEC3: 00750 case GL_BOOL_VEC3: 00751 return 3; 00752 case GL_FLOAT_VEC4: 00753 case GL_INT_VEC4: 00754 case GL_BOOL_VEC4: 00755 return 4; 00756 case GL_FLOAT_MAT2: 00757 case GL_FLOAT_MAT2x3: 00758 case GL_FLOAT_MAT2x4: 00759 return 8; /* two float[4] vectors */ 00760 case GL_FLOAT_MAT3: 00761 case GL_FLOAT_MAT3x2: 00762 case GL_FLOAT_MAT3x4: 00763 return 12; /* three float[4] vectors */ 00764 case GL_FLOAT_MAT4: 00765 case GL_FLOAT_MAT4x2: 00766 case GL_FLOAT_MAT4x3: 00767 return 16; /* four float[4] vectors */ 00768 default: 00769 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()"); 00770 return 1; 00771 } 00772 } 00773 00774 00775 static GLboolean 00776 is_boolean_type(GLenum type) 00777 { 00778 switch (type) { 00779 case GL_BOOL: 00780 case GL_BOOL_VEC2: 00781 case GL_BOOL_VEC3: 00782 case GL_BOOL_VEC4: 00783 return GL_TRUE; 00784 default: 00785 return GL_FALSE; 00786 } 00787 } 00788 00789 00790 static GLboolean 00791 is_integer_type(GLenum type) 00792 { 00793 switch (type) { 00794 case GL_INT: 00795 case GL_INT_VEC2: 00796 case GL_INT_VEC3: 00797 case GL_INT_VEC4: 00798 return GL_TRUE; 00799 default: 00800 return GL_FALSE; 00801 } 00802 } 00803 00804 00805 static GLboolean 00806 is_sampler_type(GLenum type) 00807 { 00808 switch (type) { 00809 case GL_SAMPLER_1D: 00810 case GL_SAMPLER_2D: 00811 case GL_SAMPLER_3D: 00812 case GL_SAMPLER_CUBE: 00813 case GL_SAMPLER_1D_SHADOW: 00814 case GL_SAMPLER_2D_SHADOW: 00815 case GL_SAMPLER_2D_RECT_ARB: 00816 case GL_SAMPLER_2D_RECT_SHADOW_ARB: 00817 case GL_SAMPLER_1D_ARRAY_EXT: 00818 case GL_SAMPLER_2D_ARRAY_EXT: 00819 return GL_TRUE; 00820 default: 00821 return GL_FALSE; 00822 } 00823 } 00824 00825 00826 static void 00827 _mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index, 00828 GLsizei maxLength, GLsizei *length, GLint *size, 00829 GLenum *type, GLchar *nameOut) 00830 { 00831 const struct gl_program_parameter_list *attribs = NULL; 00832 struct gl_shader_program *shProg; 00833 00834 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); 00835 if (!shProg) 00836 return; 00837 00838 if (shProg->VertexProgram) 00839 attribs = shProg->VertexProgram->Base.Attributes; 00840 00841 if (!attribs || index >= attribs->NumParameters) { 00842 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); 00843 return; 00844 } 00845 00846 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name); 00847 00848 if (size) 00849 *size = attribs->Parameters[index].Size 00850 / sizeof_glsl_type(attribs->Parameters[index].DataType); 00851 00852 if (type) 00853 *type = attribs->Parameters[index].DataType; 00854 } 00855 00856 00857 static struct gl_program_parameter * 00858 get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index) 00859 { 00860 const struct gl_program *prog; 00861 GLint progPos; 00862 00863 progPos = shProg->Uniforms->Uniforms[index].VertPos; 00864 if (progPos >= 0) { 00865 prog = &shProg->VertexProgram->Base; 00866 } 00867 else { 00868 progPos = shProg->Uniforms->Uniforms[index].FragPos; 00869 if (progPos >= 0) { 00870 prog = &shProg->FragmentProgram->Base; 00871 } 00872 } 00873 00874 if (!prog || progPos < 0) 00875 return NULL; /* should never happen */ 00876 00877 return &prog->Parameters->Parameters[progPos]; 00878 } 00879 00880 00884 static void 00885 _mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index, 00886 GLsizei maxLength, GLsizei *length, GLint *size, 00887 GLenum *type, GLchar *nameOut) 00888 { 00889 const struct gl_shader_program *shProg; 00890 const struct gl_program *prog; 00891 const struct gl_program_parameter *param; 00892 GLint progPos; 00893 00894 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform"); 00895 if (!shProg) 00896 return; 00897 00898 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) { 00899 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)"); 00900 return; 00901 } 00902 00903 progPos = shProg->Uniforms->Uniforms[index].VertPos; 00904 if (progPos >= 0) { 00905 prog = &shProg->VertexProgram->Base; 00906 } 00907 else { 00908 progPos = shProg->Uniforms->Uniforms[index].FragPos; 00909 if (progPos >= 0) { 00910 prog = &shProg->FragmentProgram->Base; 00911 } 00912 } 00913 00914 if (!prog || progPos < 0) 00915 return; /* should never happen */ 00916 00917 ASSERT(progPos < prog->Parameters->NumParameters); 00918 param = &prog->Parameters->Parameters[progPos]; 00919 00920 if (nameOut) { 00921 copy_string(nameOut, maxLength, length, param->Name); 00922 } 00923 00924 if (size) { 00925 GLint typeSize = sizeof_glsl_type(param->DataType); 00926 if (param->Size > typeSize) { 00927 /* This is an array. 00928 * Array elements are placed on vector[4] boundaries so they're 00929 * a multiple of four floats. We round typeSize up to next multiple 00930 * of four to get the right size below. 00931 */ 00932 typeSize = (typeSize + 3) & ~3; 00933 } 00934 /* Note that the returned size is in units of the <type>, not bytes */ 00935 *size = param->Size / typeSize; 00936 } 00937 00938 if (type) { 00939 *type = param->DataType; 00940 } 00941 } 00942 00943 00947 static void 00948 _mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount, 00949 GLsizei *count, GLuint *obj) 00950 { 00951 struct gl_shader_program *shProg = 00952 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders"); 00953 if (shProg) { 00954 GLuint i; 00955 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) { 00956 obj[i] = shProg->Shaders[i]->Name; 00957 } 00958 if (count) 00959 *count = i; 00960 } 00961 } 00962 00963 00964 static GLuint 00965 _mesa_get_handle(GLcontext *ctx, GLenum pname) 00966 { 00967 GLint handle = 0; 00968 00969 if (pname == GL_PROGRAM_OBJECT_ARB) { 00970 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle)); 00971 } else { 00972 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); 00973 } 00974 00975 return handle; 00976 } 00977 00978 00979 static void 00980 _mesa_get_programiv(GLcontext *ctx, GLuint program, 00981 GLenum pname, GLint *params) 00982 { 00983 const struct gl_program_parameter_list *attribs; 00984 struct gl_shader_program *shProg 00985 = _mesa_lookup_shader_program(ctx, program); 00986 00987 if (!shProg) { 00988 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)"); 00989 return; 00990 } 00991 00992 if (shProg->VertexProgram) 00993 attribs = shProg->VertexProgram->Base.Attributes; 00994 else 00995 attribs = NULL; 00996 00997 switch (pname) { 00998 case GL_DELETE_STATUS: 00999 *params = shProg->DeletePending; 01000 break; 01001 case GL_LINK_STATUS: 01002 *params = shProg->LinkStatus; 01003 break; 01004 case GL_VALIDATE_STATUS: 01005 *params = shProg->Validated; 01006 break; 01007 case GL_INFO_LOG_LENGTH: 01008 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0; 01009 break; 01010 case GL_ATTACHED_SHADERS: 01011 *params = shProg->NumShaders; 01012 break; 01013 case GL_ACTIVE_ATTRIBUTES: 01014 *params = attribs ? attribs->NumParameters : 0; 01015 break; 01016 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 01017 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1; 01018 break; 01019 case GL_ACTIVE_UNIFORMS: 01020 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0; 01021 break; 01022 case GL_ACTIVE_UNIFORM_MAX_LENGTH: 01023 *params = _mesa_longest_uniform_name(shProg->Uniforms); 01024 if (*params > 0) 01025 (*params)++; /* add one for terminating zero */ 01026 break; 01027 case GL_PROGRAM_BINARY_LENGTH_OES: 01028 *params = 0; 01029 break; 01030 default: 01031 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); 01032 return; 01033 } 01034 } 01035 01036 01037 static void 01038 _mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params) 01039 { 01040 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv"); 01041 01042 if (!shader) { 01043 return; 01044 } 01045 01046 switch (pname) { 01047 case GL_SHADER_TYPE: 01048 *params = shader->Type; 01049 break; 01050 case GL_DELETE_STATUS: 01051 *params = shader->DeletePending; 01052 break; 01053 case GL_COMPILE_STATUS: 01054 *params = shader->CompileStatus; 01055 break; 01056 case GL_INFO_LOG_LENGTH: 01057 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; 01058 break; 01059 case GL_SHADER_SOURCE_LENGTH: 01060 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0; 01061 break; 01062 default: 01063 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); 01064 return; 01065 } 01066 } 01067 01068 01069 static void 01070 _mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize, 01071 GLsizei *length, GLchar *infoLog) 01072 { 01073 struct gl_shader_program *shProg 01074 = _mesa_lookup_shader_program(ctx, program); 01075 if (!shProg) { 01076 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)"); 01077 return; 01078 } 01079 copy_string(infoLog, bufSize, length, shProg->InfoLog); 01080 } 01081 01082 01083 static void 01084 _mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize, 01085 GLsizei *length, GLchar *infoLog) 01086 { 01087 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); 01088 if (!sh) { 01089 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); 01090 return; 01091 } 01092 copy_string(infoLog, bufSize, length, sh->InfoLog); 01093 } 01094 01095 01099 static void 01100 _mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength, 01101 GLsizei *length, GLchar *sourceOut) 01102 { 01103 struct gl_shader *sh; 01104 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource"); 01105 if (!sh) { 01106 return; 01107 } 01108 copy_string(sourceOut, maxLength, length, sh->Source); 01109 } 01110 01111 01112 static void 01113 get_matrix_dims(GLenum type, GLint *rows, GLint *cols) 01114 { 01115 switch (type) { 01116 case GL_FLOAT_MAT2: 01117 *rows = *cols = 2; 01118 break; 01119 case GL_FLOAT_MAT2x3: 01120 *rows = 3; 01121 *cols = 2; 01122 break; 01123 case GL_FLOAT_MAT2x4: 01124 *rows = 4; 01125 *cols = 2; 01126 break; 01127 case GL_FLOAT_MAT3: 01128 *rows = 3; 01129 *cols = 3; 01130 break; 01131 case GL_FLOAT_MAT3x2: 01132 *rows = 2; 01133 *cols = 3; 01134 break; 01135 case GL_FLOAT_MAT3x4: 01136 *rows = 4; 01137 *cols = 3; 01138 break; 01139 case GL_FLOAT_MAT4: 01140 *rows = 4; 01141 *cols = 4; 01142 break; 01143 case GL_FLOAT_MAT4x2: 01144 *rows = 2; 01145 *cols = 4; 01146 break; 01147 case GL_FLOAT_MAT4x3: 01148 *rows = 3; 01149 *cols = 4; 01150 break; 01151 default: 01152 *rows = *cols = 0; 01153 } 01154 } 01155 01156 01161 static void 01162 get_uniform_rows_cols(const struct gl_program_parameter *p, 01163 GLint *rows, GLint *cols) 01164 { 01165 get_matrix_dims(p->DataType, rows, cols); 01166 if (*rows == 0 && *cols == 0) { 01167 /* not a matrix type, probably a float or vector */ 01168 *rows = p->Size / 4 + 1; 01169 if (p->Size % 4 == 0) 01170 *cols = 4; 01171 else 01172 *cols = p->Size % 4; 01173 } 01174 } 01175 01176 01182 static void 01183 lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location, 01184 struct gl_program **progOut, GLint *paramPosOut) 01185 { 01186 struct gl_shader_program *shProg 01187 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v"); 01188 struct gl_program *prog = NULL; 01189 GLint progPos = -1; 01190 01191 /* if shProg is NULL, we'll have already recorded an error */ 01192 01193 if (shProg) { 01194 if (!shProg->Uniforms || 01195 location < 0 || 01196 location >= (GLint) shProg->Uniforms->NumUniforms) { 01197 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)"); 01198 } 01199 else { 01200 /* OK, find the gl_program and program parameter location */ 01201 progPos = shProg->Uniforms->Uniforms[location].VertPos; 01202 if (progPos >= 0) { 01203 prog = &shProg->VertexProgram->Base; 01204 } 01205 else { 01206 progPos = shProg->Uniforms->Uniforms[location].FragPos; 01207 if (progPos >= 0) { 01208 prog = &shProg->FragmentProgram->Base; 01209 } 01210 } 01211 } 01212 } 01213 01214 *progOut = prog; 01215 *paramPosOut = progPos; 01216 } 01217 01218 01222 static void 01223 _mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location, 01224 GLfloat *params) 01225 { 01226 struct gl_program *prog; 01227 GLint paramPos; 01228 01229 lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); 01230 01231 if (prog) { 01232 const struct gl_program_parameter *p = 01233 &prog->Parameters->Parameters[paramPos]; 01234 GLint rows, cols, i, j, k; 01235 01236 get_uniform_rows_cols(p, &rows, &cols); 01237 01238 k = 0; 01239 for (i = 0; i < rows; i++) { 01240 for (j = 0; j < cols; j++ ) { 01241 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j]; 01242 } 01243 } 01244 } 01245 } 01246 01247 01252 static void 01253 _mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location, 01254 GLint *params) 01255 { 01256 struct gl_program *prog; 01257 GLint paramPos; 01258 01259 lookup_uniform_parameter(ctx, program, location, &prog, ¶mPos); 01260 01261 if (prog) { 01262 const struct gl_program_parameter *p = 01263 &prog->Parameters->Parameters[paramPos]; 01264 GLint rows, cols, i, j, k; 01265 01266 get_uniform_rows_cols(p, &rows, &cols); 01267 01268 k = 0; 01269 for (i = 0; i < rows; i++) { 01270 for (j = 0; j < cols; j++ ) { 01271 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j]; 01272 } 01273 } 01274 } 01275 } 01276 01277 01285 static void 01286 merge_location_offset(GLint *location, GLint offset) 01287 { 01288 *location = *location | (offset << 16); 01289 } 01290 01291 01295 static void 01296 split_location_offset(GLint *location, GLint *offset) 01297 { 01298 *offset = (*location >> 16); 01299 *location = *location & 0xffff; 01300 } 01301 01302 01309 static GLint 01310 _mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name) 01311 { 01312 GLint offset = 0, location = -1; 01313 01314 struct gl_shader_program *shProg = 01315 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation"); 01316 01317 if (!shProg) 01318 return -1; 01319 01320 if (shProg->LinkStatus == GL_FALSE) { 01321 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)"); 01322 return -1; 01323 } 01324 01325 /* XXX we should return -1 if the uniform was declared, but not 01326 * actually used. 01327 */ 01328 01329 /* XXX we need to be able to parse uniform names for structs and arrays 01330 * such as: 01331 * mymatrix[1] 01332 * mystruct.field1 01333 */ 01334 01335 { 01336 /* handle 1-dimension arrays here... */ 01337 char *c = strchr(name, '['); 01338 if (c) { 01339 /* truncate name at [ */ 01340 const GLint len = c - name; 01341 GLchar *newName = _mesa_malloc(len + 1); 01342 if (!newName) 01343 return -1; /* out of mem */ 01344 _mesa_memcpy(newName, name, len); 01345 newName[len] = 0; 01346 01347 location = _mesa_lookup_uniform(shProg->Uniforms, newName); 01348 if (location >= 0) { 01349 const GLint element = _mesa_atoi(c + 1); 01350 if (element > 0) { 01351 /* get type of the uniform array element */ 01352 struct gl_program_parameter *p; 01353 p = get_uniform_parameter(shProg, location); 01354 if (p) { 01355 GLint rows, cols; 01356 get_matrix_dims(p->DataType, &rows, &cols); 01357 if (rows < 1) 01358 rows = 1; 01359 offset = element * rows; 01360 } 01361 } 01362 } 01363 01364 _mesa_free(newName); 01365 } 01366 } 01367 01368 if (location < 0) { 01369 location = _mesa_lookup_uniform(shProg->Uniforms, name); 01370 } 01371 01372 if (location >= 0) { 01373 merge_location_offset(&location, offset); 01374 } 01375 01376 return location; 01377 } 01378 01379 01380 01384 static void 01385 _mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source) 01386 { 01387 struct gl_shader *sh; 01388 01389 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource"); 01390 if (!sh) 01391 return; 01392 01393 /* free old shader source string and install new one */ 01394 if (sh->Source) { 01395 _mesa_free((void *) sh->Source); 01396 } 01397 sh->Source = source; 01398 sh->CompileStatus = GL_FALSE; 01399 } 01400 01401 01405 static void 01406 _mesa_compile_shader(GLcontext *ctx, GLuint shaderObj) 01407 { 01408 struct gl_shader *sh; 01409 01410 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader"); 01411 if (!sh) 01412 return; 01413 01414 sh->CompileStatus = _slang_compile(ctx, sh); 01415 } 01416 01417 01421 static void 01422 _mesa_link_program(GLcontext *ctx, GLuint program) 01423 { 01424 struct gl_shader_program *shProg; 01425 01426 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram"); 01427 if (!shProg) 01428 return; 01429 01430 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 01431 01432 _slang_link(ctx, program, shProg); 01433 } 01434 01435 01439 void 01440 _mesa_use_program(GLcontext *ctx, GLuint program) 01441 { 01442 struct gl_shader_program *shProg; 01443 01444 if (ctx->Shader.CurrentProgram && 01445 ctx->Shader.CurrentProgram->Name == program) { 01446 /* no-op */ 01447 return; 01448 } 01449 01450 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 01451 01452 if (program) { 01453 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); 01454 if (!shProg) { 01455 return; 01456 } 01457 if (!shProg->LinkStatus) { 01458 _mesa_error(ctx, GL_INVALID_OPERATION, 01459 "glUseProgram(program %u not linked)", program); 01460 return; 01461 } 01462 } 01463 else { 01464 shProg = NULL; 01465 } 01466 01467 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg); 01468 } 01469 01470 01471 01487 void 01488 _mesa_update_shader_textures_used(struct gl_program *prog) 01489 { 01490 GLuint s; 01491 01492 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed)); 01493 01494 for (s = 0; s < MAX_SAMPLERS; s++) { 01495 if (prog->SamplersUsed & (1 << s)) { 01496 GLuint u = prog->SamplerUnits[s]; 01497 GLuint t = prog->SamplerTargets[s]; 01498 assert(u < MAX_TEXTURE_IMAGE_UNITS); 01499 prog->TexturesUsed[u] |= (1 << t); 01500 } 01501 } 01502 } 01503 01504 01510 static GLboolean 01511 compatible_types(GLenum userType, GLenum targetType) 01512 { 01513 if (userType == targetType) 01514 return GL_TRUE; 01515 01516 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT)) 01517 return GL_TRUE; 01518 01519 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 || 01520 userType == GL_INT_VEC2)) 01521 return GL_TRUE; 01522 01523 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 || 01524 userType == GL_INT_VEC3)) 01525 return GL_TRUE; 01526 01527 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 || 01528 userType == GL_INT_VEC4)) 01529 return GL_TRUE; 01530 01531 if (is_sampler_type(targetType) && userType == GL_INT) 01532 return GL_TRUE; 01533 01534 return GL_FALSE; 01535 } 01536 01537 01548 static void 01549 set_program_uniform(GLcontext *ctx, struct gl_program *program, 01550 GLint index, GLint offset, 01551 GLenum type, GLsizei count, GLint elems, 01552 const void *values) 01553 { 01554 struct gl_program_parameter *param = 01555 &program->Parameters->Parameters[index]; 01556 const GLboolean isUniformBool = is_boolean_type(param->DataType); 01557 const GLboolean areIntValues = is_integer_type(type); 01558 01559 assert(offset >= 0); 01560 assert(elems >= 1); 01561 assert(elems <= 4); 01562 01563 if (!compatible_types(type, param->DataType)) { 01564 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)"); 01565 return; 01566 } 01567 01568 if (index + offset > program->Parameters->Size) { 01569 /* out of bounds! */ 01570 return; 01571 } 01572 01573 if (param->Type == PROGRAM_SAMPLER) { 01574 /* This controls which texture unit which is used by a sampler */ 01575 GLuint texUnit, sampler; 01576 GLint i; 01577 01578 /* data type for setting samplers must be int */ 01579 if (type != GL_INT) { 01580 _mesa_error(ctx, GL_INVALID_OPERATION, 01581 "glUniform(only glUniform1i can be used " 01582 "to set sampler uniforms)"); 01583 return; 01584 } 01585 01586 /* XXX arrays of samplers haven't been tested much, but it's not a 01587 * common thing... 01588 */ 01589 for (i = 0; i < count; i++) { 01590 sampler = (GLuint) program->Parameters->ParameterValues[index + i][0]; 01591 texUnit = ((GLuint *) values)[i]; 01592 01593 /* check that the sampler (tex unit index) is legal */ 01594 if (texUnit >= ctx->Const.MaxTextureImageUnits) { 01595 _mesa_error(ctx, GL_INVALID_VALUE, 01596 "glUniform1(invalid sampler/tex unit index)"); 01597 return; 01598 } 01599 01600 /* This maps a sampler to a texture unit: */ 01601 if (sampler < MAX_SAMPLERS) { 01602 program->SamplerUnits[sampler] = texUnit; 01603 } 01604 } 01605 01606 _mesa_update_shader_textures_used(program); 01607 01608 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 01609 } 01610 else { 01611 /* ordinary uniform variable */ 01612 GLsizei k, i; 01613 const GLint slots = (param->Size + 3) / 4; 01614 const GLint typeSize = sizeof_glsl_type(param->DataType); 01615 01616 if (param->Size > typeSize) { 01617 /* an array */ 01618 /* we'll ignore extra data below */ 01619 } 01620 else { 01621 /* non-array: count must be one */ 01622 if (count != 1) { 01623 _mesa_error(ctx, GL_INVALID_OPERATION, 01624 "glUniform(uniform is not an array)"); 01625 return; 01626 } 01627 } 01628 01629 /* loop over number of array elements */ 01630 for (k = 0; k < count; k++) { 01631 GLfloat *uniformVal; 01632 01633 if (offset + k >= slots) { 01634 /* Extra array data is ignored */ 01635 break; 01636 } 01637 01638 /* uniformVal (the destination) is always float[4] */ 01639 uniformVal = program->Parameters->ParameterValues[index + offset + k]; 01640 01641 if (areIntValues) { 01642 /* convert user's ints to floats */ 01643 const GLint *iValues = ((const GLint *) values) + k * elems; 01644 for (i = 0; i < elems; i++) { 01645 uniformVal[i] = (GLfloat) iValues[i]; 01646 } 01647 } 01648 else { 01649 const GLfloat *fValues = ((const GLfloat *) values) + k * elems; 01650 for (i = 0; i < elems; i++) { 01651 uniformVal[i] = fValues[i]; 01652 } 01653 } 01654 01655 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */ 01656 if (isUniformBool) { 01657 for (i = 0; i < elems; i++) { 01658 uniformVal[i] = uniformVal[i] ? 1.0 : 0.0; 01659 } 01660 } 01661 } 01662 } 01663 } 01664 01665 01669 static void 01670 _mesa_uniform(GLcontext *ctx, GLint location, GLsizei count, 01671 const GLvoid *values, GLenum type) 01672 { 01673 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 01674 struct gl_uniform *uniform; 01675 GLint elems, offset; 01676 01677 if (!shProg || !shProg->LinkStatus) { 01678 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)"); 01679 return; 01680 } 01681 01682 if (location == -1) 01683 return; /* The standard specifies this as a no-op */ 01684 01685 if (location < -1) { 01686 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)"); 01687 return; 01688 } 01689 01690 split_location_offset(&location, &offset); 01691 01692 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { 01693 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)"); 01694 return; 01695 } 01696 01697 if (count < 0) { 01698 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)"); 01699 return; 01700 } 01701 01702 switch (type) { 01703 case GL_FLOAT: 01704 case GL_INT: 01705 elems = 1; 01706 break; 01707 case GL_FLOAT_VEC2: 01708 case GL_INT_VEC2: 01709 elems = 2; 01710 break; 01711 case GL_FLOAT_VEC3: 01712 case GL_INT_VEC3: 01713 elems = 3; 01714 break; 01715 case GL_FLOAT_VEC4: 01716 case GL_INT_VEC4: 01717 elems = 4; 01718 break; 01719 default: 01720 _mesa_problem(ctx, "Invalid type in _mesa_uniform"); 01721 return; 01722 } 01723 01724 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 01725 01726 uniform = &shProg->Uniforms->Uniforms[location]; 01727 01728 /* A uniform var may be used by both a vertex shader and a fragment 01729 * shader. We may need to update one or both shader's uniform here: 01730 */ 01731 if (shProg->VertexProgram) { 01732 /* convert uniform location to program parameter index */ 01733 GLint index = uniform->VertPos; 01734 if (index >= 0) { 01735 set_program_uniform(ctx, &shProg->VertexProgram->Base, 01736 index, offset, type, count, elems, values); 01737 } 01738 } 01739 01740 if (shProg->FragmentProgram) { 01741 /* convert uniform location to program parameter index */ 01742 GLint index = uniform->FragPos; 01743 if (index >= 0) { 01744 set_program_uniform(ctx, &shProg->FragmentProgram->Base, 01745 index, offset, type, count, elems, values); 01746 } 01747 } 01748 01749 uniform->Initialized = GL_TRUE; 01750 } 01751 01752 01756 static void 01757 set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program, 01758 GLuint index, GLuint offset, 01759 GLuint count, GLuint rows, GLuint cols, 01760 GLboolean transpose, const GLfloat *values) 01761 { 01762 GLuint mat, row, col; 01763 GLuint dst = index + offset, src = 0; 01764 GLint nr, nc; 01765 01766 /* check that the number of rows, columns is correct */ 01767 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc); 01768 if (rows != nr || cols != nc) { 01769 _mesa_error(ctx, GL_INVALID_OPERATION, 01770 "glUniformMatrix(matrix size mismatch)"); 01771 return; 01772 } 01773 01774 if (index + offset > program->Parameters->Size) { 01775 /* out of bounds! */ 01776 return; 01777 } 01778 01779 /* 01780 * Note: the _columns_ of a matrix are stored in program registers, not 01781 * the rows. So, the loops below look a little funny. 01782 * XXX could optimize this a bit... 01783 */ 01784 01785 /* loop over matrices */ 01786 for (mat = 0; mat < count; mat++) { 01787 01788 /* each matrix: */ 01789 for (col = 0; col < cols; col++) { 01790 GLfloat *v = program->Parameters->ParameterValues[dst]; 01791 for (row = 0; row < rows; row++) { 01792 if (transpose) { 01793 v[row] = values[src + row * cols + col]; 01794 } 01795 else { 01796 v[row] = values[src + col * rows + row]; 01797 } 01798 } 01799 dst++; 01800 } 01801 01802 src += rows * cols; /* next matrix */ 01803 } 01804 } 01805 01806 01811 static void 01812 _mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows, 01813 GLenum matrixType, GLint location, GLsizei count, 01814 GLboolean transpose, const GLfloat *values) 01815 { 01816 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram; 01817 struct gl_uniform *uniform; 01818 GLint offset; 01819 01820 if (!shProg || !shProg->LinkStatus) { 01821 _mesa_error(ctx, GL_INVALID_OPERATION, 01822 "glUniformMatrix(program not linked)"); 01823 return; 01824 } 01825 01826 if (location == -1) 01827 return; /* The standard specifies this as a no-op */ 01828 01829 if (location < -1) { 01830 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)"); 01831 return; 01832 } 01833 01834 split_location_offset(&location, &offset); 01835 01836 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) { 01837 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)"); 01838 return; 01839 } 01840 if (values == NULL) { 01841 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix"); 01842 return; 01843 } 01844 01845 FLUSH_VERTICES(ctx, _NEW_PROGRAM); 01846 01847 uniform = &shProg->Uniforms->Uniforms[location]; 01848 01849 if (shProg->VertexProgram) { 01850 /* convert uniform location to program parameter index */ 01851 GLint index = uniform->VertPos; 01852 if (index >= 0) { 01853 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base, 01854 index, offset, 01855 count, rows, cols, transpose, values); 01856 } 01857 } 01858 01859 if (shProg->FragmentProgram) { 01860 /* convert uniform location to program parameter index */ 01861 GLint index = uniform->FragPos; 01862 if (index >= 0) { 01863 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base, 01864 index, offset, 01865 count, rows, cols, transpose, values); 01866 } 01867 } 01868 01869 uniform->Initialized = GL_TRUE; 01870 } 01871 01872 01873 static void 01874 _mesa_validate_program(GLcontext *ctx, GLuint program) 01875 { 01876 struct gl_shader_program *shProg; 01877 01878 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram"); 01879 if (!shProg) { 01880 return; 01881 } 01882 01883 if (!shProg->LinkStatus) { 01884 shProg->Validated = GL_FALSE; 01885 return; 01886 } 01887 01888 /* From the GL spec, a program is invalid if any of these are true: 01889 01890 any two active samplers in the current program object are of 01891 different types, but refer to the same texture image unit, 01892 01893 any active sampler in the current program object refers to a texture 01894 image unit where fixed-function fragment processing accesses a 01895 texture target that does not match the sampler type, or 01896 01897 the sum of the number of active samplers in the program and the 01898 number of texture image units enabled for fixed-function fragment 01899 processing exceeds the combined limit on the total number of texture 01900 image units allowed. 01901 */ 01902 01903 shProg->Validated = GL_TRUE; 01904 } 01905 01906 01910 void 01911 _mesa_init_glsl_driver_functions(struct dd_function_table *driver) 01912 { 01913 driver->AttachShader = _mesa_attach_shader; 01914 driver->BindAttribLocation = _mesa_bind_attrib_location; 01915 driver->CompileShader = _mesa_compile_shader; 01916 driver->CreateProgram = _mesa_create_program; 01917 driver->CreateShader = _mesa_create_shader; 01918 driver->DeleteProgram2 = _mesa_delete_program2; 01919 driver->DeleteShader = _mesa_delete_shader; 01920 driver->DetachShader = _mesa_detach_shader; 01921 driver->GetActiveAttrib = _mesa_get_active_attrib; 01922 driver->GetActiveUniform = _mesa_get_active_uniform; 01923 driver->GetAttachedShaders = _mesa_get_attached_shaders; 01924 driver->GetAttribLocation = _mesa_get_attrib_location; 01925 driver->GetHandle = _mesa_get_handle; 01926 driver->GetProgramiv = _mesa_get_programiv; 01927 driver->GetProgramInfoLog = _mesa_get_program_info_log; 01928 driver->GetShaderiv = _mesa_get_shaderiv; 01929 driver->GetShaderInfoLog = _mesa_get_shader_info_log; 01930 driver->GetShaderSource = _mesa_get_shader_source; 01931 driver->GetUniformfv = _mesa_get_uniformfv; 01932 driver->GetUniformiv = _mesa_get_uniformiv; 01933 driver->GetUniformLocation = _mesa_get_uniform_location; 01934 driver->IsProgram = _mesa_is_program; 01935 driver->IsShader = _mesa_is_shader; 01936 driver->LinkProgram = _mesa_link_program; 01937 driver->ShaderSource = _mesa_shader_source; 01938 driver->Uniform = _mesa_uniform; 01939 driver->UniformMatrix = _mesa_uniform_matrix; 01940 driver->UseProgram = _mesa_use_program; 01941 driver->ValidateProgram = _mesa_validate_program; 01942 } Generated on Sun May 27 2012 04:20:35 for ReactOS by
1.7.6.1
|