ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

shader_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, &paramPos);
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, &paramPos);
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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.