blob: 002b42721df7eb73c465ff100b494f12997f8151 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian5b01c5e2006-12-19 18:02:03 -07003 * Version: 6.5.3
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian5b01c5e2006-12-19 18:02:03 -07005 * Copyright (C) 2004-2007 Brian Paul All Rights Reserved.
Brian34ae99d2006-12-18 08:28:54 -07006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file shader_api.c
Brian5b01c5e2006-12-19 18:02:03 -070027 * Implementation of GLSL-related API functions
Brian34ae99d2006-12-18 08:28:54 -070028 * \author Brian Paul
29 */
30
31/**
32 * XXX things to do:
33 * 1. Check that the right error code is generated for all _mesa_error() calls.
Brian5b01c5e2006-12-19 18:02:03 -070034 * 2. Insert FLUSH_VERTICES calls in various places
Brian34ae99d2006-12-18 08:28:54 -070035 */
36
37
38#include "glheader.h"
39#include "context.h"
40#include "hash.h"
Brian34ae99d2006-12-18 08:28:54 -070041#include "program.h"
42#include "prog_parameter.h"
Brian3209c3e2007-01-09 17:49:24 -070043#include "prog_print.h"
44#include "prog_statevars.h"
Brian34ae99d2006-12-18 08:28:54 -070045#include "shader_api.h"
46
47#include "slang_compile.h"
48#include "slang_link.h"
49
50
51
Brianf2923612006-12-20 09:56:44 -070052/**
53 * Allocate a new gl_shader_program object, initialize it.
54 */
55struct gl_shader_program *
56_mesa_new_shader_program(GLcontext *ctx, GLuint name)
57{
58 struct gl_shader_program *shProg;
59 shProg = CALLOC_STRUCT(gl_shader_program);
60 if (shProg) {
61 shProg->Type = GL_SHADER_PROGRAM;
62 shProg->Name = name;
63 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070064 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070065 }
66 return shProg;
67}
68
69
70void
71_mesa_free_shader_program_data(GLcontext *ctx,
72 struct gl_shader_program *shProg)
73{
74 assert(shProg->Type == GL_SHADER_PROGRAM);
75
76 if (shProg->VertexProgram) {
77 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
78 /* to prevent a double-free in the next call */
79 shProg->VertexProgram->Base.Parameters = NULL;
80 }
81 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
82 shProg->VertexProgram = NULL;
83 }
84
85 if (shProg->FragmentProgram) {
86 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
87 /* to prevent a double-free in the next call */
88 shProg->FragmentProgram->Base.Parameters = NULL;
89 }
90 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
91 shProg->FragmentProgram = NULL;
92 }
93
94
95 if (shProg->Uniforms) {
96 _mesa_free_parameter_list(shProg->Uniforms);
97 shProg->Uniforms = NULL;
98 }
99
100 if (shProg->Varying) {
101 _mesa_free_parameter_list(shProg->Varying);
102 shProg->Varying = NULL;
103 }
104}
105
106
107
108void
109_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
110{
111 _mesa_free_shader_program_data(ctx, shProg);
112 _mesa_free(shProg);
113}
114
115
116/**
117 * Lookup a GLSL program object.
118 */
119struct gl_shader_program *
120_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
121{
122 struct gl_shader_program *shProg;
123 if (name) {
124 shProg = (struct gl_shader_program *)
125 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
126 /* Note that both gl_shader and gl_shader_program objects are kept
127 * in the same hash table. Check the object's type to be sure it's
128 * what we're expecting.
129 */
130 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
131 return NULL;
132 }
133 return shProg;
134 }
135 return NULL;
136}
137
138
139/**
140 * Allocate a new gl_shader object, initialize it.
141 */
142struct gl_shader *
143_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
144{
145 struct gl_shader *shader;
146 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
147 shader = CALLOC_STRUCT(gl_shader);
148 if (shader) {
149 shader->Type = type;
150 shader->Name = name;
151 shader->RefCount = 1;
152 }
153 return shader;
154}
155
156
157void
158_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
159{
160 GLuint i;
161 if (sh->Source)
162 _mesa_free((void *) sh->Source);
163 if (sh->InfoLog)
164 _mesa_free(sh->InfoLog);
165 for (i = 0; i < sh->NumPrograms; i++) {
166 assert(sh->Programs[i]);
167 _mesa_delete_program(ctx, sh->Programs[i]);
168 }
169 if (sh->Programs)
170 _mesa_free(sh->Programs);
171 _mesa_free(sh);
172}
173
174
175/**
176 * Lookup a GLSL shader object.
177 */
178struct gl_shader *
179_mesa_lookup_shader(GLcontext *ctx, GLuint name)
180{
181 if (name) {
182 struct gl_shader *sh = (struct gl_shader *)
183 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
184 /* Note that both gl_shader and gl_shader_program objects are kept
185 * in the same hash table. Check the object's type to be sure it's
186 * what we're expecting.
187 */
188 if (sh && sh->Type == GL_SHADER_PROGRAM) {
189 assert(sh->Type == GL_VERTEX_SHADER ||
190 sh->Type == GL_FRAGMENT_SHADER);
191 return NULL;
192 }
193 return sh;
194 }
195 return NULL;
196}
197
198
Brianfa4d0362007-02-26 18:33:50 -0700199/**
200 * Initialize context's shader state.
201 */
Brianf2923612006-12-20 09:56:44 -0700202void
203_mesa_init_shader_state(GLcontext * ctx)
204{
Brianfa4d0362007-02-26 18:33:50 -0700205 /* Device drivers may override these to control what kind of instructions
206 * are generated by the GLSL compiler.
207 */
208 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600209 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700210 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700211}
212
213
Brian5b01c5e2006-12-19 18:02:03 -0700214/**
Brian935f93f2007-03-24 16:20:02 -0600215 * Free the per-context shader-related state.
216 */
217void
218_mesa_free_shader_state(GLcontext *ctx)
219{
220 if (ctx->Shader.CurrentProgram) {
221 ctx->Shader.CurrentProgram->RefCount--;
222 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
223 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
224 ctx->Shader.CurrentProgram = NULL;
225 }
226 }
227}
228
229
230/**
Brian5b01c5e2006-12-19 18:02:03 -0700231 * Copy string from <src> to <dst>, up to maxLength characters, returning
232 * length of <dst> in <length>.
233 * \param src the strings source
234 * \param maxLength max chars to copy
235 * \param length returns number of chars copied
236 * \param dst the string destination
237 */
238static void
239copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
240{
241 GLsizei len;
242 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
243 dst[len] = src[len];
244 if (maxLength > 0)
245 dst[len] = 0;
246 if (length)
247 *length = len;
248}
249
250
Brian5b01c5e2006-12-19 18:02:03 -0700251/**
252 * Called via ctx->Driver.AttachShader()
253 */
254void
255_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
256{
Brian65a18442006-12-19 18:46:56 -0700257 struct gl_shader_program *shProg
258 = _mesa_lookup_shader_program(ctx, program);
259 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
260 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700261 GLuint i;
262
Brian65a18442006-12-19 18:46:56 -0700263 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700264 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700265 "glAttachShader(bad program or shader name)");
266 return;
267 }
268
269 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700270 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700271 /* already attached */
272 return;
Brian34ae99d2006-12-18 08:28:54 -0700273 }
274 }
Brian5b01c5e2006-12-19 18:02:03 -0700275
276 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700277 shProg->Shaders = (struct gl_shader **)
278 _mesa_realloc(shProg->Shaders,
279 n * sizeof(struct gl_shader *),
280 (n + 1) * sizeof(struct gl_shader *));
281 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700282 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
283 return;
284 }
285
286 /* append */
Brian65a18442006-12-19 18:46:56 -0700287 shProg->Shaders[n] = sh;
288 sh->RefCount++;
289 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700290}
291
292
293void
294_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
295 const GLchar *name)
296{
Brian65a18442006-12-19 18:46:56 -0700297 struct gl_shader_program *shProg
298 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700299 const GLint size = -1; /* unknown size */
300 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700301
Brian65a18442006-12-19 18:46:56 -0700302 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700303 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700304 return;
305 }
306
Brian9e4bae92006-12-20 09:27:42 -0700307 if (!name)
308 return;
309
310 if (strncmp(name, "gl_", 3) == 0) {
311 _mesa_error(ctx, GL_INVALID_OPERATION,
312 "glBindAttribLocation(illegal name)");
313 return;
314 }
315
Brian3209c3e2007-01-09 17:49:24 -0700316 oldIndex = _mesa_get_attrib_location(ctx, program, name);
317
318 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700319 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700320 if (i < 0) {
321 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
322 }
323
324 if (shProg->VertexProgram && oldIndex >= 0) {
325 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
326 }
327
Brian88e2dbf2007-01-10 13:33:38 -0700328#if 0
Brian3209c3e2007-01-09 17:49:24 -0700329 printf("===== post BindAttrib:\n");
330 _mesa_print_program(&shProg->VertexProgram->Base);
Brian88e2dbf2007-01-10 13:33:38 -0700331#endif
Brian34ae99d2006-12-18 08:28:54 -0700332}
333
334
Brian5b01c5e2006-12-19 18:02:03 -0700335GLuint
336_mesa_create_shader(GLcontext *ctx, GLenum type)
337{
Brian65a18442006-12-19 18:46:56 -0700338 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700339 GLuint name;
340
341 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
342
343 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700344 case GL_FRAGMENT_SHADER:
345 case GL_VERTEX_SHADER:
346 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700347 break;
348 default:
349 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
350 return 0;
351 }
352
Brian65a18442006-12-19 18:46:56 -0700353 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700354
355 return name;
356}
357
358
359GLuint
360_mesa_create_program(GLcontext *ctx)
361{
362 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700363 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700364
Brian65a18442006-12-19 18:46:56 -0700365 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
366 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700367
Brian65a18442006-12-19 18:46:56 -0700368 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700369
370 return name;
371}
372
373
374void
375_mesa_delete_program2(GLcontext *ctx, GLuint name)
376{
Brian65a18442006-12-19 18:46:56 -0700377 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700378
Brian65a18442006-12-19 18:46:56 -0700379 shProg = _mesa_lookup_shader_program(ctx, name);
380 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700381 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700382 return;
383 }
384
Brian9e4bae92006-12-20 09:27:42 -0700385 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700386 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700387
388 shProg->DeletePending = GL_TRUE;
389
390 /* decrement refcount, delete if zero */
391 shProg->RefCount--;
392 if (shProg->RefCount <= 0) {
393 _mesa_free_shader_program(ctx, shProg);
394 }
Brian5b01c5e2006-12-19 18:02:03 -0700395}
396
397
398void
399_mesa_delete_shader(GLcontext *ctx, GLuint shader)
400{
Brian9e4bae92006-12-20 09:27:42 -0700401 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
402 if (!sh) {
403 return;
404 }
Brian5b01c5e2006-12-19 18:02:03 -0700405
Brian9e4bae92006-12-20 09:27:42 -0700406 sh->DeletePending = GL_TRUE;
407 sh->RefCount--;
408 if (sh->RefCount <= 0) {
409 _mesa_free_shader(ctx, sh);
410 }
Brian5b01c5e2006-12-19 18:02:03 -0700411}
412
413
414void
415_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
416{
Brian65a18442006-12-19 18:46:56 -0700417 struct gl_shader_program *shProg
418 = _mesa_lookup_shader_program(ctx, program);
419 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700420 GLuint i, j;
421
Brian65a18442006-12-19 18:46:56 -0700422 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700423 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700424 "glDetachShader(bad program or shader name)");
425 return;
426 }
427
428 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700429 if (shProg->Shaders[i]->Name == shader) {
430 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700431 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700432
433 shProg->Shaders[i]->RefCount--;
434
Brian5b01c5e2006-12-19 18:02:03 -0700435 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700436 newList = (struct gl_shader **)
437 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700438 if (!newList) {
439 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
440 return;
441 }
442 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700443 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700444 }
445 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700446 newList[j++] = shProg->Shaders[i];
447 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700448
449 /* XXX refcounting! */
450
Brian65a18442006-12-19 18:46:56 -0700451 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700452 return;
453 }
454 }
455
456 /* not found */
Brian43975832007-01-04 08:21:09 -0700457 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700458 "glDetachShader(shader not found)");
459}
460
461
462void
463_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
464 GLsizei maxLength, GLsizei *length, GLint *size,
465 GLenum *type, GLchar *nameOut)
466{
467 static const GLenum vec_types[] = {
468 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
469 };
Brian65a18442006-12-19 18:46:56 -0700470 struct gl_shader_program *shProg
471 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700472 GLint sz;
473
Brian65a18442006-12-19 18:46:56 -0700474 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700475 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700476 return;
477 }
478
Brian65a18442006-12-19 18:46:56 -0700479 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700480 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
481 return;
482 }
483
484 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700485 shProg->Attributes->Parameters[index].Name);
486 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700487 if (size)
488 *size = sz;
489 if (type)
490 *type = vec_types[sz]; /* XXX this is a temporary hack */
491}
492
493
494/**
495 * Called via ctx->Driver.GetActiveUniform().
496 */
497void
498_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
499 GLsizei maxLength, GLsizei *length, GLint *size,
500 GLenum *type, GLchar *nameOut)
501{
502 static const GLenum vec_types[] = {
503 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
504 };
Brian65a18442006-12-19 18:46:56 -0700505 struct gl_shader_program *shProg
506 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700507 GLint sz;
508
Brian65a18442006-12-19 18:46:56 -0700509 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700510 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700511 return;
512 }
513
Brian65a18442006-12-19 18:46:56 -0700514 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700515 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
516 return;
517 }
518
519 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700520 shProg->Uniforms->Parameters[index].Name);
521 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700522 if (size)
523 *size = sz;
524 if (type)
525 *type = vec_types[sz]; /* XXX this is a temporary hack */
526}
527
528
529/**
530 * Called via ctx->Driver.GetAttachedShaders().
531 */
532void
533_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
534 GLsizei *count, GLuint *obj)
535{
Brian65a18442006-12-19 18:46:56 -0700536 struct gl_shader_program *shProg
537 = _mesa_lookup_shader_program(ctx, program);
538 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700539 GLint i;
Brian65a18442006-12-19 18:46:56 -0700540 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
541 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700542 }
543 if (count)
544 *count = i;
545 }
546 else {
Brian43975832007-01-04 08:21:09 -0700547 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700548 }
549}
550
551
552GLint
553_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
554 const GLchar *name)
555{
Brian65a18442006-12-19 18:46:56 -0700556 struct gl_shader_program *shProg
557 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700558
Brian65a18442006-12-19 18:46:56 -0700559 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700560 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700561 return -1;
562 }
563
Brian65a18442006-12-19 18:46:56 -0700564 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700565 _mesa_error(ctx, GL_INVALID_OPERATION,
566 "glGetAttribLocation(program not linked)");
567 return -1;
568 }
569
570 if (!name)
571 return -1;
572
Brian65a18442006-12-19 18:46:56 -0700573 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700574 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
575 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700576 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700577 }
578 }
579 return -1;
580}
581
582
583GLuint
584_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700585{
586#if 0
587 GET_CURRENT_CONTEXT(ctx);
588
589 switch (pname) {
590 case GL_PROGRAM_OBJECT_ARB:
591 {
Brian5b01c5e2006-12-19 18:02:03 -0700592 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700593
594 if (pro != NULL)
595 return (**pro)._container._generic.
596 GetName((struct gl2_generic_intf **) (pro));
597 }
598 break;
599 default:
600 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
601 }
602#endif
603 return 0;
604}
605
606
Brian5b01c5e2006-12-19 18:02:03 -0700607void
608_mesa_get_programiv(GLcontext *ctx, GLuint program,
609 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700610{
Brian65a18442006-12-19 18:46:56 -0700611 struct gl_shader_program *shProg
612 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700613
Brian65a18442006-12-19 18:46:56 -0700614 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700615 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700616 return;
617 }
618
Brian5b01c5e2006-12-19 18:02:03 -0700619 switch (pname) {
620 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700621 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700622 break;
623 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700624 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700625 break;
Brian5b01c5e2006-12-19 18:02:03 -0700626 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700627 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700628 break;
629 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700630 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700631 break;
632 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700633 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700634 break;
635 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700636 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700637 break;
638 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700639 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700640 break;
641 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700642 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700643 break;
644 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700645 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700646 break;
647 default:
Brian5b01c5e2006-12-19 18:02:03 -0700648 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
649 return;
Brian34ae99d2006-12-18 08:28:54 -0700650 }
Brian5b01c5e2006-12-19 18:02:03 -0700651}
Brian34ae99d2006-12-18 08:28:54 -0700652
Brian34ae99d2006-12-18 08:28:54 -0700653
Brian5b01c5e2006-12-19 18:02:03 -0700654void
655_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
656{
Brian65a18442006-12-19 18:46:56 -0700657 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700658
659 if (!shader) {
660 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
661 return;
662 }
Brian65a18442006-12-19 18:46:56 -0700663
Brian5b01c5e2006-12-19 18:02:03 -0700664 switch (pname) {
665 case GL_SHADER_TYPE:
666 *params = shader->Type;
667 break;
668 case GL_DELETE_STATUS:
669 *params = shader->DeletePending;
670 break;
671 case GL_COMPILE_STATUS:
672 *params = shader->CompileStatus;
673 break;
674 case GL_INFO_LOG_LENGTH:
675 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
676 break;
677 case GL_SHADER_SOURCE_LENGTH:
678 *params = shader->Source ? strlen((char *) shader->Source) : 0;
679 break;
680 default:
681 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
682 return;
683 }
684}
685
686
687void
688_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
689 GLsizei *length, GLchar *infoLog)
690{
Brian65a18442006-12-19 18:46:56 -0700691 struct gl_shader_program *shProg
692 = _mesa_lookup_shader_program(ctx, program);
693 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700694 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
695 return;
696 }
Brian65a18442006-12-19 18:46:56 -0700697 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700698}
699
700
701void
702_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
703 GLsizei *length, GLchar *infoLog)
704{
Brian65a18442006-12-19 18:46:56 -0700705 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
706 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700707 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
708 return;
709 }
Brian65a18442006-12-19 18:46:56 -0700710 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700711}
712
713
714/**
715 * Called via ctx->Driver.GetShaderSource().
716 */
717void
718_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
719 GLsizei *length, GLchar *sourceOut)
720{
Brian65a18442006-12-19 18:46:56 -0700721 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
722 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700723 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
724 return;
725 }
Brian65a18442006-12-19 18:46:56 -0700726 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700727}
728
729
730/**
731 * Called via ctx->Driver.GetUniformfv().
732 */
733void
734_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
735 GLfloat *params)
736{
Brian65a18442006-12-19 18:46:56 -0700737 struct gl_shader_program *shProg
738 = _mesa_lookup_shader_program(ctx, program);
739 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700740 GLint i;
Brian65a18442006-12-19 18:46:56 -0700741 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
742 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
743 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700744 }
745 }
746 else {
747 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
748 }
749 }
750 else {
Brian43975832007-01-04 08:21:09 -0700751 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700752 }
753}
754
755
756/**
757 * Called via ctx->Driver.GetUniformLocation().
758 */
759GLint
760_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
761{
Brian71623982007-01-30 16:55:03 -0700762 struct gl_shader_program *shProg
763 = _mesa_lookup_shader_program(ctx, program);
764 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700765 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700766 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700767 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700768 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700769 /* XXX this is a temporary simplification / short-cut.
770 * We need to handle things like "e.c[0].b" as seen in the
771 * GLSL orange book, page 189.
772 */
Brian5cf73262007-01-05 16:02:45 -0700773 if ((u->Type == PROGRAM_UNIFORM ||
774 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700775 return loc;
776 }
777 }
778 }
779 return -1;
780
781}
782
783
784GLboolean
785_mesa_is_program(GLcontext *ctx, GLuint name)
786{
Brian65a18442006-12-19 18:46:56 -0700787 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
788 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700789}
790
791
792GLboolean
793_mesa_is_shader(GLcontext *ctx, GLuint name)
794{
Brian65a18442006-12-19 18:46:56 -0700795 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700796 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700797}
798
799
800
Brian5b01c5e2006-12-19 18:02:03 -0700801/**
802 * Called via ctx->Driver.ShaderSource()
803 */
804void
805_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700806{
Brian65a18442006-12-19 18:46:56 -0700807 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
808 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700809 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700810 return;
811 }
812
Brian34ae99d2006-12-18 08:28:54 -0700813 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700814 if (sh->Source) {
815 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700816 }
Brian65a18442006-12-19 18:46:56 -0700817 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700818 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700819}
820
821
Brian5b01c5e2006-12-19 18:02:03 -0700822/**
823 * Called via ctx->Driver.CompileShader()
824 */
825void
826_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700827{
Brian65a18442006-12-19 18:46:56 -0700828 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700829
Brian65a18442006-12-19 18:46:56 -0700830 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700831 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
832 return;
833 }
834
Brian43975832007-01-04 08:21:09 -0700835 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700836}
837
838
Brian5b01c5e2006-12-19 18:02:03 -0700839/**
840 * Called via ctx->Driver.LinkProgram()
841 */
842void
843_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700844{
Brian65a18442006-12-19 18:46:56 -0700845 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700846
Brian65a18442006-12-19 18:46:56 -0700847 shProg = _mesa_lookup_shader_program(ctx, program);
848 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700849 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700850 return;
851 }
852
Brianc1771912007-02-16 09:56:19 -0700853 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700854}
855
856
857/**
Brian5b01c5e2006-12-19 18:02:03 -0700858 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700859 */
Brian5b01c5e2006-12-19 18:02:03 -0700860void
861_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700862{
Brian00d63aa2007-02-03 11:35:02 -0700863 if (ctx->Shader.CurrentProgram &&
864 ctx->Shader.CurrentProgram->Name == program) {
865 /* no-op */
866 return;
867 }
868
869 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
870
Brian9e4bae92006-12-20 09:27:42 -0700871 /* unbind old */
872 if (ctx->Shader.CurrentProgram) {
873 ctx->Shader.CurrentProgram->RefCount--;
874 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
875 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
876 }
877 ctx->Shader.CurrentProgram = NULL;
878 }
879
Brian5b01c5e2006-12-19 18:02:03 -0700880 if (program) {
Brian65a18442006-12-19 18:46:56 -0700881 struct gl_shader_program *shProg;
882 shProg = _mesa_lookup_shader_program(ctx, program);
883 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700884 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700885 "glUseProgramObjectARB(programObj)");
886 return;
887 }
Brian65a18442006-12-19 18:46:56 -0700888 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700889 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700890 }
891 else {
892 /* don't use a shader program */
893 ctx->Shader.CurrentProgram = NULL;
894 }
895}
Brian34ae99d2006-12-18 08:28:54 -0700896
Brian5b01c5e2006-12-19 18:02:03 -0700897
898/**
899 * Called via ctx->Driver.Uniform().
900 */
901void
902_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
903 const GLvoid *values, GLenum type)
904{
Brian3a8e2772006-12-20 17:19:16 -0700905 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -0600906 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -0700907
908 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700909 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700910 return;
911 }
912
Brian223d7cb2007-01-23 16:37:51 -0700913 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700914 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
915 return;
916 }
917
918 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
919
Brianfee9bbe2007-02-02 18:05:43 -0700920 /*
921 * If we're setting a sampler, we must use glUniformi1()!
922 */
923 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
924 if (type != GL_INT || count != 1) {
925 _mesa_error(ctx, GL_INVALID_OPERATION,
926 "glUniform(only glUniform1i can be used "
927 "to set sampler uniforms)");
928 return;
929 }
930 }
931
Brian52363952007-03-13 16:50:24 -0600932 if (count < 0) {
933 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
934 return;
935 }
936
Brian98650bd2007-03-13 16:32:48 -0600937 switch (type) {
938 case GL_FLOAT:
939 case GL_INT:
940 elems = 1;
941 break;
942 case GL_FLOAT_VEC2:
943 case GL_INT_VEC2:
944 elems = 2;
945 break;
946 case GL_FLOAT_VEC3:
947 case GL_INT_VEC3:
948 elems = 3;
949 break;
950 case GL_FLOAT_VEC4:
951 case GL_INT_VEC4:
952 elems = 4;
953 break;
954 default:
955 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
956 return;
Brian89dc4852007-01-04 14:35:44 -0700957 }
Brian98650bd2007-03-13 16:32:48 -0600958
959 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
960 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
961 return;
962 }
963
964 for (k = 0; k < count; k++) {
965 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
966 if (type == GL_INT ||
967 type == GL_INT_VEC2 ||
968 type == GL_INT_VEC3 ||
969 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -0600970 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600971 for (i = 0; i < elems; i++) {
972 uniformVal[i] = (GLfloat) iValues[i];
973 }
974 }
975 else {
Brian52363952007-03-13 16:50:24 -0600976 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600977 for (i = 0; i < elems; i++) {
978 uniformVal[i] = fValues[i];
979 }
Brian89dc4852007-01-04 14:35:44 -0700980 }
Brian5b01c5e2006-12-19 18:02:03 -0700981 }
Brian5cf73262007-01-05 16:02:45 -0700982
983 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -0700984 if (shProg->VertexProgram)
985 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
986 if (shProg->FragmentProgram)
987 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -0700988 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
989 }
Brian34ae99d2006-12-18 08:28:54 -0700990}
991
992
993/**
Brian5b01c5e2006-12-19 18:02:03 -0700994 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700995 */
Brian5b01c5e2006-12-19 18:02:03 -0700996void
997_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
998 GLenum matrixType, GLint location, GLsizei count,
999 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001000{
Brian3a8e2772006-12-20 17:19:16 -07001001 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1002 if (!shProg || !shProg->LinkStatus) {
1003 _mesa_error(ctx, GL_INVALID_OPERATION,
1004 "glUniformMatrix(program not linked)");
1005 return;
1006 }
1007 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
1008 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1009 return;
1010 }
Brian34ae99d2006-12-18 08:28:54 -07001011 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001012 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001013 return;
1014 }
1015
1016 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1017
Brian3a8e2772006-12-20 17:19:16 -07001018 /*
1019 * Note: the _columns_ of a matrix are stored in program registers, not
1020 * the rows.
1021 */
1022 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001023 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001024 GLuint row, col;
1025 for (col = 0; col < cols; col++) {
1026 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1027 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001028 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001029 }
Brian34ae99d2006-12-18 08:28:54 -07001030 }
Brian34ae99d2006-12-18 08:28:54 -07001031 }
1032 else {
Brian3a8e2772006-12-20 17:19:16 -07001033 GLuint row, col;
1034 for (col = 0; col < cols; col++) {
1035 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1036 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001037 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001038 }
1039 }
Brian34ae99d2006-12-18 08:28:54 -07001040 }
1041}
1042
1043
Brian5b01c5e2006-12-19 18:02:03 -07001044void
1045_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001046{
Brian65a18442006-12-19 18:46:56 -07001047 struct gl_shader_program *shProg;
1048 shProg = _mesa_lookup_shader_program(ctx, program);
1049 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001050 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001051 return;
1052 }
Brian5b01c5e2006-12-19 18:02:03 -07001053 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001054 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001055
Brian5b01c5e2006-12-19 18:02:03 -07001056 /* From the GL spec:
1057 any two active samplers in the current program object are of
1058 different types, but refer to the same texture image unit,
1059
1060 any active sampler in the current program object refers to a texture
1061 image unit where fixed-function fragment processing accesses a
1062 texture target that does not match the sampler type, or
1063
1064 the sum of the number of active samplers in the program and the
1065 number of texture image units enabled for fixed-function fragment
1066 processing exceeds the combined limit on the total number of texture
1067 image units allowed.
1068 */
Brian34ae99d2006-12-18 08:28:54 -07001069}