blob: a8390d30942796df7095d3cad392a05af6ad9391 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian Paulc4ffbf02009-02-18 17:46:00 -07003 * Version: 7.5
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian Paul8c51e002008-08-11 15:09:47 -06005 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
Brian Paulc4ffbf02009-02-18 17:46:00 -07006 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
Brian34ae99d2006-12-18 08:28:54 -07007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * \file shader_api.c
Brian5b01c5e2006-12-19 18:02:03 -070028 * Implementation of GLSL-related API functions
Brian34ae99d2006-12-18 08:28:54 -070029 * \author Brian Paul
30 */
31
32/**
33 * XXX things to do:
34 * 1. Check that the right error code is generated for all _mesa_error() calls.
Brian5b01c5e2006-12-19 18:02:03 -070035 * 2. Insert FLUSH_VERTICES calls in various places
Brian34ae99d2006-12-18 08:28:54 -070036 */
37
38
Brian Paulbbd28712008-09-18 12:26:54 -060039#include "main/glheader.h"
40#include "main/context.h"
41#include "main/hash.h"
42#include "main/macros.h"
43#include "shader/program.h"
44#include "shader/prog_parameter.h"
45#include "shader/prog_print.h"
46#include "shader/prog_statevars.h"
47#include "shader/prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060048#include "shader/shader_api.h"
49#include "shader/slang/slang_compile.h"
50#include "shader/slang/slang_link.h"
Ian Romanick905d8e02008-09-29 12:27:00 -070051#include "glapi/dispatch.h"
Brian34ae99d2006-12-18 08:28:54 -070052
53
Brianf2923612006-12-20 09:56:44 -070054/**
55 * Allocate a new gl_shader_program object, initialize it.
56 */
Brian Paulfd59f192008-05-18 16:04:55 -060057static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070058_mesa_new_shader_program(GLcontext *ctx, GLuint name)
59{
60 struct gl_shader_program *shProg;
61 shProg = CALLOC_STRUCT(gl_shader_program);
62 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060063 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070064 shProg->Name = name;
65 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070066 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070067 }
68 return shProg;
69}
70
71
Brianb9fbedd2007-03-26 09:23:44 -060072/**
Brian3c008a02007-04-12 15:22:32 -060073 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060074 */
Brianf2923612006-12-20 09:56:44 -070075void
Brian3c008a02007-04-12 15:22:32 -060076_mesa_clear_shader_program_data(GLcontext *ctx,
77 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070078{
Brian Paul8bdf5b62008-05-16 09:56:59 -060079 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
80 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070081
Brianf2923612006-12-20 09:56:44 -070082 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060083 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070084 shProg->Uniforms = NULL;
85 }
86
87 if (shProg->Varying) {
88 _mesa_free_parameter_list(shProg->Varying);
89 shProg->Varying = NULL;
90 }
91}
92
93
Brianb9fbedd2007-03-26 09:23:44 -060094/**
Brian3c008a02007-04-12 15:22:32 -060095 * Free all the data that hangs off a shader program object, but not the
96 * object itself.
97 */
98void
99_mesa_free_shader_program_data(GLcontext *ctx,
100 struct gl_shader_program *shProg)
101{
102 GLuint i;
103
Brianf3e8c322007-04-18 14:53:23 -0600104 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600105
106 _mesa_clear_shader_program_data(ctx, shProg);
107
Brian4b7c6fc2007-04-19 15:23:34 -0600108 if (shProg->Attributes) {
109 _mesa_free_parameter_list(shProg->Attributes);
110 shProg->Attributes = NULL;
111 }
112
Brian3c008a02007-04-12 15:22:32 -0600113 /* detach shaders */
114 for (i = 0; i < shProg->NumShaders; i++) {
115 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
116 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800117 shProg->NumShaders = 0;
118
Brian3c008a02007-04-12 15:22:32 -0600119 if (shProg->Shaders) {
120 _mesa_free(shProg->Shaders);
121 shProg->Shaders = NULL;
122 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100123
124 if (shProg->InfoLog) {
125 _mesa_free(shProg->InfoLog);
126 shProg->InfoLog = NULL;
127 }
Brian3c008a02007-04-12 15:22:32 -0600128}
129
130
131/**
Brianb9fbedd2007-03-26 09:23:44 -0600132 * Free/delete a shader program object.
133 */
Brianf2923612006-12-20 09:56:44 -0700134void
135_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
136{
137 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100138
Brianf2923612006-12-20 09:56:44 -0700139 _mesa_free(shProg);
140}
141
142
143/**
Brian3c008a02007-04-12 15:22:32 -0600144 * Set ptr to point to shProg.
145 * If ptr is pointing to another object, decrement its refcount (and delete
146 * if refcount hits zero).
147 * Then set ptr to point to shProg, incrementing its refcount.
148 */
149/* XXX this could be static */
150void
151_mesa_reference_shader_program(GLcontext *ctx,
152 struct gl_shader_program **ptr,
153 struct gl_shader_program *shProg)
154{
155 assert(ptr);
156 if (*ptr == shProg) {
157 /* no-op */
158 return;
159 }
160 if (*ptr) {
161 /* Unreference the old shader program */
162 GLboolean deleteFlag = GL_FALSE;
163 struct gl_shader_program *old = *ptr;
164
165 ASSERT(old->RefCount > 0);
166 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600167#if 0
168 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
169 (void *) old, old->Name, old->RefCount);
170#endif
Brian3c008a02007-04-12 15:22:32 -0600171 deleteFlag = (old->RefCount == 0);
172
173 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800174 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600175 _mesa_free_shader_program(ctx, old);
176 }
177
178 *ptr = NULL;
179 }
180 assert(!*ptr);
181
182 if (shProg) {
183 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600184#if 0
185 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
186 (void *) shProg, shProg->Name, shProg->RefCount);
187#endif
Brian3c008a02007-04-12 15:22:32 -0600188 *ptr = shProg;
189 }
190}
191
192
193/**
Brianf2923612006-12-20 09:56:44 -0700194 * Lookup a GLSL program object.
195 */
196struct gl_shader_program *
197_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
198{
199 struct gl_shader_program *shProg;
200 if (name) {
201 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800202 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700203 /* Note that both gl_shader and gl_shader_program objects are kept
204 * in the same hash table. Check the object's type to be sure it's
205 * what we're expecting.
206 */
Brianf3e8c322007-04-18 14:53:23 -0600207 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700208 return NULL;
209 }
210 return shProg;
211 }
212 return NULL;
213}
214
215
216/**
Brian Paul530df582008-07-03 16:21:11 -0600217 * As above, but record an error if program is not found.
218 */
219static struct gl_shader_program *
220_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
221 const char *caller)
222{
223 if (!name) {
224 _mesa_error(ctx, GL_INVALID_VALUE, caller);
225 return NULL;
226 }
227 else {
228 struct gl_shader_program *shProg = (struct gl_shader_program *)
229 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
230 if (!shProg) {
231 _mesa_error(ctx, GL_INVALID_VALUE, caller);
232 return NULL;
233 }
234 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
235 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
236 return NULL;
237 }
238 return shProg;
239 }
240}
241
242
243
244
245/**
Brianf2923612006-12-20 09:56:44 -0700246 * Allocate a new gl_shader object, initialize it.
247 */
248struct gl_shader *
249_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
250{
251 struct gl_shader *shader;
252 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
253 shader = CALLOC_STRUCT(gl_shader);
254 if (shader) {
255 shader->Type = type;
256 shader->Name = name;
257 shader->RefCount = 1;
258 }
259 return shader;
260}
261
262
263void
264_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
265{
Brianf2923612006-12-20 09:56:44 -0700266 if (sh->Source)
267 _mesa_free((void *) sh->Source);
268 if (sh->InfoLog)
269 _mesa_free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600270 _mesa_reference_program(ctx, &sh->Program, NULL);
Brianf2923612006-12-20 09:56:44 -0700271 _mesa_free(sh);
272}
273
274
275/**
Brian3c008a02007-04-12 15:22:32 -0600276 * Set ptr to point to sh.
277 * If ptr is pointing to another shader, decrement its refcount (and delete
278 * if refcount hits zero).
279 * Then set ptr to point to sh, incrementing its refcount.
280 */
281/* XXX this could be static */
282void
283_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
284 struct gl_shader *sh)
285{
286 assert(ptr);
287 if (*ptr == sh) {
288 /* no-op */
289 return;
290 }
291 if (*ptr) {
292 /* Unreference the old shader */
293 GLboolean deleteFlag = GL_FALSE;
294 struct gl_shader *old = *ptr;
295
296 ASSERT(old->RefCount > 0);
297 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600298 /*printf("SHADER DECR %p (%d) to %d\n",
299 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600300 deleteFlag = (old->RefCount == 0);
301
302 if (deleteFlag) {
303 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
304 _mesa_free_shader(ctx, old);
305 }
306
307 *ptr = NULL;
308 }
309 assert(!*ptr);
310
311 if (sh) {
312 /* reference new */
313 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600314 /*printf("SHADER INCR %p (%d) to %d\n",
315 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600316 *ptr = sh;
317 }
318}
319
320
321/**
Brianf2923612006-12-20 09:56:44 -0700322 * Lookup a GLSL shader object.
323 */
324struct gl_shader *
325_mesa_lookup_shader(GLcontext *ctx, GLuint name)
326{
327 if (name) {
328 struct gl_shader *sh = (struct gl_shader *)
329 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
330 /* Note that both gl_shader and gl_shader_program objects are kept
331 * in the same hash table. Check the object's type to be sure it's
332 * what we're expecting.
333 */
Brianf3e8c322007-04-18 14:53:23 -0600334 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700335 return NULL;
336 }
337 return sh;
338 }
339 return NULL;
340}
341
342
Brianfa4d0362007-02-26 18:33:50 -0700343/**
Brian Paul530df582008-07-03 16:21:11 -0600344 * As above, but record an error if shader is not found.
345 */
346static struct gl_shader *
347_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
348{
349 if (!name) {
350 _mesa_error(ctx, GL_INVALID_VALUE, caller);
351 return NULL;
352 }
353 else {
354 struct gl_shader *sh = (struct gl_shader *)
355 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
356 if (!sh) {
357 _mesa_error(ctx, GL_INVALID_VALUE, caller);
358 return NULL;
359 }
360 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
361 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
362 return NULL;
363 }
364 return sh;
365 }
366}
367
368
Brian Paule01a03d2009-02-06 10:21:36 -0700369/**
370 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
371 */
372static GLbitfield
373get_shader_flags(void)
374{
375 GLbitfield flags = 0x0;
376 const char *env = _mesa_getenv("MESA_GLSL");
377
378 if (env) {
379 if (_mesa_strstr(env, "dump"))
380 flags |= GLSL_DUMP;
381 if (_mesa_strstr(env, "log"))
382 flags |= GLSL_LOG;
383 if (_mesa_strstr(env, "nopt"))
384 flags |= GLSL_NO_OPT;
385 else if (_mesa_strstr(env, "opt"))
386 flags |= GLSL_OPT;
387 if (_mesa_strstr(env, "uniform"))
388 flags |= GLSL_UNIFORMS;
389 }
390
391 return flags;
392}
393
Brian Paul530df582008-07-03 16:21:11 -0600394
395/**
Brianfa4d0362007-02-26 18:33:50 -0700396 * Initialize context's shader state.
397 */
Brianf2923612006-12-20 09:56:44 -0700398void
399_mesa_init_shader_state(GLcontext * ctx)
400{
Brianfa4d0362007-02-26 18:33:50 -0700401 /* Device drivers may override these to control what kind of instructions
402 * are generated by the GLSL compiler.
403 */
404 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700405 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700406 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700407 ctx->Shader.Flags = get_shader_flags();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600408
409 /* Default pragma settings */
410 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
411 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
412 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
413 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700414}
415
416
Brian5b01c5e2006-12-19 18:02:03 -0700417/**
Brian935f93f2007-03-24 16:20:02 -0600418 * Free the per-context shader-related state.
419 */
420void
421_mesa_free_shader_state(GLcontext *ctx)
422{
Brian3c008a02007-04-12 15:22:32 -0600423 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600424}
425
426
427/**
Brian5b01c5e2006-12-19 18:02:03 -0700428 * Copy string from <src> to <dst>, up to maxLength characters, returning
429 * length of <dst> in <length>.
430 * \param src the strings source
431 * \param maxLength max chars to copy
432 * \param length returns number of chars copied
433 * \param dst the string destination
434 */
435static void
436copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
437{
438 GLsizei len;
439 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
440 dst[len] = src[len];
441 if (maxLength > 0)
442 dst[len] = 0;
443 if (length)
444 *length = len;
445}
446
447
Brian Paul7acb7c12008-07-03 13:49:48 -0600448static GLboolean
449_mesa_is_program(GLcontext *ctx, GLuint name)
450{
451 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
452 return shProg ? GL_TRUE : GL_FALSE;
453}
454
455
456static GLboolean
457_mesa_is_shader(GLcontext *ctx, GLuint name)
458{
459 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
460 return shader ? GL_TRUE : GL_FALSE;
461}
462
463
Brian5b01c5e2006-12-19 18:02:03 -0700464/**
465 * Called via ctx->Driver.AttachShader()
466 */
Brian Paulfd59f192008-05-18 16:04:55 -0600467static void
Brian5b01c5e2006-12-19 18:02:03 -0700468_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
469{
Brian Paul530df582008-07-03 16:21:11 -0600470 struct gl_shader_program *shProg;
471 struct gl_shader *sh;
472 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700473
Brian Paul530df582008-07-03 16:21:11 -0600474 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
475 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700476 return;
Brian5b01c5e2006-12-19 18:02:03 -0700477
Brian Paul530df582008-07-03 16:21:11 -0600478 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600479 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600480 return;
481 }
482
Brian237b9852007-08-07 21:48:31 +0100483 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700484 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700485 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700486 /* The shader is already attched to this program. The
487 * GL_ARB_shader_objects spec says:
488 *
489 * "The error INVALID_OPERATION is generated by AttachObjectARB
490 * if <obj> is already attached to <containerObj>."
491 */
492 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700493 return;
Brian34ae99d2006-12-18 08:28:54 -0700494 }
495 }
Brian5b01c5e2006-12-19 18:02:03 -0700496
497 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700498 shProg->Shaders = (struct gl_shader **)
499 _mesa_realloc(shProg->Shaders,
500 n * sizeof(struct gl_shader *),
501 (n + 1) * sizeof(struct gl_shader *));
502 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700503 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
504 return;
505 }
506
507 /* append */
Brian3c008a02007-04-12 15:22:32 -0600508 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
509 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700510 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700511}
512
513
Brian Paulfd59f192008-05-18 16:04:55 -0600514static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600515_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
516 const GLchar *name)
517{
518 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600519 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600520
521 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600522 return -1;
523 }
524
525 if (!shProg->LinkStatus) {
526 _mesa_error(ctx, GL_INVALID_OPERATION,
527 "glGetAttribLocation(program not linked)");
528 return -1;
529 }
530
531 if (!name)
532 return -1;
533
Brian Paul27341a92008-09-16 16:28:36 -0600534 if (shProg->VertexProgram) {
535 const struct gl_program_parameter_list *attribs =
536 shProg->VertexProgram->Base.Attributes;
537 if (attribs) {
538 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
539 if (i >= 0) {
540 return attribs->Parameters[i].StateIndexes[0];
541 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600542 }
543 }
544 return -1;
545}
546
547
Brian Paulfd59f192008-05-18 16:04:55 -0600548static void
Brian5b01c5e2006-12-19 18:02:03 -0700549_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
550 const GLchar *name)
551{
Brian Paul530df582008-07-03 16:21:11 -0600552 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700553 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600554 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600555 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700556
Brian Paul530df582008-07-03 16:21:11 -0600557 shProg = _mesa_lookup_shader_program_err(ctx, program,
558 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700559 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700560 return;
561 }
562
Brian9e4bae92006-12-20 09:27:42 -0700563 if (!name)
564 return;
565
566 if (strncmp(name, "gl_", 3) == 0) {
567 _mesa_error(ctx, GL_INVALID_OPERATION,
568 "glBindAttribLocation(illegal name)");
569 return;
570 }
571
Brian Paul7acb7c12008-07-03 13:49:48 -0600572 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
573 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
574 return;
575 }
576
Brian Paul6bc87492008-07-25 08:34:54 -0600577 if (shProg->LinkStatus) {
578 /* get current index/location for the attribute */
579 oldIndex = _mesa_get_attrib_location(ctx, program, name);
580 }
581 else {
582 oldIndex = -1;
583 }
584
Brian3209c3e2007-01-09 17:49:24 -0700585 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600586 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700587 if (i < 0) {
588 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600589 return;
Brian3209c3e2007-01-09 17:49:24 -0700590 }
591
Brian Paul27341a92008-09-16 16:28:36 -0600592 /*
593 * Note that this attribute binding won't go into effect until
594 * glLinkProgram is called again.
595 */
Brian34ae99d2006-12-18 08:28:54 -0700596}
597
598
Brian Paulfd59f192008-05-18 16:04:55 -0600599static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700600_mesa_create_shader(GLcontext *ctx, GLenum type)
601{
Brian65a18442006-12-19 18:46:56 -0700602 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700603 GLuint name;
604
605 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
606
607 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700608 case GL_FRAGMENT_SHADER:
609 case GL_VERTEX_SHADER:
610 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700611 break;
612 default:
613 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
614 return 0;
615 }
616
Brian65a18442006-12-19 18:46:56 -0700617 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700618
619 return name;
620}
621
622
Brian Paulfd59f192008-05-18 16:04:55 -0600623static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700624_mesa_create_program(GLcontext *ctx)
625{
626 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700627 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700628
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800629 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700630 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700631
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800632 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700633
Brian3c008a02007-04-12 15:22:32 -0600634 assert(shProg->RefCount == 1);
635
Brian5b01c5e2006-12-19 18:02:03 -0700636 return name;
637}
638
639
Brian3c008a02007-04-12 15:22:32 -0600640/**
641 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
642 * DeleteProgramARB.
643 */
Brian Paulfd59f192008-05-18 16:04:55 -0600644static void
Brian5b01c5e2006-12-19 18:02:03 -0700645_mesa_delete_program2(GLcontext *ctx, GLuint name)
646{
Brian3c008a02007-04-12 15:22:32 -0600647 /*
648 * NOTE: deleting shaders/programs works a bit differently than
649 * texture objects (and buffer objects, etc). Shader/program
650 * handles/IDs exist in the hash table until the object is really
651 * deleted (refcount==0). With texture objects, the handle/ID is
652 * removed from the hash table in glDeleteTextures() while the tex
653 * object itself might linger until its refcount goes to zero.
654 */
Brian65a18442006-12-19 18:46:56 -0700655 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700656
Brian Paul530df582008-07-03 16:21:11 -0600657 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
658 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700659 return;
Brian5b01c5e2006-12-19 18:02:03 -0700660
Brian9e4bae92006-12-20 09:27:42 -0700661 shProg->DeletePending = GL_TRUE;
662
Brian3c008a02007-04-12 15:22:32 -0600663 /* effectively, decr shProg's refcount */
664 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700665}
666
667
Brian Paulfd59f192008-05-18 16:04:55 -0600668static void
Brian5b01c5e2006-12-19 18:02:03 -0700669_mesa_delete_shader(GLcontext *ctx, GLuint shader)
670{
Brian Paul530df582008-07-03 16:21:11 -0600671 struct gl_shader *sh;
672
673 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
674 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700675 return;
Brian5b01c5e2006-12-19 18:02:03 -0700676
Brian9e4bae92006-12-20 09:27:42 -0700677 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600678
679 /* effectively, decr sh's refcount */
680 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700681}
682
683
Brian Paulfd59f192008-05-18 16:04:55 -0600684static void
Brian5b01c5e2006-12-19 18:02:03 -0700685_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
686{
Brian Paul530df582008-07-03 16:21:11 -0600687 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100688 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700689 GLuint i, j;
690
Brian Paul530df582008-07-03 16:21:11 -0600691 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
692 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700693 return;
Brian5b01c5e2006-12-19 18:02:03 -0700694
Brian237b9852007-08-07 21:48:31 +0100695 n = shProg->NumShaders;
696
Brian5b01c5e2006-12-19 18:02:03 -0700697 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700698 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700699 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600700 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700701
Brian Paul530df582008-07-03 16:21:11 -0600702 /* release */
Brian3c008a02007-04-12 15:22:32 -0600703 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700704
Brian5b01c5e2006-12-19 18:02:03 -0700705 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700706 newList = (struct gl_shader **)
707 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700708 if (!newList) {
709 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
710 return;
711 }
712 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700713 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700714 }
715 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700716 newList[j++] = shProg->Shaders[i];
717 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700718
Brian65a18442006-12-19 18:46:56 -0700719 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600720 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600721
722#ifdef DEBUG
723 /* sanity check */
724 {
725 for (j = 0; j < shProg->NumShaders; j++) {
726 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
727 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
728 assert(shProg->Shaders[j]->RefCount > 0);
729 }
730 }
731#endif
732
Brian5b01c5e2006-12-19 18:02:03 -0700733 return;
734 }
735 }
736
737 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600738 {
739 GLenum err;
740 if (_mesa_is_shader(ctx, shader))
741 err = GL_INVALID_OPERATION;
742 else if (_mesa_is_program(ctx, shader))
743 err = GL_INVALID_OPERATION;
744 else
745 err = GL_INVALID_VALUE;
746 _mesa_error(ctx, err, "glDetachProgram(shader)");
747 return;
748 }
Brian5b01c5e2006-12-19 18:02:03 -0700749}
750
751
Brian Paulffbc66b2008-07-21 13:58:50 -0600752static GLint
753sizeof_glsl_type(GLenum type)
754{
755 switch (type) {
756 case GL_FLOAT:
757 case GL_INT:
758 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600759 case GL_SAMPLER_1D:
760 case GL_SAMPLER_2D:
761 case GL_SAMPLER_3D:
762 case GL_SAMPLER_CUBE:
763 case GL_SAMPLER_1D_SHADOW:
764 case GL_SAMPLER_2D_SHADOW:
765 case GL_SAMPLER_2D_RECT_ARB:
766 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
767 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
768 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
769 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600770 return 1;
771 case GL_FLOAT_VEC2:
772 case GL_INT_VEC2:
773 case GL_BOOL_VEC2:
774 return 2;
775 case GL_FLOAT_VEC3:
776 case GL_INT_VEC3:
777 case GL_BOOL_VEC3:
778 return 3;
779 case GL_FLOAT_VEC4:
780 case GL_INT_VEC4:
781 case GL_BOOL_VEC4:
782 return 4;
783 case GL_FLOAT_MAT2:
784 case GL_FLOAT_MAT2x3:
785 case GL_FLOAT_MAT2x4:
786 return 8; /* two float[4] vectors */
787 case GL_FLOAT_MAT3:
788 case GL_FLOAT_MAT3x2:
789 case GL_FLOAT_MAT3x4:
790 return 12; /* three float[4] vectors */
791 case GL_FLOAT_MAT4:
792 case GL_FLOAT_MAT4x2:
793 case GL_FLOAT_MAT4x3:
794 return 16; /* four float[4] vectors */
795 default:
796 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
797 return 1;
798 }
799}
800
801
Brian Pauleda291e2008-08-06 16:26:47 -0600802static GLboolean
803is_boolean_type(GLenum type)
804{
805 switch (type) {
806 case GL_BOOL:
807 case GL_BOOL_VEC2:
808 case GL_BOOL_VEC3:
809 case GL_BOOL_VEC4:
810 return GL_TRUE;
811 default:
812 return GL_FALSE;
813 }
814}
815
816
817static GLboolean
818is_integer_type(GLenum type)
819{
820 switch (type) {
821 case GL_INT:
822 case GL_INT_VEC2:
823 case GL_INT_VEC3:
824 case GL_INT_VEC4:
825 return GL_TRUE;
826 default:
827 return GL_FALSE;
828 }
829}
830
831
Brian Paulc4ffbf02009-02-18 17:46:00 -0700832static GLboolean
833is_sampler_type(GLenum type)
834{
835 switch (type) {
836 case GL_SAMPLER_1D:
837 case GL_SAMPLER_2D:
838 case GL_SAMPLER_3D:
839 case GL_SAMPLER_CUBE:
840 case GL_SAMPLER_1D_SHADOW:
841 case GL_SAMPLER_2D_SHADOW:
842 case GL_SAMPLER_2D_RECT_ARB:
843 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
844 case GL_SAMPLER_1D_ARRAY_EXT:
845 case GL_SAMPLER_2D_ARRAY_EXT:
846 return GL_TRUE;
847 default:
848 return GL_FALSE;
849 }
850}
851
852
Brian Paulfd59f192008-05-18 16:04:55 -0600853static void
Brian5b01c5e2006-12-19 18:02:03 -0700854_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
855 GLsizei maxLength, GLsizei *length, GLint *size,
856 GLenum *type, GLchar *nameOut)
857{
Brian Paul27341a92008-09-16 16:28:36 -0600858 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600859 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700860
Brian Paul530df582008-07-03 16:21:11 -0600861 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
862 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700863 return;
Brian5b01c5e2006-12-19 18:02:03 -0700864
Brian Paul27341a92008-09-16 16:28:36 -0600865 if (shProg->VertexProgram)
866 attribs = shProg->VertexProgram->Base.Attributes;
867
868 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600869 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700870 return;
871 }
872
Brian Paul27341a92008-09-16 16:28:36 -0600873 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
874
Brian5b01c5e2006-12-19 18:02:03 -0700875 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600876 *size = attribs->Parameters[index].Size
877 / sizeof_glsl_type(attribs->Parameters[index].DataType);
878
Brian Paulade50832008-05-14 16:09:46 -0600879 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600880 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700881}
882
883
Brian Pauleda291e2008-08-06 16:26:47 -0600884static struct gl_program_parameter *
885get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
886{
887 const struct gl_program *prog;
888 GLint progPos;
889
890 progPos = shProg->Uniforms->Uniforms[index].VertPos;
891 if (progPos >= 0) {
892 prog = &shProg->VertexProgram->Base;
893 }
894 else {
895 progPos = shProg->Uniforms->Uniforms[index].FragPos;
896 if (progPos >= 0) {
897 prog = &shProg->FragmentProgram->Base;
898 }
899 }
900
901 if (!prog || progPos < 0)
902 return NULL; /* should never happen */
903
904 return &prog->Parameters->Parameters[progPos];
905}
906
907
Brian5b01c5e2006-12-19 18:02:03 -0700908/**
909 * Called via ctx->Driver.GetActiveUniform().
910 */
Brian Paulfd59f192008-05-18 16:04:55 -0600911static void
Brian5b01c5e2006-12-19 18:02:03 -0700912_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
913 GLsizei maxLength, GLsizei *length, GLint *size,
914 GLenum *type, GLchar *nameOut)
915{
Brian Paul530df582008-07-03 16:21:11 -0600916 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600917 const struct gl_program *prog;
Brian Paul369d1852009-02-11 08:16:14 -0700918 const struct gl_program_parameter *param;
Brian Paulade50832008-05-14 16:09:46 -0600919 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700920
Brian Paul530df582008-07-03 16:21:11 -0600921 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
922 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700923 return;
Brian5b01c5e2006-12-19 18:02:03 -0700924
Brian Paulade50832008-05-14 16:09:46 -0600925 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700926 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
927 return;
928 }
929
Brian Paulade50832008-05-14 16:09:46 -0600930 progPos = shProg->Uniforms->Uniforms[index].VertPos;
931 if (progPos >= 0) {
932 prog = &shProg->VertexProgram->Base;
933 }
934 else {
935 progPos = shProg->Uniforms->Uniforms[index].FragPos;
936 if (progPos >= 0) {
937 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600938 }
939 }
940
Brian Paulade50832008-05-14 16:09:46 -0600941 if (!prog || progPos < 0)
942 return; /* should never happen */
943
Brian Paul369d1852009-02-11 08:16:14 -0700944 ASSERT(progPos < prog->Parameters->NumParameters);
945 param = &prog->Parameters->Parameters[progPos];
946
947 if (nameOut) {
948 copy_string(nameOut, maxLength, length, param->Name);
949 }
950
951 if (size) {
952 GLint typeSize = sizeof_glsl_type(param->DataType);
953 if (param->Size > typeSize) {
954 /* This is an array.
955 * Array elements are placed on vector[4] boundaries so they're
956 * a multiple of four floats. We round typeSize up to next multiple
957 * of four to get the right size below.
958 */
959 typeSize = (typeSize + 3) & ~3;
960 }
961 /* Note that the returned size is in units of the <type>, not bytes */
962 *size = param->Size / typeSize;
963 }
964
965 if (type) {
966 *type = param->DataType;
967 }
Brian5b01c5e2006-12-19 18:02:03 -0700968}
969
970
971/**
972 * Called via ctx->Driver.GetAttachedShaders().
973 */
Brian Paulfd59f192008-05-18 16:04:55 -0600974static void
Brian5b01c5e2006-12-19 18:02:03 -0700975_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
976 GLsizei *count, GLuint *obj)
977{
Brian Paul530df582008-07-03 16:21:11 -0600978 struct gl_shader_program *shProg =
979 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700980 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600981 GLuint i;
982 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700983 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700984 }
985 if (count)
986 *count = i;
987 }
Brian5b01c5e2006-12-19 18:02:03 -0700988}
989
990
Brian Paulfd59f192008-05-18 16:04:55 -0600991static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700992_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700993{
Ian Romanick905d8e02008-09-29 12:27:00 -0700994 GLint handle = 0;
995
996 if (pname == GL_PROGRAM_OBJECT_ARB) {
997 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
998 } else {
Brian34ae99d2006-12-18 08:28:54 -0700999 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
1000 }
Ian Romanick905d8e02008-09-29 12:27:00 -07001001
1002 return handle;
Brian34ae99d2006-12-18 08:28:54 -07001003}
1004
1005
Brian Paulfd59f192008-05-18 16:04:55 -06001006static void
Brian5b01c5e2006-12-19 18:02:03 -07001007_mesa_get_programiv(GLcontext *ctx, GLuint program,
1008 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -07001009{
Brian Paul27341a92008-09-16 16:28:36 -06001010 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -07001011 struct gl_shader_program *shProg
1012 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -07001013
Brian65a18442006-12-19 18:46:56 -07001014 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001015 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -07001016 return;
1017 }
1018
Brian Paul27341a92008-09-16 16:28:36 -06001019 if (shProg->VertexProgram)
1020 attribs = shProg->VertexProgram->Base.Attributes;
1021 else
1022 attribs = NULL;
1023
Brian5b01c5e2006-12-19 18:02:03 -07001024 switch (pname) {
1025 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001026 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -07001027 break;
1028 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -07001029 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -07001030 break;
Brian5b01c5e2006-12-19 18:02:03 -07001031 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001032 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -07001033 break;
1034 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001035 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001036 break;
1037 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -07001038 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -07001039 break;
1040 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -06001041 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001042 break;
1043 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -06001044 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -07001045 break;
1046 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -06001047 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001048 break;
1049 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -06001050 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -06001051 if (*params > 0)
1052 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -07001053 break;
Brian Paulbda6ad22008-08-06 12:45:14 -06001054 case GL_PROGRAM_BINARY_LENGTH_OES:
1055 *params = 0;
1056 break;
Brian34ae99d2006-12-18 08:28:54 -07001057 default:
Brian5b01c5e2006-12-19 18:02:03 -07001058 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
1059 return;
Brian34ae99d2006-12-18 08:28:54 -07001060 }
Brian5b01c5e2006-12-19 18:02:03 -07001061}
Brian34ae99d2006-12-18 08:28:54 -07001062
Brian34ae99d2006-12-18 08:28:54 -07001063
Brian Paulfd59f192008-05-18 16:04:55 -06001064static void
Brian5b01c5e2006-12-19 18:02:03 -07001065_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
1066{
Brian Paul530df582008-07-03 16:21:11 -06001067 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -07001068
1069 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -07001070 return;
1071 }
Brian65a18442006-12-19 18:46:56 -07001072
Brian5b01c5e2006-12-19 18:02:03 -07001073 switch (pname) {
1074 case GL_SHADER_TYPE:
1075 *params = shader->Type;
1076 break;
1077 case GL_DELETE_STATUS:
1078 *params = shader->DeletePending;
1079 break;
1080 case GL_COMPILE_STATUS:
1081 *params = shader->CompileStatus;
1082 break;
1083 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001084 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001085 break;
1086 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001087 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001088 break;
1089 default:
1090 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1091 return;
1092 }
1093}
1094
1095
Brian Paulfd59f192008-05-18 16:04:55 -06001096static void
Brian5b01c5e2006-12-19 18:02:03 -07001097_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1098 GLsizei *length, GLchar *infoLog)
1099{
Brian65a18442006-12-19 18:46:56 -07001100 struct gl_shader_program *shProg
1101 = _mesa_lookup_shader_program(ctx, program);
1102 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001103 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1104 return;
1105 }
Brian65a18442006-12-19 18:46:56 -07001106 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001107}
1108
1109
Brian Paulfd59f192008-05-18 16:04:55 -06001110static void
Brian5b01c5e2006-12-19 18:02:03 -07001111_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1112 GLsizei *length, GLchar *infoLog)
1113{
Brian65a18442006-12-19 18:46:56 -07001114 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1115 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001116 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1117 return;
1118 }
Brian65a18442006-12-19 18:46:56 -07001119 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001120}
1121
1122
1123/**
1124 * Called via ctx->Driver.GetShaderSource().
1125 */
Brian Paulfd59f192008-05-18 16:04:55 -06001126static void
Brian5b01c5e2006-12-19 18:02:03 -07001127_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1128 GLsizei *length, GLchar *sourceOut)
1129{
Brian Paul530df582008-07-03 16:21:11 -06001130 struct gl_shader *sh;
1131 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001132 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001133 return;
1134 }
Brian65a18442006-12-19 18:46:56 -07001135 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001136}
1137
1138
Brian Paul5b982362008-08-06 13:07:09 -06001139static void
1140get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1141{
1142 switch (type) {
1143 case GL_FLOAT_MAT2:
1144 *rows = *cols = 2;
1145 break;
1146 case GL_FLOAT_MAT2x3:
1147 *rows = 3;
1148 *cols = 2;
1149 break;
1150 case GL_FLOAT_MAT2x4:
1151 *rows = 4;
1152 *cols = 2;
1153 break;
1154 case GL_FLOAT_MAT3:
1155 *rows = 3;
1156 *cols = 3;
1157 break;
1158 case GL_FLOAT_MAT3x2:
1159 *rows = 2;
1160 *cols = 3;
1161 break;
1162 case GL_FLOAT_MAT3x4:
1163 *rows = 4;
1164 *cols = 3;
1165 break;
1166 case GL_FLOAT_MAT4:
1167 *rows = 4;
1168 *cols = 4;
1169 break;
1170 case GL_FLOAT_MAT4x2:
1171 *rows = 2;
1172 *cols = 4;
1173 break;
1174 case GL_FLOAT_MAT4x3:
1175 *rows = 3;
1176 *cols = 4;
1177 break;
1178 default:
1179 *rows = *cols = 0;
1180 }
1181}
1182
1183
1184/**
1185 * Determine the number of rows and columns occupied by a uniform
Brian Paulea9568d2008-09-16 08:55:54 -06001186 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
1187 * the number of rows = 1 and cols = number of elements in the vector.
Brian Paul5b982362008-08-06 13:07:09 -06001188 */
1189static void
1190get_uniform_rows_cols(const struct gl_program_parameter *p,
1191 GLint *rows, GLint *cols)
1192{
1193 get_matrix_dims(p->DataType, rows, cols);
1194 if (*rows == 0 && *cols == 0) {
1195 /* not a matrix type, probably a float or vector */
Brian Paulea9568d2008-09-16 08:55:54 -06001196 if (p->Size <= 4) {
1197 *rows = 1;
1198 *cols = p->Size;
1199 }
1200 else {
1201 *rows = p->Size / 4 + 1;
1202 if (p->Size % 4 == 0)
1203 *cols = 4;
1204 else
1205 *cols = p->Size % 4;
1206 }
Brian Paul5b982362008-08-06 13:07:09 -06001207 }
1208}
1209
1210
Brian5b01c5e2006-12-19 18:02:03 -07001211/**
Brian Paul4ef7a932009-02-11 09:03:16 -07001212 * Helper for get_uniform[fi]v() functions.
1213 * Given a shader program name and uniform location, return a pointer
1214 * to the shader program and return the program parameter position.
Brian5b01c5e2006-12-19 18:02:03 -07001215 */
Brian Paul4ef7a932009-02-11 09:03:16 -07001216static void
1217lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
1218 struct gl_program **progOut, GLint *paramPosOut)
Brian5b01c5e2006-12-19 18:02:03 -07001219{
Brian65a18442006-12-19 18:46:56 -07001220 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001221 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian Paul4ef7a932009-02-11 09:03:16 -07001222 struct gl_program *prog = NULL;
1223 GLint progPos = -1;
Brian Paulade50832008-05-14 16:09:46 -06001224
Brian Paul4ef7a932009-02-11 09:03:16 -07001225 /* if shProg is NULL, we'll have already recorded an error */
1226
1227 if (shProg) {
1228 if (!shProg->Uniforms ||
1229 location < 0 ||
1230 location >= (GLint) shProg->Uniforms->NumUniforms) {
1231 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1232 }
1233 else {
1234 /* OK, find the gl_program and program parameter location */
Brian Paulade50832008-05-14 16:09:46 -06001235 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1236 if (progPos >= 0) {
1237 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001238 }
Brian Paulade50832008-05-14 16:09:46 -06001239 else {
1240 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1241 if (progPos >= 0) {
1242 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001243 }
Brian Paulade50832008-05-14 16:09:46 -06001244 }
Brian5b01c5e2006-12-19 18:02:03 -07001245 }
1246 }
Brian Paul4ef7a932009-02-11 09:03:16 -07001247
1248 *progOut = prog;
1249 *paramPosOut = progPos;
Brian Paul2be54a82008-07-08 16:17:04 -06001250}
1251
1252
1253/**
1254 * Called via ctx->Driver.GetUniformfv().
1255 */
1256static void
1257_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1258 GLfloat *params)
1259{
Brian Paul4ef7a932009-02-11 09:03:16 -07001260 struct gl_program *prog;
1261 GLint paramPos;
1262
1263 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1264
1265 if (prog) {
1266 const struct gl_program_parameter *p =
1267 &prog->Parameters->Parameters[paramPos];
1268 GLint rows, cols, i, j, k;
1269
1270 get_uniform_rows_cols(p, &rows, &cols);
1271
1272 k = 0;
1273 for (i = 0; i < rows; i++) {
1274 for (j = 0; j < cols; j++ ) {
1275 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
1276 }
1277 }
1278 }
Brian Paul2be54a82008-07-08 16:17:04 -06001279}
1280
1281
1282/**
1283 * Called via ctx->Driver.GetUniformiv().
Brian Paul4ef7a932009-02-11 09:03:16 -07001284 * \sa _mesa_get_uniformfv, only difference is a cast.
Brian Paul2be54a82008-07-08 16:17:04 -06001285 */
1286static void
1287_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1288 GLint *params)
1289{
Brian Paul4ef7a932009-02-11 09:03:16 -07001290 struct gl_program *prog;
1291 GLint paramPos;
1292
1293 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1294
1295 if (prog) {
1296 const struct gl_program_parameter *p =
1297 &prog->Parameters->Parameters[paramPos];
1298 GLint rows, cols, i, j, k;
1299
1300 get_uniform_rows_cols(p, &rows, &cols);
1301
1302 k = 0;
1303 for (i = 0; i < rows; i++) {
1304 for (j = 0; j < cols; j++ ) {
1305 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
1306 }
1307 }
Brian Paul2be54a82008-07-08 16:17:04 -06001308 }
Brian5b01c5e2006-12-19 18:02:03 -07001309}
1310
1311
1312/**
Brian Pauleda291e2008-08-06 16:26:47 -06001313 * The value returned by GetUniformLocation actually encodes two things:
1314 * 1. the index into the prog->Uniforms[] array for the uniform
1315 * 2. an offset in the prog->ParameterValues[] array for specifying array
1316 * elements or structure fields.
1317 * This function merges those two values.
1318 */
1319static void
1320merge_location_offset(GLint *location, GLint offset)
1321{
1322 *location = *location | (offset << 16);
1323}
1324
1325
1326/**
1327 * Seperate the uniform location and parameter offset. See above.
1328 */
1329static void
1330split_location_offset(GLint *location, GLint *offset)
1331{
1332 *offset = (*location >> 16);
1333 *location = *location & 0xffff;
1334}
1335
1336
1337/**
Brian5b01c5e2006-12-19 18:02:03 -07001338 * Called via ctx->Driver.GetUniformLocation().
Brian Pauleda291e2008-08-06 16:26:47 -06001339 *
1340 * The return value will encode two values, the uniform location and an
1341 * offset (used for arrays, structs).
Brian5b01c5e2006-12-19 18:02:03 -07001342 */
Brian Paulfd59f192008-05-18 16:04:55 -06001343static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001344_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1345{
Brian Pauleda291e2008-08-06 16:26:47 -06001346 GLint offset = 0, location = -1;
1347
Brian Paul530df582008-07-03 16:21:11 -06001348 struct gl_shader_program *shProg =
1349 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1350
Brian Paulade50832008-05-14 16:09:46 -06001351 if (!shProg)
1352 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001353
Brian Paule06565b2008-07-04 09:58:55 -06001354 if (shProg->LinkStatus == GL_FALSE) {
1355 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1356 return -1;
1357 }
1358
Brian Paul530df582008-07-03 16:21:11 -06001359 /* XXX we should return -1 if the uniform was declared, but not
1360 * actually used.
1361 */
1362
Brian Pauleda291e2008-08-06 16:26:47 -06001363 /* XXX we need to be able to parse uniform names for structs and arrays
1364 * such as:
1365 * mymatrix[1]
1366 * mystruct.field1
1367 */
1368
1369 {
1370 /* handle 1-dimension arrays here... */
1371 char *c = strchr(name, '[');
1372 if (c) {
1373 /* truncate name at [ */
1374 const GLint len = c - name;
1375 GLchar *newName = _mesa_malloc(len + 1);
1376 if (!newName)
1377 return -1; /* out of mem */
1378 _mesa_memcpy(newName, name, len);
1379 newName[len] = 0;
1380
1381 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1382 if (location >= 0) {
1383 const GLint element = _mesa_atoi(c + 1);
1384 if (element > 0) {
1385 /* get type of the uniform array element */
1386 struct gl_program_parameter *p;
1387 p = get_uniform_parameter(shProg, location);
1388 if (p) {
1389 GLint rows, cols;
1390 get_matrix_dims(p->DataType, &rows, &cols);
1391 if (rows < 1)
1392 rows = 1;
1393 offset = element * rows;
1394 }
1395 }
1396 }
1397
1398 _mesa_free(newName);
1399 }
1400 }
1401
1402 if (location < 0) {
1403 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1404 }
1405
1406 if (location >= 0) {
1407 merge_location_offset(&location, offset);
1408 }
1409
1410 return location;
Brian5b01c5e2006-12-19 18:02:03 -07001411}
1412
1413
Brian34ae99d2006-12-18 08:28:54 -07001414
Brian5b01c5e2006-12-19 18:02:03 -07001415/**
1416 * Called via ctx->Driver.ShaderSource()
1417 */
Brian Paulfd59f192008-05-18 16:04:55 -06001418static void
Brian5b01c5e2006-12-19 18:02:03 -07001419_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001420{
Brian Paul530df582008-07-03 16:21:11 -06001421 struct gl_shader *sh;
1422
1423 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1424 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001425 return;
Brian34ae99d2006-12-18 08:28:54 -07001426
Brian34ae99d2006-12-18 08:28:54 -07001427 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001428 if (sh->Source) {
1429 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001430 }
Brian65a18442006-12-19 18:46:56 -07001431 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001432 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001433}
1434
1435
Brian5b01c5e2006-12-19 18:02:03 -07001436/**
1437 * Called via ctx->Driver.CompileShader()
1438 */
Brian Paulfd59f192008-05-18 16:04:55 -06001439static void
Brian5b01c5e2006-12-19 18:02:03 -07001440_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001441{
Brian Paul530df582008-07-03 16:21:11 -06001442 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001443
Brian Paul530df582008-07-03 16:21:11 -06001444 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1445 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001446 return;
Brian34ae99d2006-12-18 08:28:54 -07001447
Brian Paul65fc2ca2009-03-19 10:25:24 -06001448 /* set default pragma state for shader */
1449 sh->Pragmas = ctx->Shader.DefaultPragmas;
1450
Brian Paulcb136e02009-01-22 10:34:15 -07001451 /* this call will set the sh->CompileStatus field to indicate if
1452 * compilation was successful.
1453 */
1454 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001455}
1456
1457
Brian5b01c5e2006-12-19 18:02:03 -07001458/**
1459 * Called via ctx->Driver.LinkProgram()
1460 */
Brian Paulfd59f192008-05-18 16:04:55 -06001461static void
Brian5b01c5e2006-12-19 18:02:03 -07001462_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001463{
Brian65a18442006-12-19 18:46:56 -07001464 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001465
Brian Paul530df582008-07-03 16:21:11 -06001466 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1467 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001468 return;
Brian34ae99d2006-12-18 08:28:54 -07001469
Briandf43fb62008-05-06 23:08:51 -06001470 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1471
Brianc1771912007-02-16 09:56:19 -07001472 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001473}
1474
1475
1476/**
Brian5b01c5e2006-12-19 18:02:03 -07001477 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001478 */
Brian5b01c5e2006-12-19 18:02:03 -07001479void
1480_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001481{
Brian3c008a02007-04-12 15:22:32 -06001482 struct gl_shader_program *shProg;
1483
Brian00d63aa2007-02-03 11:35:02 -07001484 if (ctx->Shader.CurrentProgram &&
1485 ctx->Shader.CurrentProgram->Name == program) {
1486 /* no-op */
1487 return;
1488 }
1489
Brian Paul027ed1b2009-04-24 09:43:44 -06001490 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
Brian00d63aa2007-02-03 11:35:02 -07001491
Brian5b01c5e2006-12-19 18:02:03 -07001492 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001493 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001494 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001495 return;
1496 }
1497 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001498 _mesa_error(ctx, GL_INVALID_OPERATION,
1499 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001500 return;
1501 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001502
1503 /* debug code */
1504 if (0) {
1505 GLuint i;
1506 _mesa_printf("Use Shader %u\n", shProg->Name);
1507 for (i = 0; i < shProg->NumShaders; i++) {
1508 _mesa_printf(" shader %u, type 0x%x\n",
1509 shProg->Shaders[i]->Name,
1510 shProg->Shaders[i]->Type);
1511 }
Brian Paulccaa6462009-05-08 12:17:11 -06001512 if (shProg->VertexProgram)
1513 printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
1514 if (shProg->FragmentProgram)
1515 printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
Brian Paul4eda17d2009-03-13 09:11:42 -06001516 }
Brian5b01c5e2006-12-19 18:02:03 -07001517 }
1518 else {
Brian3c008a02007-04-12 15:22:32 -06001519 shProg = NULL;
1520 }
1521
1522 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001523}
Brian34ae99d2006-12-18 08:28:54 -07001524
Brian5b01c5e2006-12-19 18:02:03 -07001525
Brian Paulade50832008-05-14 16:09:46 -06001526
1527/**
Brian Paul517401a2008-11-06 15:04:11 -07001528 * Update the vertex/fragment program's TexturesUsed array.
1529 *
1530 * This needs to be called after glUniform(set sampler var) is called.
1531 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1532 * particular texture unit. We know the sampler's texture target
1533 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1534 * set by glUniform() calls.
1535 *
1536 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1537 * information to update the prog->TexturesUsed[] values.
1538 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1539 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1540 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001541 */
Brian Paul517401a2008-11-06 15:04:11 -07001542void
1543_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001544{
1545 GLuint s;
1546
1547 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1548
1549 for (s = 0; s < MAX_SAMPLERS; s++) {
1550 if (prog->SamplersUsed & (1 << s)) {
1551 GLuint u = prog->SamplerUnits[s];
1552 GLuint t = prog->SamplerTargets[s];
1553 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1554 prog->TexturesUsed[u] |= (1 << t);
1555 }
1556 }
1557}
1558
1559
1560/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001561 * Check if the type given by userType is allowed to set a uniform of the
1562 * target type. Generally, equivalence is required, but setting Boolean
1563 * uniforms can be done with glUniformiv or glUniformfv.
1564 */
1565static GLboolean
1566compatible_types(GLenum userType, GLenum targetType)
1567{
1568 if (userType == targetType)
1569 return GL_TRUE;
1570
1571 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1572 return GL_TRUE;
1573
1574 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1575 userType == GL_INT_VEC2))
1576 return GL_TRUE;
1577
1578 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1579 userType == GL_INT_VEC3))
1580 return GL_TRUE;
1581
1582 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1583 userType == GL_INT_VEC4))
1584 return GL_TRUE;
1585
Brianb36749d2008-07-21 20:42:05 -06001586 if (is_sampler_type(targetType) && userType == GL_INT)
1587 return GL_TRUE;
1588
Brian Paulffbc66b2008-07-21 13:58:50 -06001589 return GL_FALSE;
1590}
1591
1592
1593/**
Brian Paulade50832008-05-14 16:09:46 -06001594 * Set the value of a program's uniform variable.
1595 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001596 * \param index the index of the program parameter for the uniform
1597 * \param offset additional parameter slot offset (for arrays)
Brian Paulc4ffbf02009-02-18 17:46:00 -07001598 * \param type the incoming datatype of 'values'
Brian Paulade50832008-05-14 16:09:46 -06001599 * \param count the number of uniforms to set
Brian Paulc4ffbf02009-02-18 17:46:00 -07001600 * \param elems number of elements per uniform (1, 2, 3 or 4)
1601 * \param values the new values, of datatype 'type'
Brian Paulade50832008-05-14 16:09:46 -06001602 */
1603static void
Brian Pauleda291e2008-08-06 16:26:47 -06001604set_program_uniform(GLcontext *ctx, struct gl_program *program,
1605 GLint index, GLint offset,
1606 GLenum type, GLsizei count, GLint elems,
1607 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001608{
Brian Paul949e7382008-11-05 09:17:55 -07001609 struct gl_program_parameter *param =
1610 &program->Parameters->Parameters[index];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001611 const GLboolean isUniformBool = is_boolean_type(param->DataType);
1612 const GLboolean areIntValues = is_integer_type(type);
Brian Paul949e7382008-11-05 09:17:55 -07001613
Brian Pauleda291e2008-08-06 16:26:47 -06001614 assert(offset >= 0);
Brian Paulc4ffbf02009-02-18 17:46:00 -07001615 assert(elems >= 1);
1616 assert(elems <= 4);
Brian Pauleda291e2008-08-06 16:26:47 -06001617
Brian Paul949e7382008-11-05 09:17:55 -07001618 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001619 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1620 return;
1621 }
1622
Michal Krolc5c71302008-08-07 16:23:15 +02001623 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001624 /* out of bounds! */
1625 return;
1626 }
1627
Brian Paul949e7382008-11-05 09:17:55 -07001628 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001629 /* This controls which texture unit which is used by a sampler */
1630 GLuint texUnit, sampler;
Brian Paul2b4f0212009-02-11 09:12:34 -07001631 GLint i;
Brian Paulade50832008-05-14 16:09:46 -06001632
1633 /* data type for setting samplers must be int */
Brian Paul2b4f0212009-02-11 09:12:34 -07001634 if (type != GL_INT) {
Brian Paulade50832008-05-14 16:09:46 -06001635 _mesa_error(ctx, GL_INVALID_OPERATION,
1636 "glUniform(only glUniform1i can be used "
1637 "to set sampler uniforms)");
1638 return;
1639 }
1640
Brian Paul2b4f0212009-02-11 09:12:34 -07001641 /* XXX arrays of samplers haven't been tested much, but it's not a
1642 * common thing...
1643 */
1644 for (i = 0; i < count; i++) {
1645 sampler = (GLuint) program->Parameters->ParameterValues[index + i][0];
1646 texUnit = ((GLuint *) values)[i];
Brian Paulade50832008-05-14 16:09:46 -06001647
Brian Paul2b4f0212009-02-11 09:12:34 -07001648 /* check that the sampler (tex unit index) is legal */
1649 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1650 _mesa_error(ctx, GL_INVALID_VALUE,
1651 "glUniform1(invalid sampler/tex unit index)");
1652 return;
1653 }
1654
1655 /* This maps a sampler to a texture unit: */
1656 if (sampler < MAX_SAMPLERS) {
1657 program->SamplerUnits[sampler] = texUnit;
1658 }
Brian Paulade50832008-05-14 16:09:46 -06001659 }
1660
Brian Paul517401a2008-11-06 15:04:11 -07001661 _mesa_update_shader_textures_used(program);
Brian Paulade50832008-05-14 16:09:46 -06001662
1663 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1664 }
1665 else {
1666 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001667 GLsizei k, i;
Brian Paul2c1ea072009-02-11 08:46:21 -07001668 const GLint slots = (param->Size + 3) / 4;
1669 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paulade50832008-05-14 16:09:46 -06001670
Brian Paul2c1ea072009-02-11 08:46:21 -07001671 if (param->Size > typeSize) {
1672 /* an array */
1673 /* we'll ignore extra data below */
1674 }
1675 else {
1676 /* non-array: count must be one */
1677 if (count != 1) {
1678 _mesa_error(ctx, GL_INVALID_OPERATION,
1679 "glUniform(uniform is not an array)");
1680 return;
1681 }
Brian Paulade50832008-05-14 16:09:46 -06001682 }
1683
Brian Paulc4ffbf02009-02-18 17:46:00 -07001684 /* loop over number of array elements */
Brian Paulade50832008-05-14 16:09:46 -06001685 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001686 GLfloat *uniformVal;
1687
Brian Paulb9d8f712009-02-18 17:40:44 -07001688 if (offset + k >= slots) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001689 /* Extra array data is ignored */
1690 break;
1691 }
1692
Brian Paulc4ffbf02009-02-18 17:46:00 -07001693 /* uniformVal (the destination) is always float[4] */
Brian Paul2c1ea072009-02-11 08:46:21 -07001694 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001695
1696 if (areIntValues) {
1697 /* convert user's ints to floats */
Brian Paulade50832008-05-14 16:09:46 -06001698 const GLint *iValues = ((const GLint *) values) + k * elems;
1699 for (i = 0; i < elems; i++) {
1700 uniformVal[i] = (GLfloat) iValues[i];
1701 }
1702 }
1703 else {
1704 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1705 for (i = 0; i < elems; i++) {
1706 uniformVal[i] = fValues[i];
1707 }
1708 }
Brian Pauleda291e2008-08-06 16:26:47 -06001709
1710 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paulc4ffbf02009-02-18 17:46:00 -07001711 if (isUniformBool) {
Brian Pauleda291e2008-08-06 16:26:47 -06001712 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001713 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001714 }
1715 }
Brian Paulade50832008-05-14 16:09:46 -06001716 }
1717 }
1718}
1719
1720
Brian5b01c5e2006-12-19 18:02:03 -07001721/**
1722 * Called via ctx->Driver.Uniform().
1723 */
Brian Paulfd59f192008-05-18 16:04:55 -06001724static void
Brian5b01c5e2006-12-19 18:02:03 -07001725_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1726 const GLvoid *values, GLenum type)
1727{
Brian3a8e2772006-12-20 17:19:16 -07001728 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001729 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001730 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001731 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001732
1733 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001734 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001735 return;
1736 }
1737
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001738 if (location == -1)
1739 return; /* The standard specifies this as a no-op */
1740
Brian Paul234f03e2009-02-11 09:05:08 -07001741 if (location < -1) {
1742 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
1743 return;
1744 }
1745
Brian Pauleda291e2008-08-06 16:26:47 -06001746 split_location_offset(&location, &offset);
1747
Brian Paulade50832008-05-14 16:09:46 -06001748 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1749 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001750 return;
1751 }
1752
Brian52363952007-03-13 16:50:24 -06001753 if (count < 0) {
1754 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1755 return;
1756 }
1757
Brian98650bd2007-03-13 16:32:48 -06001758 switch (type) {
1759 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001760 basicType = GL_FLOAT;
1761 elems = 1;
1762 break;
Brian98650bd2007-03-13 16:32:48 -06001763 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001764 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001765 elems = 1;
1766 break;
1767 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001768 basicType = GL_FLOAT;
1769 elems = 2;
1770 break;
Brian98650bd2007-03-13 16:32:48 -06001771 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001772 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001773 elems = 2;
1774 break;
1775 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001776 basicType = GL_FLOAT;
1777 elems = 3;
1778 break;
Brian98650bd2007-03-13 16:32:48 -06001779 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001780 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001781 elems = 3;
1782 break;
1783 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001784 basicType = GL_FLOAT;
1785 elems = 4;
1786 break;
Brian98650bd2007-03-13 16:32:48 -06001787 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001788 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001789 elems = 4;
1790 break;
1791 default:
1792 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1793 return;
Brian89dc4852007-01-04 14:35:44 -07001794 }
Brian98650bd2007-03-13 16:32:48 -06001795
Brian Paul027ed1b2009-04-24 09:43:44 -06001796 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Brian98650bd2007-03-13 16:32:48 -06001797
Brian Paul2d76a0d2008-11-10 12:33:17 -07001798 uniform = &shProg->Uniforms->Uniforms[location];
1799
Brian Paule01a03d2009-02-06 10:21:36 -07001800 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1801 GLint i;
1802 _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
1803 shProg->Name, uniform->Name, location);
1804 if (basicType == GL_INT) {
1805 const GLint *v = (const GLint *) values;
1806 for (i = 0; i < count * elems; i++) {
1807 _mesa_printf("%d ", v[i]);
1808 }
1809 }
1810 else {
1811 const GLfloat *v = (const GLfloat *) values;
1812 for (i = 0; i < count * elems; i++) {
1813 _mesa_printf("%g ", v[i]);
1814 }
1815 }
1816 _mesa_printf("\n");
1817 }
1818
Brian Paulade50832008-05-14 16:09:46 -06001819 /* A uniform var may be used by both a vertex shader and a fragment
1820 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001821 */
Brian Paulade50832008-05-14 16:09:46 -06001822 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001823 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001824 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001825 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001826 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001827 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001828 }
Brian5b01c5e2006-12-19 18:02:03 -07001829 }
Brian5cf73262007-01-05 16:02:45 -07001830
Brian Paulade50832008-05-14 16:09:46 -06001831 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001832 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001833 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001834 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001835 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001836 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06001837 }
1838 }
Brian Paul949e7382008-11-05 09:17:55 -07001839
Brian Paul2d76a0d2008-11-10 12:33:17 -07001840 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06001841}
1842
1843
Brian Pauleda291e2008-08-06 16:26:47 -06001844/**
1845 * Set a matrix-valued program parameter.
1846 */
Brian Paulade50832008-05-14 16:09:46 -06001847static void
1848set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06001849 GLuint index, GLuint offset,
1850 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001851 GLboolean transpose, const GLfloat *values)
1852{
Brian Paulffbc66b2008-07-21 13:58:50 -06001853 GLuint mat, row, col;
Brian Pauleda291e2008-08-06 16:26:47 -06001854 GLuint dst = index + offset, src = 0;
Brian Paulffbc66b2008-07-21 13:58:50 -06001855 GLint nr, nc;
1856
1857 /* check that the number of rows, columns is correct */
Brian Pauleda291e2008-08-06 16:26:47 -06001858 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06001859 if (rows != nr || cols != nc) {
1860 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06001861 "glUniformMatrix(matrix size mismatch)");
1862 return;
1863 }
1864
1865 if (index + offset > program->Parameters->Size) {
1866 /* out of bounds! */
Brian Paulffbc66b2008-07-21 13:58:50 -06001867 return;
1868 }
1869
Brian Paulade50832008-05-14 16:09:46 -06001870 /*
1871 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001872 * the rows. So, the loops below look a little funny.
1873 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001874 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001875
1876 /* loop over matrices */
1877 for (mat = 0; mat < count; mat++) {
1878
1879 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001880 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001881 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001882 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001883 if (transpose) {
1884 v[row] = values[src + row * cols + col];
1885 }
1886 else {
1887 v[row] = values[src + col * rows + row];
1888 }
Brian Paulade50832008-05-14 16:09:46 -06001889 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001890 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001891 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001892
1893 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001894 }
Brian34ae99d2006-12-18 08:28:54 -07001895}
1896
1897
1898/**
Brian5b01c5e2006-12-19 18:02:03 -07001899 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001900 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001901 */
Brian Paulfd59f192008-05-18 16:04:55 -06001902static void
Brian5b01c5e2006-12-19 18:02:03 -07001903_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
Brian Paul0115a4f2009-04-14 20:00:28 -06001904 GLint location, GLsizei count,
Brian5b01c5e2006-12-19 18:02:03 -07001905 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001906{
Brian3a8e2772006-12-20 17:19:16 -07001907 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001908 struct gl_uniform *uniform;
1909 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06001910
Brian3a8e2772006-12-20 17:19:16 -07001911 if (!shProg || !shProg->LinkStatus) {
1912 _mesa_error(ctx, GL_INVALID_OPERATION,
1913 "glUniformMatrix(program not linked)");
1914 return;
1915 }
Brian Paulade50832008-05-14 16:09:46 -06001916
Bruce Merry89b80322007-12-21 15:20:17 +02001917 if (location == -1)
1918 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001919
Brian Paul234f03e2009-02-11 09:05:08 -07001920 if (location < -1) {
1921 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1922 return;
1923 }
1924
Brian Pauleda291e2008-08-06 16:26:47 -06001925 split_location_offset(&location, &offset);
1926
Brian Paul016701f2008-07-29 17:43:35 -06001927 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001928 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001929 return;
1930 }
Brian34ae99d2006-12-18 08:28:54 -07001931 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001932 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001933 return;
1934 }
1935
Brian Paul027ed1b2009-04-24 09:43:44 -06001936 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Brian34ae99d2006-12-18 08:28:54 -07001937
Brian Paul2d76a0d2008-11-10 12:33:17 -07001938 uniform = &shProg->Uniforms->Uniforms[location];
1939
Brian Paulade50832008-05-14 16:09:46 -06001940 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001941 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001942 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001943 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001944 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001945 index, offset,
1946 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001947 }
Brian Paulade50832008-05-14 16:09:46 -06001948 }
1949
1950 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001951 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001952 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001953 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001954 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001955 index, offset,
1956 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001957 }
Brian34ae99d2006-12-18 08:28:54 -07001958 }
Brian Paul949e7382008-11-05 09:17:55 -07001959
Brian Paul2d76a0d2008-11-10 12:33:17 -07001960 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001961}
1962
1963
Brian Paulfd59f192008-05-18 16:04:55 -06001964static void
Brian5b01c5e2006-12-19 18:02:03 -07001965_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001966{
Brian65a18442006-12-19 18:46:56 -07001967 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001968
1969 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001970 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001971 return;
1972 }
1973
Brian Paulbc985b52008-07-21 14:16:07 -06001974 if (!shProg->LinkStatus) {
1975 shProg->Validated = GL_FALSE;
1976 return;
1977 }
1978
1979 /* From the GL spec, a program is invalid if any of these are true:
1980
Brian5b01c5e2006-12-19 18:02:03 -07001981 any two active samplers in the current program object are of
1982 different types, but refer to the same texture image unit,
1983
1984 any active sampler in the current program object refers to a texture
1985 image unit where fixed-function fragment processing accesses a
1986 texture target that does not match the sampler type, or
1987
1988 the sum of the number of active samplers in the program and the
1989 number of texture image units enabled for fixed-function fragment
1990 processing exceeds the combined limit on the total number of texture
1991 image units allowed.
1992 */
Brian Paulbc985b52008-07-21 14:16:07 -06001993
1994 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001995}
Brian Paulfd59f192008-05-18 16:04:55 -06001996
1997
1998/**
1999 * Plug in Mesa's GLSL functions into the device driver function table.
2000 */
2001void
2002_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
2003{
2004 driver->AttachShader = _mesa_attach_shader;
2005 driver->BindAttribLocation = _mesa_bind_attrib_location;
2006 driver->CompileShader = _mesa_compile_shader;
2007 driver->CreateProgram = _mesa_create_program;
2008 driver->CreateShader = _mesa_create_shader;
2009 driver->DeleteProgram2 = _mesa_delete_program2;
2010 driver->DeleteShader = _mesa_delete_shader;
2011 driver->DetachShader = _mesa_detach_shader;
2012 driver->GetActiveAttrib = _mesa_get_active_attrib;
2013 driver->GetActiveUniform = _mesa_get_active_uniform;
2014 driver->GetAttachedShaders = _mesa_get_attached_shaders;
2015 driver->GetAttribLocation = _mesa_get_attrib_location;
2016 driver->GetHandle = _mesa_get_handle;
2017 driver->GetProgramiv = _mesa_get_programiv;
2018 driver->GetProgramInfoLog = _mesa_get_program_info_log;
2019 driver->GetShaderiv = _mesa_get_shaderiv;
2020 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
2021 driver->GetShaderSource = _mesa_get_shader_source;
2022 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06002023 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06002024 driver->GetUniformLocation = _mesa_get_uniform_location;
2025 driver->IsProgram = _mesa_is_program;
2026 driver->IsShader = _mesa_is_shader;
2027 driver->LinkProgram = _mesa_link_program;
2028 driver->ShaderSource = _mesa_shader_source;
2029 driver->Uniform = _mesa_uniform;
2030 driver->UniformMatrix = _mesa_uniform_matrix;
2031 driver->UseProgram = _mesa_use_program;
2032 driver->ValidateProgram = _mesa_validate_program;
2033}