blob: b8b34bb2b454570f066dbd9a72c292a3abfd24e0 [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
Brian Paulbda6ad22008-08-06 12:45:14 -060054#ifndef GL_PROGRAM_BINARY_LENGTH_OES
55#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
56#endif
57
58
Brianf2923612006-12-20 09:56:44 -070059/**
60 * Allocate a new gl_shader_program object, initialize it.
61 */
Brian Paulfd59f192008-05-18 16:04:55 -060062static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070063_mesa_new_shader_program(GLcontext *ctx, GLuint name)
64{
65 struct gl_shader_program *shProg;
66 shProg = CALLOC_STRUCT(gl_shader_program);
67 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060068 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070069 shProg->Name = name;
70 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070071 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070072 }
73 return shProg;
74}
75
76
Brianb9fbedd2007-03-26 09:23:44 -060077/**
Brian3c008a02007-04-12 15:22:32 -060078 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060079 */
Brianf2923612006-12-20 09:56:44 -070080void
Brian3c008a02007-04-12 15:22:32 -060081_mesa_clear_shader_program_data(GLcontext *ctx,
82 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070083{
Brian Paul8bdf5b62008-05-16 09:56:59 -060084 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
85 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070086
Brianf2923612006-12-20 09:56:44 -070087 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060088 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070089 shProg->Uniforms = NULL;
90 }
91
92 if (shProg->Varying) {
93 _mesa_free_parameter_list(shProg->Varying);
94 shProg->Varying = NULL;
95 }
96}
97
98
Brianb9fbedd2007-03-26 09:23:44 -060099/**
Brian3c008a02007-04-12 15:22:32 -0600100 * Free all the data that hangs off a shader program object, but not the
101 * object itself.
102 */
103void
104_mesa_free_shader_program_data(GLcontext *ctx,
105 struct gl_shader_program *shProg)
106{
107 GLuint i;
108
Brianf3e8c322007-04-18 14:53:23 -0600109 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600110
111 _mesa_clear_shader_program_data(ctx, shProg);
112
Brian4b7c6fc2007-04-19 15:23:34 -0600113 if (shProg->Attributes) {
114 _mesa_free_parameter_list(shProg->Attributes);
115 shProg->Attributes = NULL;
116 }
117
Brian3c008a02007-04-12 15:22:32 -0600118 /* detach shaders */
119 for (i = 0; i < shProg->NumShaders; i++) {
120 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
121 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800122 shProg->NumShaders = 0;
123
Brian3c008a02007-04-12 15:22:32 -0600124 if (shProg->Shaders) {
125 _mesa_free(shProg->Shaders);
126 shProg->Shaders = NULL;
127 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100128
129 if (shProg->InfoLog) {
130 _mesa_free(shProg->InfoLog);
131 shProg->InfoLog = NULL;
132 }
Brian3c008a02007-04-12 15:22:32 -0600133}
134
135
136/**
Brianb9fbedd2007-03-26 09:23:44 -0600137 * Free/delete a shader program object.
138 */
Brianf2923612006-12-20 09:56:44 -0700139void
140_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
141{
142 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100143
Brianf2923612006-12-20 09:56:44 -0700144 _mesa_free(shProg);
145}
146
147
148/**
Brian3c008a02007-04-12 15:22:32 -0600149 * Set ptr to point to shProg.
150 * If ptr is pointing to another object, decrement its refcount (and delete
151 * if refcount hits zero).
152 * Then set ptr to point to shProg, incrementing its refcount.
153 */
154/* XXX this could be static */
155void
156_mesa_reference_shader_program(GLcontext *ctx,
157 struct gl_shader_program **ptr,
158 struct gl_shader_program *shProg)
159{
160 assert(ptr);
161 if (*ptr == shProg) {
162 /* no-op */
163 return;
164 }
165 if (*ptr) {
166 /* Unreference the old shader program */
167 GLboolean deleteFlag = GL_FALSE;
168 struct gl_shader_program *old = *ptr;
169
170 ASSERT(old->RefCount > 0);
171 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600172#if 0
173 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
174 (void *) old, old->Name, old->RefCount);
175#endif
Brian3c008a02007-04-12 15:22:32 -0600176 deleteFlag = (old->RefCount == 0);
177
178 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800179 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600180 _mesa_free_shader_program(ctx, old);
181 }
182
183 *ptr = NULL;
184 }
185 assert(!*ptr);
186
187 if (shProg) {
188 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600189#if 0
190 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
191 (void *) shProg, shProg->Name, shProg->RefCount);
192#endif
Brian3c008a02007-04-12 15:22:32 -0600193 *ptr = shProg;
194 }
195}
196
197
198/**
Brianf2923612006-12-20 09:56:44 -0700199 * Lookup a GLSL program object.
200 */
201struct gl_shader_program *
202_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
203{
204 struct gl_shader_program *shProg;
205 if (name) {
206 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800207 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700208 /* Note that both gl_shader and gl_shader_program objects are kept
209 * in the same hash table. Check the object's type to be sure it's
210 * what we're expecting.
211 */
Brianf3e8c322007-04-18 14:53:23 -0600212 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700213 return NULL;
214 }
215 return shProg;
216 }
217 return NULL;
218}
219
220
221/**
Brian Paul530df582008-07-03 16:21:11 -0600222 * As above, but record an error if program is not found.
223 */
224static struct gl_shader_program *
225_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
226 const char *caller)
227{
228 if (!name) {
229 _mesa_error(ctx, GL_INVALID_VALUE, caller);
230 return NULL;
231 }
232 else {
233 struct gl_shader_program *shProg = (struct gl_shader_program *)
234 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
235 if (!shProg) {
236 _mesa_error(ctx, GL_INVALID_VALUE, caller);
237 return NULL;
238 }
239 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
240 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
241 return NULL;
242 }
243 return shProg;
244 }
245}
246
247
248
249
250/**
Brianf2923612006-12-20 09:56:44 -0700251 * Allocate a new gl_shader object, initialize it.
252 */
253struct gl_shader *
254_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
255{
256 struct gl_shader *shader;
257 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
258 shader = CALLOC_STRUCT(gl_shader);
259 if (shader) {
260 shader->Type = type;
261 shader->Name = name;
262 shader->RefCount = 1;
263 }
264 return shader;
265}
266
267
268void
269_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
270{
Brianf2923612006-12-20 09:56:44 -0700271 if (sh->Source)
272 _mesa_free((void *) sh->Source);
273 if (sh->InfoLog)
274 _mesa_free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600275 _mesa_reference_program(ctx, &sh->Program, NULL);
Brianf2923612006-12-20 09:56:44 -0700276 _mesa_free(sh);
277}
278
279
280/**
Brian3c008a02007-04-12 15:22:32 -0600281 * Set ptr to point to sh.
282 * If ptr is pointing to another shader, decrement its refcount (and delete
283 * if refcount hits zero).
284 * Then set ptr to point to sh, incrementing its refcount.
285 */
286/* XXX this could be static */
287void
288_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
289 struct gl_shader *sh)
290{
291 assert(ptr);
292 if (*ptr == sh) {
293 /* no-op */
294 return;
295 }
296 if (*ptr) {
297 /* Unreference the old shader */
298 GLboolean deleteFlag = GL_FALSE;
299 struct gl_shader *old = *ptr;
300
301 ASSERT(old->RefCount > 0);
302 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600303 /*printf("SHADER DECR %p (%d) to %d\n",
304 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600305 deleteFlag = (old->RefCount == 0);
306
307 if (deleteFlag) {
308 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
309 _mesa_free_shader(ctx, old);
310 }
311
312 *ptr = NULL;
313 }
314 assert(!*ptr);
315
316 if (sh) {
317 /* reference new */
318 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600319 /*printf("SHADER INCR %p (%d) to %d\n",
320 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600321 *ptr = sh;
322 }
323}
324
325
326/**
Brianf2923612006-12-20 09:56:44 -0700327 * Lookup a GLSL shader object.
328 */
329struct gl_shader *
330_mesa_lookup_shader(GLcontext *ctx, GLuint name)
331{
332 if (name) {
333 struct gl_shader *sh = (struct gl_shader *)
334 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
335 /* Note that both gl_shader and gl_shader_program objects are kept
336 * in the same hash table. Check the object's type to be sure it's
337 * what we're expecting.
338 */
Brianf3e8c322007-04-18 14:53:23 -0600339 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700340 return NULL;
341 }
342 return sh;
343 }
344 return NULL;
345}
346
347
Brianfa4d0362007-02-26 18:33:50 -0700348/**
Brian Paul530df582008-07-03 16:21:11 -0600349 * As above, but record an error if shader is not found.
350 */
351static struct gl_shader *
352_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
353{
354 if (!name) {
355 _mesa_error(ctx, GL_INVALID_VALUE, caller);
356 return NULL;
357 }
358 else {
359 struct gl_shader *sh = (struct gl_shader *)
360 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
361 if (!sh) {
362 _mesa_error(ctx, GL_INVALID_VALUE, caller);
363 return NULL;
364 }
365 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
366 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
367 return NULL;
368 }
369 return sh;
370 }
371}
372
373
Brian Paule01a03d2009-02-06 10:21:36 -0700374/**
375 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
376 */
377static GLbitfield
378get_shader_flags(void)
379{
380 GLbitfield flags = 0x0;
381 const char *env = _mesa_getenv("MESA_GLSL");
382
383 if (env) {
384 if (_mesa_strstr(env, "dump"))
385 flags |= GLSL_DUMP;
386 if (_mesa_strstr(env, "log"))
387 flags |= GLSL_LOG;
388 if (_mesa_strstr(env, "nopt"))
389 flags |= GLSL_NO_OPT;
390 else if (_mesa_strstr(env, "opt"))
391 flags |= GLSL_OPT;
392 if (_mesa_strstr(env, "uniform"))
393 flags |= GLSL_UNIFORMS;
394 }
395
396 return flags;
397}
398
Brian Paul530df582008-07-03 16:21:11 -0600399
400/**
Brianfa4d0362007-02-26 18:33:50 -0700401 * Initialize context's shader state.
402 */
Brianf2923612006-12-20 09:56:44 -0700403void
404_mesa_init_shader_state(GLcontext * ctx)
405{
Brianfa4d0362007-02-26 18:33:50 -0700406 /* Device drivers may override these to control what kind of instructions
407 * are generated by the GLSL compiler.
408 */
409 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700410 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700411 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700412 ctx->Shader.Flags = get_shader_flags();
Brianf2923612006-12-20 09:56:44 -0700413}
414
415
Brian5b01c5e2006-12-19 18:02:03 -0700416/**
Brian935f93f2007-03-24 16:20:02 -0600417 * Free the per-context shader-related state.
418 */
419void
420_mesa_free_shader_state(GLcontext *ctx)
421{
Brian3c008a02007-04-12 15:22:32 -0600422 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600423}
424
425
426/**
Brian5b01c5e2006-12-19 18:02:03 -0700427 * Copy string from <src> to <dst>, up to maxLength characters, returning
428 * length of <dst> in <length>.
429 * \param src the strings source
430 * \param maxLength max chars to copy
431 * \param length returns number of chars copied
432 * \param dst the string destination
433 */
434static void
435copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
436{
437 GLsizei len;
438 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
439 dst[len] = src[len];
440 if (maxLength > 0)
441 dst[len] = 0;
442 if (length)
443 *length = len;
444}
445
446
Brian Paul7acb7c12008-07-03 13:49:48 -0600447static GLboolean
448_mesa_is_program(GLcontext *ctx, GLuint name)
449{
450 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
451 return shProg ? GL_TRUE : GL_FALSE;
452}
453
454
455static GLboolean
456_mesa_is_shader(GLcontext *ctx, GLuint name)
457{
458 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
459 return shader ? GL_TRUE : GL_FALSE;
460}
461
462
Brian5b01c5e2006-12-19 18:02:03 -0700463/**
464 * Called via ctx->Driver.AttachShader()
465 */
Brian Paulfd59f192008-05-18 16:04:55 -0600466static void
Brian5b01c5e2006-12-19 18:02:03 -0700467_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
468{
Brian Paul530df582008-07-03 16:21:11 -0600469 struct gl_shader_program *shProg;
470 struct gl_shader *sh;
471 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700472
Brian Paul530df582008-07-03 16:21:11 -0600473 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
474 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700475 return;
Brian5b01c5e2006-12-19 18:02:03 -0700476
Brian Paul530df582008-07-03 16:21:11 -0600477 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600478 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600479 return;
480 }
481
Brian237b9852007-08-07 21:48:31 +0100482 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700483 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700484 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700485 /* The shader is already attched to this program. The
486 * GL_ARB_shader_objects spec says:
487 *
488 * "The error INVALID_OPERATION is generated by AttachObjectARB
489 * if <obj> is already attached to <containerObj>."
490 */
491 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700492 return;
Brian34ae99d2006-12-18 08:28:54 -0700493 }
494 }
Brian5b01c5e2006-12-19 18:02:03 -0700495
496 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700497 shProg->Shaders = (struct gl_shader **)
498 _mesa_realloc(shProg->Shaders,
499 n * sizeof(struct gl_shader *),
500 (n + 1) * sizeof(struct gl_shader *));
501 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700502 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
503 return;
504 }
505
506 /* append */
Brian3c008a02007-04-12 15:22:32 -0600507 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
508 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700509 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700510}
511
512
Brian Paulfd59f192008-05-18 16:04:55 -0600513static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600514_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
515 const GLchar *name)
516{
517 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600518 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600519
520 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600521 return -1;
522 }
523
524 if (!shProg->LinkStatus) {
525 _mesa_error(ctx, GL_INVALID_OPERATION,
526 "glGetAttribLocation(program not linked)");
527 return -1;
528 }
529
530 if (!name)
531 return -1;
532
Brian Paul27341a92008-09-16 16:28:36 -0600533 if (shProg->VertexProgram) {
534 const struct gl_program_parameter_list *attribs =
535 shProg->VertexProgram->Base.Attributes;
536 if (attribs) {
537 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
538 if (i >= 0) {
539 return attribs->Parameters[i].StateIndexes[0];
540 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600541 }
542 }
543 return -1;
544}
545
546
Brian Paulfd59f192008-05-18 16:04:55 -0600547static void
Brian5b01c5e2006-12-19 18:02:03 -0700548_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
549 const GLchar *name)
550{
Brian Paul530df582008-07-03 16:21:11 -0600551 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700552 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600553 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600554 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700555
Brian Paul530df582008-07-03 16:21:11 -0600556 shProg = _mesa_lookup_shader_program_err(ctx, program,
557 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700558 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700559 return;
560 }
561
Brian9e4bae92006-12-20 09:27:42 -0700562 if (!name)
563 return;
564
565 if (strncmp(name, "gl_", 3) == 0) {
566 _mesa_error(ctx, GL_INVALID_OPERATION,
567 "glBindAttribLocation(illegal name)");
568 return;
569 }
570
Brian Paul7acb7c12008-07-03 13:49:48 -0600571 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
572 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
573 return;
574 }
575
Brian Paul6bc87492008-07-25 08:34:54 -0600576 if (shProg->LinkStatus) {
577 /* get current index/location for the attribute */
578 oldIndex = _mesa_get_attrib_location(ctx, program, name);
579 }
580 else {
581 oldIndex = -1;
582 }
583
Brian3209c3e2007-01-09 17:49:24 -0700584 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600585 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700586 if (i < 0) {
587 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600588 return;
Brian3209c3e2007-01-09 17:49:24 -0700589 }
590
Brian Paul27341a92008-09-16 16:28:36 -0600591 /*
592 * Note that this attribute binding won't go into effect until
593 * glLinkProgram is called again.
594 */
Brian34ae99d2006-12-18 08:28:54 -0700595}
596
597
Brian Paulfd59f192008-05-18 16:04:55 -0600598static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700599_mesa_create_shader(GLcontext *ctx, GLenum type)
600{
Brian65a18442006-12-19 18:46:56 -0700601 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700602 GLuint name;
603
604 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
605
606 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700607 case GL_FRAGMENT_SHADER:
608 case GL_VERTEX_SHADER:
609 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700610 break;
611 default:
612 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
613 return 0;
614 }
615
Brian65a18442006-12-19 18:46:56 -0700616 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700617
618 return name;
619}
620
621
Brian Paulfd59f192008-05-18 16:04:55 -0600622static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700623_mesa_create_program(GLcontext *ctx)
624{
625 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700626 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700627
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800628 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700629 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700630
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800631 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700632
Brian3c008a02007-04-12 15:22:32 -0600633 assert(shProg->RefCount == 1);
634
Brian5b01c5e2006-12-19 18:02:03 -0700635 return name;
636}
637
638
Brian3c008a02007-04-12 15:22:32 -0600639/**
640 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
641 * DeleteProgramARB.
642 */
Brian Paulfd59f192008-05-18 16:04:55 -0600643static void
Brian5b01c5e2006-12-19 18:02:03 -0700644_mesa_delete_program2(GLcontext *ctx, GLuint name)
645{
Brian3c008a02007-04-12 15:22:32 -0600646 /*
647 * NOTE: deleting shaders/programs works a bit differently than
648 * texture objects (and buffer objects, etc). Shader/program
649 * handles/IDs exist in the hash table until the object is really
650 * deleted (refcount==0). With texture objects, the handle/ID is
651 * removed from the hash table in glDeleteTextures() while the tex
652 * object itself might linger until its refcount goes to zero.
653 */
Brian65a18442006-12-19 18:46:56 -0700654 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700655
Brian Paul530df582008-07-03 16:21:11 -0600656 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
657 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700658 return;
Brian5b01c5e2006-12-19 18:02:03 -0700659
Brian9e4bae92006-12-20 09:27:42 -0700660 shProg->DeletePending = GL_TRUE;
661
Brian3c008a02007-04-12 15:22:32 -0600662 /* effectively, decr shProg's refcount */
663 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700664}
665
666
Brian Paulfd59f192008-05-18 16:04:55 -0600667static void
Brian5b01c5e2006-12-19 18:02:03 -0700668_mesa_delete_shader(GLcontext *ctx, GLuint shader)
669{
Brian Paul530df582008-07-03 16:21:11 -0600670 struct gl_shader *sh;
671
672 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
673 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700674 return;
Brian5b01c5e2006-12-19 18:02:03 -0700675
Brian9e4bae92006-12-20 09:27:42 -0700676 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600677
678 /* effectively, decr sh's refcount */
679 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700680}
681
682
Brian Paulfd59f192008-05-18 16:04:55 -0600683static void
Brian5b01c5e2006-12-19 18:02:03 -0700684_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
685{
Brian Paul530df582008-07-03 16:21:11 -0600686 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100687 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700688 GLuint i, j;
689
Brian Paul530df582008-07-03 16:21:11 -0600690 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
691 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700692 return;
Brian5b01c5e2006-12-19 18:02:03 -0700693
Brian237b9852007-08-07 21:48:31 +0100694 n = shProg->NumShaders;
695
Brian5b01c5e2006-12-19 18:02:03 -0700696 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700697 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700698 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600699 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700700
Brian Paul530df582008-07-03 16:21:11 -0600701 /* release */
Brian3c008a02007-04-12 15:22:32 -0600702 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700703
Brian5b01c5e2006-12-19 18:02:03 -0700704 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700705 newList = (struct gl_shader **)
706 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700707 if (!newList) {
708 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
709 return;
710 }
711 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700712 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700713 }
714 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700715 newList[j++] = shProg->Shaders[i];
716 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700717
Brian65a18442006-12-19 18:46:56 -0700718 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600719 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600720
721#ifdef DEBUG
722 /* sanity check */
723 {
724 for (j = 0; j < shProg->NumShaders; j++) {
725 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
726 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
727 assert(shProg->Shaders[j]->RefCount > 0);
728 }
729 }
730#endif
731
Brian5b01c5e2006-12-19 18:02:03 -0700732 return;
733 }
734 }
735
736 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600737 {
738 GLenum err;
739 if (_mesa_is_shader(ctx, shader))
740 err = GL_INVALID_OPERATION;
741 else if (_mesa_is_program(ctx, shader))
742 err = GL_INVALID_OPERATION;
743 else
744 err = GL_INVALID_VALUE;
745 _mesa_error(ctx, err, "glDetachProgram(shader)");
746 return;
747 }
Brian5b01c5e2006-12-19 18:02:03 -0700748}
749
750
Brian Paulffbc66b2008-07-21 13:58:50 -0600751static GLint
752sizeof_glsl_type(GLenum type)
753{
754 switch (type) {
755 case GL_FLOAT:
756 case GL_INT:
757 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600758 case GL_SAMPLER_1D:
759 case GL_SAMPLER_2D:
760 case GL_SAMPLER_3D:
761 case GL_SAMPLER_CUBE:
762 case GL_SAMPLER_1D_SHADOW:
763 case GL_SAMPLER_2D_SHADOW:
764 case GL_SAMPLER_2D_RECT_ARB:
765 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
766 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
767 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
768 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600769 return 1;
770 case GL_FLOAT_VEC2:
771 case GL_INT_VEC2:
772 case GL_BOOL_VEC2:
773 return 2;
774 case GL_FLOAT_VEC3:
775 case GL_INT_VEC3:
776 case GL_BOOL_VEC3:
777 return 3;
778 case GL_FLOAT_VEC4:
779 case GL_INT_VEC4:
780 case GL_BOOL_VEC4:
781 return 4;
782 case GL_FLOAT_MAT2:
783 case GL_FLOAT_MAT2x3:
784 case GL_FLOAT_MAT2x4:
785 return 8; /* two float[4] vectors */
786 case GL_FLOAT_MAT3:
787 case GL_FLOAT_MAT3x2:
788 case GL_FLOAT_MAT3x4:
789 return 12; /* three float[4] vectors */
790 case GL_FLOAT_MAT4:
791 case GL_FLOAT_MAT4x2:
792 case GL_FLOAT_MAT4x3:
793 return 16; /* four float[4] vectors */
794 default:
795 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
796 return 1;
797 }
798}
799
800
Brian Pauleda291e2008-08-06 16:26:47 -0600801static GLboolean
802is_boolean_type(GLenum type)
803{
804 switch (type) {
805 case GL_BOOL:
806 case GL_BOOL_VEC2:
807 case GL_BOOL_VEC3:
808 case GL_BOOL_VEC4:
809 return GL_TRUE;
810 default:
811 return GL_FALSE;
812 }
813}
814
815
816static GLboolean
817is_integer_type(GLenum type)
818{
819 switch (type) {
820 case GL_INT:
821 case GL_INT_VEC2:
822 case GL_INT_VEC3:
823 case GL_INT_VEC4:
824 return GL_TRUE;
825 default:
826 return GL_FALSE;
827 }
828}
829
830
Brian Paulc4ffbf02009-02-18 17:46:00 -0700831static GLboolean
832is_sampler_type(GLenum type)
833{
834 switch (type) {
835 case GL_SAMPLER_1D:
836 case GL_SAMPLER_2D:
837 case GL_SAMPLER_3D:
838 case GL_SAMPLER_CUBE:
839 case GL_SAMPLER_1D_SHADOW:
840 case GL_SAMPLER_2D_SHADOW:
841 case GL_SAMPLER_2D_RECT_ARB:
842 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
843 case GL_SAMPLER_1D_ARRAY_EXT:
844 case GL_SAMPLER_2D_ARRAY_EXT:
845 return GL_TRUE;
846 default:
847 return GL_FALSE;
848 }
849}
850
851
Brian Paulfd59f192008-05-18 16:04:55 -0600852static void
Brian5b01c5e2006-12-19 18:02:03 -0700853_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
854 GLsizei maxLength, GLsizei *length, GLint *size,
855 GLenum *type, GLchar *nameOut)
856{
Brian Paul27341a92008-09-16 16:28:36 -0600857 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600858 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700859
Brian Paul530df582008-07-03 16:21:11 -0600860 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
861 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700862 return;
Brian5b01c5e2006-12-19 18:02:03 -0700863
Brian Paul27341a92008-09-16 16:28:36 -0600864 if (shProg->VertexProgram)
865 attribs = shProg->VertexProgram->Base.Attributes;
866
867 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600868 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700869 return;
870 }
871
Brian Paul27341a92008-09-16 16:28:36 -0600872 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
873
Brian5b01c5e2006-12-19 18:02:03 -0700874 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600875 *size = attribs->Parameters[index].Size
876 / sizeof_glsl_type(attribs->Parameters[index].DataType);
877
Brian Paulade50832008-05-14 16:09:46 -0600878 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600879 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700880}
881
882
Brian Pauleda291e2008-08-06 16:26:47 -0600883static struct gl_program_parameter *
884get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
885{
886 const struct gl_program *prog;
887 GLint progPos;
888
889 progPos = shProg->Uniforms->Uniforms[index].VertPos;
890 if (progPos >= 0) {
891 prog = &shProg->VertexProgram->Base;
892 }
893 else {
894 progPos = shProg->Uniforms->Uniforms[index].FragPos;
895 if (progPos >= 0) {
896 prog = &shProg->FragmentProgram->Base;
897 }
898 }
899
900 if (!prog || progPos < 0)
901 return NULL; /* should never happen */
902
903 return &prog->Parameters->Parameters[progPos];
904}
905
906
Brian5b01c5e2006-12-19 18:02:03 -0700907/**
908 * Called via ctx->Driver.GetActiveUniform().
909 */
Brian Paulfd59f192008-05-18 16:04:55 -0600910static void
Brian5b01c5e2006-12-19 18:02:03 -0700911_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
912 GLsizei maxLength, GLsizei *length, GLint *size,
913 GLenum *type, GLchar *nameOut)
914{
Brian Paul530df582008-07-03 16:21:11 -0600915 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600916 const struct gl_program *prog;
Brian Paul369d1852009-02-11 08:16:14 -0700917 const struct gl_program_parameter *param;
Brian Paulade50832008-05-14 16:09:46 -0600918 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700919
Brian Paul530df582008-07-03 16:21:11 -0600920 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
921 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700922 return;
Brian5b01c5e2006-12-19 18:02:03 -0700923
Brian Paulade50832008-05-14 16:09:46 -0600924 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700925 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
926 return;
927 }
928
Brian Paulade50832008-05-14 16:09:46 -0600929 progPos = shProg->Uniforms->Uniforms[index].VertPos;
930 if (progPos >= 0) {
931 prog = &shProg->VertexProgram->Base;
932 }
933 else {
934 progPos = shProg->Uniforms->Uniforms[index].FragPos;
935 if (progPos >= 0) {
936 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600937 }
938 }
939
Brian Paulade50832008-05-14 16:09:46 -0600940 if (!prog || progPos < 0)
941 return; /* should never happen */
942
Brian Paul369d1852009-02-11 08:16:14 -0700943 ASSERT(progPos < prog->Parameters->NumParameters);
944 param = &prog->Parameters->Parameters[progPos];
945
946 if (nameOut) {
947 copy_string(nameOut, maxLength, length, param->Name);
948 }
949
950 if (size) {
951 GLint typeSize = sizeof_glsl_type(param->DataType);
952 if (param->Size > typeSize) {
953 /* This is an array.
954 * Array elements are placed on vector[4] boundaries so they're
955 * a multiple of four floats. We round typeSize up to next multiple
956 * of four to get the right size below.
957 */
958 typeSize = (typeSize + 3) & ~3;
959 }
960 /* Note that the returned size is in units of the <type>, not bytes */
961 *size = param->Size / typeSize;
962 }
963
964 if (type) {
965 *type = param->DataType;
966 }
Brian5b01c5e2006-12-19 18:02:03 -0700967}
968
969
970/**
971 * Called via ctx->Driver.GetAttachedShaders().
972 */
Brian Paulfd59f192008-05-18 16:04:55 -0600973static void
Brian5b01c5e2006-12-19 18:02:03 -0700974_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
975 GLsizei *count, GLuint *obj)
976{
Brian Paul530df582008-07-03 16:21:11 -0600977 struct gl_shader_program *shProg =
978 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700979 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600980 GLuint i;
981 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700982 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700983 }
984 if (count)
985 *count = i;
986 }
Brian5b01c5e2006-12-19 18:02:03 -0700987}
988
989
Brian Paulfd59f192008-05-18 16:04:55 -0600990static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700991_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700992{
Ian Romanick905d8e02008-09-29 12:27:00 -0700993 GLint handle = 0;
994
995 if (pname == GL_PROGRAM_OBJECT_ARB) {
996 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
997 } else {
Brian34ae99d2006-12-18 08:28:54 -0700998 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
999 }
Ian Romanick905d8e02008-09-29 12:27:00 -07001000
1001 return handle;
Brian34ae99d2006-12-18 08:28:54 -07001002}
1003
1004
Brian Paulfd59f192008-05-18 16:04:55 -06001005static void
Brian5b01c5e2006-12-19 18:02:03 -07001006_mesa_get_programiv(GLcontext *ctx, GLuint program,
1007 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -07001008{
Brian Paul27341a92008-09-16 16:28:36 -06001009 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -07001010 struct gl_shader_program *shProg
1011 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -07001012
Brian65a18442006-12-19 18:46:56 -07001013 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001014 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -07001015 return;
1016 }
1017
Brian Paul27341a92008-09-16 16:28:36 -06001018 if (shProg->VertexProgram)
1019 attribs = shProg->VertexProgram->Base.Attributes;
1020 else
1021 attribs = NULL;
1022
Brian5b01c5e2006-12-19 18:02:03 -07001023 switch (pname) {
1024 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001025 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -07001026 break;
1027 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -07001028 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -07001029 break;
Brian5b01c5e2006-12-19 18:02:03 -07001030 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001031 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -07001032 break;
1033 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001034 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001035 break;
1036 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -07001037 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -07001038 break;
1039 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -06001040 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001041 break;
1042 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -06001043 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -07001044 break;
1045 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -06001046 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001047 break;
1048 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -06001049 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -06001050 if (*params > 0)
1051 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -07001052 break;
Brian Paulbda6ad22008-08-06 12:45:14 -06001053 case GL_PROGRAM_BINARY_LENGTH_OES:
1054 *params = 0;
1055 break;
Brian34ae99d2006-12-18 08:28:54 -07001056 default:
Brian5b01c5e2006-12-19 18:02:03 -07001057 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
1058 return;
Brian34ae99d2006-12-18 08:28:54 -07001059 }
Brian5b01c5e2006-12-19 18:02:03 -07001060}
Brian34ae99d2006-12-18 08:28:54 -07001061
Brian34ae99d2006-12-18 08:28:54 -07001062
Brian Paulfd59f192008-05-18 16:04:55 -06001063static void
Brian5b01c5e2006-12-19 18:02:03 -07001064_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
1065{
Brian Paul530df582008-07-03 16:21:11 -06001066 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -07001067
1068 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -07001069 return;
1070 }
Brian65a18442006-12-19 18:46:56 -07001071
Brian5b01c5e2006-12-19 18:02:03 -07001072 switch (pname) {
1073 case GL_SHADER_TYPE:
1074 *params = shader->Type;
1075 break;
1076 case GL_DELETE_STATUS:
1077 *params = shader->DeletePending;
1078 break;
1079 case GL_COMPILE_STATUS:
1080 *params = shader->CompileStatus;
1081 break;
1082 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001083 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001084 break;
1085 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001086 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001087 break;
1088 default:
1089 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1090 return;
1091 }
1092}
1093
1094
Brian Paulfd59f192008-05-18 16:04:55 -06001095static void
Brian5b01c5e2006-12-19 18:02:03 -07001096_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1097 GLsizei *length, GLchar *infoLog)
1098{
Brian65a18442006-12-19 18:46:56 -07001099 struct gl_shader_program *shProg
1100 = _mesa_lookup_shader_program(ctx, program);
1101 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001102 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1103 return;
1104 }
Brian65a18442006-12-19 18:46:56 -07001105 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001106}
1107
1108
Brian Paulfd59f192008-05-18 16:04:55 -06001109static void
Brian5b01c5e2006-12-19 18:02:03 -07001110_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1111 GLsizei *length, GLchar *infoLog)
1112{
Brian65a18442006-12-19 18:46:56 -07001113 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1114 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001115 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1116 return;
1117 }
Brian65a18442006-12-19 18:46:56 -07001118 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001119}
1120
1121
1122/**
1123 * Called via ctx->Driver.GetShaderSource().
1124 */
Brian Paulfd59f192008-05-18 16:04:55 -06001125static void
Brian5b01c5e2006-12-19 18:02:03 -07001126_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1127 GLsizei *length, GLchar *sourceOut)
1128{
Brian Paul530df582008-07-03 16:21:11 -06001129 struct gl_shader *sh;
1130 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001131 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001132 return;
1133 }
Brian65a18442006-12-19 18:46:56 -07001134 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001135}
1136
1137
Brian Paul5b982362008-08-06 13:07:09 -06001138static void
1139get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1140{
1141 switch (type) {
1142 case GL_FLOAT_MAT2:
1143 *rows = *cols = 2;
1144 break;
1145 case GL_FLOAT_MAT2x3:
1146 *rows = 3;
1147 *cols = 2;
1148 break;
1149 case GL_FLOAT_MAT2x4:
1150 *rows = 4;
1151 *cols = 2;
1152 break;
1153 case GL_FLOAT_MAT3:
1154 *rows = 3;
1155 *cols = 3;
1156 break;
1157 case GL_FLOAT_MAT3x2:
1158 *rows = 2;
1159 *cols = 3;
1160 break;
1161 case GL_FLOAT_MAT3x4:
1162 *rows = 4;
1163 *cols = 3;
1164 break;
1165 case GL_FLOAT_MAT4:
1166 *rows = 4;
1167 *cols = 4;
1168 break;
1169 case GL_FLOAT_MAT4x2:
1170 *rows = 2;
1171 *cols = 4;
1172 break;
1173 case GL_FLOAT_MAT4x3:
1174 *rows = 3;
1175 *cols = 4;
1176 break;
1177 default:
1178 *rows = *cols = 0;
1179 }
1180}
1181
1182
1183/**
1184 * Determine the number of rows and columns occupied by a uniform
Brian Paulea9568d2008-09-16 08:55:54 -06001185 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
1186 * the number of rows = 1 and cols = number of elements in the vector.
Brian Paul5b982362008-08-06 13:07:09 -06001187 */
1188static void
1189get_uniform_rows_cols(const struct gl_program_parameter *p,
1190 GLint *rows, GLint *cols)
1191{
1192 get_matrix_dims(p->DataType, rows, cols);
1193 if (*rows == 0 && *cols == 0) {
1194 /* not a matrix type, probably a float or vector */
Brian Paulea9568d2008-09-16 08:55:54 -06001195 if (p->Size <= 4) {
1196 *rows = 1;
1197 *cols = p->Size;
1198 }
1199 else {
1200 *rows = p->Size / 4 + 1;
1201 if (p->Size % 4 == 0)
1202 *cols = 4;
1203 else
1204 *cols = p->Size % 4;
1205 }
Brian Paul5b982362008-08-06 13:07:09 -06001206 }
1207}
1208
1209
Brian5b01c5e2006-12-19 18:02:03 -07001210/**
Brian Paul4ef7a932009-02-11 09:03:16 -07001211 * Helper for get_uniform[fi]v() functions.
1212 * Given a shader program name and uniform location, return a pointer
1213 * to the shader program and return the program parameter position.
Brian5b01c5e2006-12-19 18:02:03 -07001214 */
Brian Paul4ef7a932009-02-11 09:03:16 -07001215static void
1216lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
1217 struct gl_program **progOut, GLint *paramPosOut)
Brian5b01c5e2006-12-19 18:02:03 -07001218{
Brian65a18442006-12-19 18:46:56 -07001219 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001220 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian Paul4ef7a932009-02-11 09:03:16 -07001221 struct gl_program *prog = NULL;
1222 GLint progPos = -1;
Brian Paulade50832008-05-14 16:09:46 -06001223
Brian Paul4ef7a932009-02-11 09:03:16 -07001224 /* if shProg is NULL, we'll have already recorded an error */
1225
1226 if (shProg) {
1227 if (!shProg->Uniforms ||
1228 location < 0 ||
1229 location >= (GLint) shProg->Uniforms->NumUniforms) {
1230 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1231 }
1232 else {
1233 /* OK, find the gl_program and program parameter location */
Brian Paulade50832008-05-14 16:09:46 -06001234 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1235 if (progPos >= 0) {
1236 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001237 }
Brian Paulade50832008-05-14 16:09:46 -06001238 else {
1239 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1240 if (progPos >= 0) {
1241 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001242 }
Brian Paulade50832008-05-14 16:09:46 -06001243 }
Brian5b01c5e2006-12-19 18:02:03 -07001244 }
1245 }
Brian Paul4ef7a932009-02-11 09:03:16 -07001246
1247 *progOut = prog;
1248 *paramPosOut = progPos;
Brian Paul2be54a82008-07-08 16:17:04 -06001249}
1250
1251
1252/**
1253 * Called via ctx->Driver.GetUniformfv().
1254 */
1255static void
1256_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1257 GLfloat *params)
1258{
Brian Paul4ef7a932009-02-11 09:03:16 -07001259 struct gl_program *prog;
1260 GLint paramPos;
1261
1262 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1263
1264 if (prog) {
1265 const struct gl_program_parameter *p =
1266 &prog->Parameters->Parameters[paramPos];
1267 GLint rows, cols, i, j, k;
1268
1269 get_uniform_rows_cols(p, &rows, &cols);
1270
1271 k = 0;
1272 for (i = 0; i < rows; i++) {
1273 for (j = 0; j < cols; j++ ) {
1274 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
1275 }
1276 }
1277 }
Brian Paul2be54a82008-07-08 16:17:04 -06001278}
1279
1280
1281/**
1282 * Called via ctx->Driver.GetUniformiv().
Brian Paul4ef7a932009-02-11 09:03:16 -07001283 * \sa _mesa_get_uniformfv, only difference is a cast.
Brian Paul2be54a82008-07-08 16:17:04 -06001284 */
1285static void
1286_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1287 GLint *params)
1288{
Brian Paul4ef7a932009-02-11 09:03:16 -07001289 struct gl_program *prog;
1290 GLint paramPos;
1291
1292 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1293
1294 if (prog) {
1295 const struct gl_program_parameter *p =
1296 &prog->Parameters->Parameters[paramPos];
1297 GLint rows, cols, i, j, k;
1298
1299 get_uniform_rows_cols(p, &rows, &cols);
1300
1301 k = 0;
1302 for (i = 0; i < rows; i++) {
1303 for (j = 0; j < cols; j++ ) {
1304 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
1305 }
1306 }
Brian Paul2be54a82008-07-08 16:17:04 -06001307 }
Brian5b01c5e2006-12-19 18:02:03 -07001308}
1309
1310
1311/**
Brian Pauleda291e2008-08-06 16:26:47 -06001312 * The value returned by GetUniformLocation actually encodes two things:
1313 * 1. the index into the prog->Uniforms[] array for the uniform
1314 * 2. an offset in the prog->ParameterValues[] array for specifying array
1315 * elements or structure fields.
1316 * This function merges those two values.
1317 */
1318static void
1319merge_location_offset(GLint *location, GLint offset)
1320{
1321 *location = *location | (offset << 16);
1322}
1323
1324
1325/**
1326 * Seperate the uniform location and parameter offset. See above.
1327 */
1328static void
1329split_location_offset(GLint *location, GLint *offset)
1330{
1331 *offset = (*location >> 16);
1332 *location = *location & 0xffff;
1333}
1334
1335
1336/**
Brian5b01c5e2006-12-19 18:02:03 -07001337 * Called via ctx->Driver.GetUniformLocation().
Brian Pauleda291e2008-08-06 16:26:47 -06001338 *
1339 * The return value will encode two values, the uniform location and an
1340 * offset (used for arrays, structs).
Brian5b01c5e2006-12-19 18:02:03 -07001341 */
Brian Paulfd59f192008-05-18 16:04:55 -06001342static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001343_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1344{
Brian Pauleda291e2008-08-06 16:26:47 -06001345 GLint offset = 0, location = -1;
1346
Brian Paul530df582008-07-03 16:21:11 -06001347 struct gl_shader_program *shProg =
1348 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1349
Brian Paulade50832008-05-14 16:09:46 -06001350 if (!shProg)
1351 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001352
Brian Paule06565b2008-07-04 09:58:55 -06001353 if (shProg->LinkStatus == GL_FALSE) {
1354 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1355 return -1;
1356 }
1357
Brian Paul530df582008-07-03 16:21:11 -06001358 /* XXX we should return -1 if the uniform was declared, but not
1359 * actually used.
1360 */
1361
Brian Pauleda291e2008-08-06 16:26:47 -06001362 /* XXX we need to be able to parse uniform names for structs and arrays
1363 * such as:
1364 * mymatrix[1]
1365 * mystruct.field1
1366 */
1367
1368 {
1369 /* handle 1-dimension arrays here... */
1370 char *c = strchr(name, '[');
1371 if (c) {
1372 /* truncate name at [ */
1373 const GLint len = c - name;
1374 GLchar *newName = _mesa_malloc(len + 1);
1375 if (!newName)
1376 return -1; /* out of mem */
1377 _mesa_memcpy(newName, name, len);
1378 newName[len] = 0;
1379
1380 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1381 if (location >= 0) {
1382 const GLint element = _mesa_atoi(c + 1);
1383 if (element > 0) {
1384 /* get type of the uniform array element */
1385 struct gl_program_parameter *p;
1386 p = get_uniform_parameter(shProg, location);
1387 if (p) {
1388 GLint rows, cols;
1389 get_matrix_dims(p->DataType, &rows, &cols);
1390 if (rows < 1)
1391 rows = 1;
1392 offset = element * rows;
1393 }
1394 }
1395 }
1396
1397 _mesa_free(newName);
1398 }
1399 }
1400
1401 if (location < 0) {
1402 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1403 }
1404
1405 if (location >= 0) {
1406 merge_location_offset(&location, offset);
1407 }
1408
1409 return location;
Brian5b01c5e2006-12-19 18:02:03 -07001410}
1411
1412
Brian34ae99d2006-12-18 08:28:54 -07001413
Brian5b01c5e2006-12-19 18:02:03 -07001414/**
1415 * Called via ctx->Driver.ShaderSource()
1416 */
Brian Paulfd59f192008-05-18 16:04:55 -06001417static void
Brian5b01c5e2006-12-19 18:02:03 -07001418_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001419{
Brian Paul530df582008-07-03 16:21:11 -06001420 struct gl_shader *sh;
1421
1422 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1423 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001424 return;
Brian34ae99d2006-12-18 08:28:54 -07001425
Brian34ae99d2006-12-18 08:28:54 -07001426 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001427 if (sh->Source) {
1428 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001429 }
Brian65a18442006-12-19 18:46:56 -07001430 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001431 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001432}
1433
1434
Brian5b01c5e2006-12-19 18:02:03 -07001435/**
1436 * Called via ctx->Driver.CompileShader()
1437 */
Brian Paulfd59f192008-05-18 16:04:55 -06001438static void
Brian5b01c5e2006-12-19 18:02:03 -07001439_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001440{
Brian Paul530df582008-07-03 16:21:11 -06001441 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001442
Brian Paul530df582008-07-03 16:21:11 -06001443 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1444 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001445 return;
Brian34ae99d2006-12-18 08:28:54 -07001446
Brian Paulcb136e02009-01-22 10:34:15 -07001447 /* this call will set the sh->CompileStatus field to indicate if
1448 * compilation was successful.
1449 */
1450 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001451}
1452
1453
Brian5b01c5e2006-12-19 18:02:03 -07001454/**
1455 * Called via ctx->Driver.LinkProgram()
1456 */
Brian Paulfd59f192008-05-18 16:04:55 -06001457static void
Brian5b01c5e2006-12-19 18:02:03 -07001458_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001459{
Brian65a18442006-12-19 18:46:56 -07001460 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001461
Brian Paul530df582008-07-03 16:21:11 -06001462 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1463 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001464 return;
Brian34ae99d2006-12-18 08:28:54 -07001465
Briandf43fb62008-05-06 23:08:51 -06001466 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1467
Brianc1771912007-02-16 09:56:19 -07001468 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001469}
1470
1471
1472/**
Brian5b01c5e2006-12-19 18:02:03 -07001473 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001474 */
Brian5b01c5e2006-12-19 18:02:03 -07001475void
1476_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001477{
Brian3c008a02007-04-12 15:22:32 -06001478 struct gl_shader_program *shProg;
1479
Brian00d63aa2007-02-03 11:35:02 -07001480 if (ctx->Shader.CurrentProgram &&
1481 ctx->Shader.CurrentProgram->Name == program) {
1482 /* no-op */
1483 return;
1484 }
1485
1486 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1487
Brian5b01c5e2006-12-19 18:02:03 -07001488 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001489 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001490 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001491 return;
1492 }
1493 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001494 _mesa_error(ctx, GL_INVALID_OPERATION,
1495 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001496 return;
1497 }
Brian5b01c5e2006-12-19 18:02:03 -07001498 }
1499 else {
Brian3c008a02007-04-12 15:22:32 -06001500 shProg = NULL;
1501 }
1502
1503 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001504}
Brian34ae99d2006-12-18 08:28:54 -07001505
Brian5b01c5e2006-12-19 18:02:03 -07001506
Brian Paulade50832008-05-14 16:09:46 -06001507
1508/**
Brian Paul517401a2008-11-06 15:04:11 -07001509 * Update the vertex/fragment program's TexturesUsed array.
1510 *
1511 * This needs to be called after glUniform(set sampler var) is called.
1512 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1513 * particular texture unit. We know the sampler's texture target
1514 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1515 * set by glUniform() calls.
1516 *
1517 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1518 * information to update the prog->TexturesUsed[] values.
1519 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1520 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1521 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001522 */
Brian Paul517401a2008-11-06 15:04:11 -07001523void
1524_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001525{
1526 GLuint s;
1527
1528 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1529
1530 for (s = 0; s < MAX_SAMPLERS; s++) {
1531 if (prog->SamplersUsed & (1 << s)) {
1532 GLuint u = prog->SamplerUnits[s];
1533 GLuint t = prog->SamplerTargets[s];
1534 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1535 prog->TexturesUsed[u] |= (1 << t);
1536 }
1537 }
1538}
1539
1540
1541/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001542 * Check if the type given by userType is allowed to set a uniform of the
1543 * target type. Generally, equivalence is required, but setting Boolean
1544 * uniforms can be done with glUniformiv or glUniformfv.
1545 */
1546static GLboolean
1547compatible_types(GLenum userType, GLenum targetType)
1548{
1549 if (userType == targetType)
1550 return GL_TRUE;
1551
1552 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1553 return GL_TRUE;
1554
1555 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1556 userType == GL_INT_VEC2))
1557 return GL_TRUE;
1558
1559 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1560 userType == GL_INT_VEC3))
1561 return GL_TRUE;
1562
1563 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1564 userType == GL_INT_VEC4))
1565 return GL_TRUE;
1566
Brianb36749d2008-07-21 20:42:05 -06001567 if (is_sampler_type(targetType) && userType == GL_INT)
1568 return GL_TRUE;
1569
Brian Paulffbc66b2008-07-21 13:58:50 -06001570 return GL_FALSE;
1571}
1572
1573
1574/**
Brian Paulade50832008-05-14 16:09:46 -06001575 * Set the value of a program's uniform variable.
1576 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001577 * \param index the index of the program parameter for the uniform
1578 * \param offset additional parameter slot offset (for arrays)
Brian Paulc4ffbf02009-02-18 17:46:00 -07001579 * \param type the incoming datatype of 'values'
Brian Paulade50832008-05-14 16:09:46 -06001580 * \param count the number of uniforms to set
Brian Paulc4ffbf02009-02-18 17:46:00 -07001581 * \param elems number of elements per uniform (1, 2, 3 or 4)
1582 * \param values the new values, of datatype 'type'
Brian Paulade50832008-05-14 16:09:46 -06001583 */
1584static void
Brian Pauleda291e2008-08-06 16:26:47 -06001585set_program_uniform(GLcontext *ctx, struct gl_program *program,
1586 GLint index, GLint offset,
1587 GLenum type, GLsizei count, GLint elems,
1588 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001589{
Brian Paul949e7382008-11-05 09:17:55 -07001590 struct gl_program_parameter *param =
1591 &program->Parameters->Parameters[index];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001592 const GLboolean isUniformBool = is_boolean_type(param->DataType);
1593 const GLboolean areIntValues = is_integer_type(type);
Brian Paul949e7382008-11-05 09:17:55 -07001594
Brian Pauleda291e2008-08-06 16:26:47 -06001595 assert(offset >= 0);
Brian Paulc4ffbf02009-02-18 17:46:00 -07001596 assert(elems >= 1);
1597 assert(elems <= 4);
Brian Pauleda291e2008-08-06 16:26:47 -06001598
Brian Paul949e7382008-11-05 09:17:55 -07001599 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001600 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1601 return;
1602 }
1603
Michal Krolc5c71302008-08-07 16:23:15 +02001604 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001605 /* out of bounds! */
1606 return;
1607 }
1608
Brian Paul949e7382008-11-05 09:17:55 -07001609 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001610 /* This controls which texture unit which is used by a sampler */
1611 GLuint texUnit, sampler;
Brian Paul2b4f0212009-02-11 09:12:34 -07001612 GLint i;
Brian Paulade50832008-05-14 16:09:46 -06001613
1614 /* data type for setting samplers must be int */
Brian Paul2b4f0212009-02-11 09:12:34 -07001615 if (type != GL_INT) {
Brian Paulade50832008-05-14 16:09:46 -06001616 _mesa_error(ctx, GL_INVALID_OPERATION,
1617 "glUniform(only glUniform1i can be used "
1618 "to set sampler uniforms)");
1619 return;
1620 }
1621
Brian Paul2b4f0212009-02-11 09:12:34 -07001622 /* XXX arrays of samplers haven't been tested much, but it's not a
1623 * common thing...
1624 */
1625 for (i = 0; i < count; i++) {
1626 sampler = (GLuint) program->Parameters->ParameterValues[index + i][0];
1627 texUnit = ((GLuint *) values)[i];
Brian Paulade50832008-05-14 16:09:46 -06001628
Brian Paul2b4f0212009-02-11 09:12:34 -07001629 /* check that the sampler (tex unit index) is legal */
1630 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1631 _mesa_error(ctx, GL_INVALID_VALUE,
1632 "glUniform1(invalid sampler/tex unit index)");
1633 return;
1634 }
1635
1636 /* This maps a sampler to a texture unit: */
1637 if (sampler < MAX_SAMPLERS) {
1638 program->SamplerUnits[sampler] = texUnit;
1639 }
Brian Paulade50832008-05-14 16:09:46 -06001640 }
1641
Brian Paul517401a2008-11-06 15:04:11 -07001642 _mesa_update_shader_textures_used(program);
Brian Paulade50832008-05-14 16:09:46 -06001643
1644 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1645 }
1646 else {
1647 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001648 GLsizei k, i;
Brian Paul2c1ea072009-02-11 08:46:21 -07001649 const GLint slots = (param->Size + 3) / 4;
1650 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paulade50832008-05-14 16:09:46 -06001651
Brian Paul2c1ea072009-02-11 08:46:21 -07001652 if (param->Size > typeSize) {
1653 /* an array */
1654 /* we'll ignore extra data below */
1655 }
1656 else {
1657 /* non-array: count must be one */
1658 if (count != 1) {
1659 _mesa_error(ctx, GL_INVALID_OPERATION,
1660 "glUniform(uniform is not an array)");
1661 return;
1662 }
Brian Paulade50832008-05-14 16:09:46 -06001663 }
1664
Brian Paulc4ffbf02009-02-18 17:46:00 -07001665 /* loop over number of array elements */
Brian Paulade50832008-05-14 16:09:46 -06001666 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001667 GLfloat *uniformVal;
1668
Brian Paulb9d8f712009-02-18 17:40:44 -07001669 if (offset + k >= slots) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001670 /* Extra array data is ignored */
1671 break;
1672 }
1673
Brian Paulc4ffbf02009-02-18 17:46:00 -07001674 /* uniformVal (the destination) is always float[4] */
Brian Paul2c1ea072009-02-11 08:46:21 -07001675 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001676
1677 if (areIntValues) {
1678 /* convert user's ints to floats */
Brian Paulade50832008-05-14 16:09:46 -06001679 const GLint *iValues = ((const GLint *) values) + k * elems;
1680 for (i = 0; i < elems; i++) {
1681 uniformVal[i] = (GLfloat) iValues[i];
1682 }
1683 }
1684 else {
1685 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1686 for (i = 0; i < elems; i++) {
1687 uniformVal[i] = fValues[i];
1688 }
1689 }
Brian Pauleda291e2008-08-06 16:26:47 -06001690
1691 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paulc4ffbf02009-02-18 17:46:00 -07001692 if (isUniformBool) {
Brian Pauleda291e2008-08-06 16:26:47 -06001693 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001694 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001695 }
1696 }
Brian Paulade50832008-05-14 16:09:46 -06001697 }
1698 }
1699}
1700
1701
Brian5b01c5e2006-12-19 18:02:03 -07001702/**
1703 * Called via ctx->Driver.Uniform().
1704 */
Brian Paulfd59f192008-05-18 16:04:55 -06001705static void
Brian5b01c5e2006-12-19 18:02:03 -07001706_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1707 const GLvoid *values, GLenum type)
1708{
Brian3a8e2772006-12-20 17:19:16 -07001709 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001710 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001711 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001712 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001713
1714 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001715 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001716 return;
1717 }
1718
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001719 if (location == -1)
1720 return; /* The standard specifies this as a no-op */
1721
Brian Paul234f03e2009-02-11 09:05:08 -07001722 if (location < -1) {
1723 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
1724 return;
1725 }
1726
Brian Pauleda291e2008-08-06 16:26:47 -06001727 split_location_offset(&location, &offset);
1728
Brian Paulade50832008-05-14 16:09:46 -06001729 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1730 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001731 return;
1732 }
1733
Brian52363952007-03-13 16:50:24 -06001734 if (count < 0) {
1735 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1736 return;
1737 }
1738
Brian98650bd2007-03-13 16:32:48 -06001739 switch (type) {
1740 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001741 basicType = GL_FLOAT;
1742 elems = 1;
1743 break;
Brian98650bd2007-03-13 16:32:48 -06001744 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001745 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001746 elems = 1;
1747 break;
1748 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001749 basicType = GL_FLOAT;
1750 elems = 2;
1751 break;
Brian98650bd2007-03-13 16:32:48 -06001752 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001753 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001754 elems = 2;
1755 break;
1756 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001757 basicType = GL_FLOAT;
1758 elems = 3;
1759 break;
Brian98650bd2007-03-13 16:32:48 -06001760 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001761 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001762 elems = 3;
1763 break;
1764 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001765 basicType = GL_FLOAT;
1766 elems = 4;
1767 break;
Brian98650bd2007-03-13 16:32:48 -06001768 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001769 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001770 elems = 4;
1771 break;
1772 default:
1773 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1774 return;
Brian89dc4852007-01-04 14:35:44 -07001775 }
Brian98650bd2007-03-13 16:32:48 -06001776
Brian Paulade50832008-05-14 16:09:46 -06001777 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001778
Brian Paul2d76a0d2008-11-10 12:33:17 -07001779 uniform = &shProg->Uniforms->Uniforms[location];
1780
Brian Paule01a03d2009-02-06 10:21:36 -07001781 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1782 GLint i;
1783 _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
1784 shProg->Name, uniform->Name, location);
1785 if (basicType == GL_INT) {
1786 const GLint *v = (const GLint *) values;
1787 for (i = 0; i < count * elems; i++) {
1788 _mesa_printf("%d ", v[i]);
1789 }
1790 }
1791 else {
1792 const GLfloat *v = (const GLfloat *) values;
1793 for (i = 0; i < count * elems; i++) {
1794 _mesa_printf("%g ", v[i]);
1795 }
1796 }
1797 _mesa_printf("\n");
1798 }
1799
Brian Paulade50832008-05-14 16:09:46 -06001800 /* A uniform var may be used by both a vertex shader and a fragment
1801 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001802 */
Brian Paulade50832008-05-14 16:09:46 -06001803 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001804 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001805 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001806 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001807 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001808 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001809 }
Brian5b01c5e2006-12-19 18:02:03 -07001810 }
Brian5cf73262007-01-05 16:02:45 -07001811
Brian Paulade50832008-05-14 16:09:46 -06001812 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001813 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001814 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001815 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001816 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001817 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06001818 }
1819 }
Brian Paul949e7382008-11-05 09:17:55 -07001820
Brian Paul2d76a0d2008-11-10 12:33:17 -07001821 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06001822}
1823
1824
Brian Pauleda291e2008-08-06 16:26:47 -06001825/**
1826 * Set a matrix-valued program parameter.
1827 */
Brian Paulade50832008-05-14 16:09:46 -06001828static void
1829set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06001830 GLuint index, GLuint offset,
1831 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001832 GLboolean transpose, const GLfloat *values)
1833{
Brian Paulffbc66b2008-07-21 13:58:50 -06001834 GLuint mat, row, col;
Brian Pauleda291e2008-08-06 16:26:47 -06001835 GLuint dst = index + offset, src = 0;
Brian Paulffbc66b2008-07-21 13:58:50 -06001836 GLint nr, nc;
1837
1838 /* check that the number of rows, columns is correct */
Brian Pauleda291e2008-08-06 16:26:47 -06001839 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06001840 if (rows != nr || cols != nc) {
1841 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06001842 "glUniformMatrix(matrix size mismatch)");
1843 return;
1844 }
1845
1846 if (index + offset > program->Parameters->Size) {
1847 /* out of bounds! */
Brian Paulffbc66b2008-07-21 13:58:50 -06001848 return;
1849 }
1850
Brian Paulade50832008-05-14 16:09:46 -06001851 /*
1852 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001853 * the rows. So, the loops below look a little funny.
1854 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001855 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001856
1857 /* loop over matrices */
1858 for (mat = 0; mat < count; mat++) {
1859
1860 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001861 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001862 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001863 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001864 if (transpose) {
1865 v[row] = values[src + row * cols + col];
1866 }
1867 else {
1868 v[row] = values[src + col * rows + row];
1869 }
Brian Paulade50832008-05-14 16:09:46 -06001870 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001871 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001872 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001873
1874 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001875 }
Brian34ae99d2006-12-18 08:28:54 -07001876}
1877
1878
1879/**
Brian5b01c5e2006-12-19 18:02:03 -07001880 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001881 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001882 */
Brian Paulfd59f192008-05-18 16:04:55 -06001883static void
Brian5b01c5e2006-12-19 18:02:03 -07001884_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1885 GLenum matrixType, GLint location, GLsizei count,
1886 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001887{
Brian3a8e2772006-12-20 17:19:16 -07001888 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001889 struct gl_uniform *uniform;
1890 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06001891
Brian3a8e2772006-12-20 17:19:16 -07001892 if (!shProg || !shProg->LinkStatus) {
1893 _mesa_error(ctx, GL_INVALID_OPERATION,
1894 "glUniformMatrix(program not linked)");
1895 return;
1896 }
Brian Paulade50832008-05-14 16:09:46 -06001897
Bruce Merry89b80322007-12-21 15:20:17 +02001898 if (location == -1)
1899 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001900
Brian Paul234f03e2009-02-11 09:05:08 -07001901 if (location < -1) {
1902 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1903 return;
1904 }
1905
Brian Pauleda291e2008-08-06 16:26:47 -06001906 split_location_offset(&location, &offset);
1907
Brian Paul016701f2008-07-29 17:43:35 -06001908 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001909 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001910 return;
1911 }
Brian34ae99d2006-12-18 08:28:54 -07001912 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001913 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001914 return;
1915 }
1916
1917 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1918
Brian Paul2d76a0d2008-11-10 12:33:17 -07001919 uniform = &shProg->Uniforms->Uniforms[location];
1920
Brian Paulade50832008-05-14 16:09:46 -06001921 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001922 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001923 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001924 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001925 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001926 index, offset,
1927 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001928 }
Brian Paulade50832008-05-14 16:09:46 -06001929 }
1930
1931 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001932 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001933 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001934 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001935 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001936 index, offset,
1937 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001938 }
Brian34ae99d2006-12-18 08:28:54 -07001939 }
Brian Paul949e7382008-11-05 09:17:55 -07001940
Brian Paul2d76a0d2008-11-10 12:33:17 -07001941 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001942}
1943
1944
Brian Paulfd59f192008-05-18 16:04:55 -06001945static void
Brian5b01c5e2006-12-19 18:02:03 -07001946_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001947{
Brian65a18442006-12-19 18:46:56 -07001948 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001949
1950 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001951 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001952 return;
1953 }
1954
Brian Paulbc985b52008-07-21 14:16:07 -06001955 if (!shProg->LinkStatus) {
1956 shProg->Validated = GL_FALSE;
1957 return;
1958 }
1959
1960 /* From the GL spec, a program is invalid if any of these are true:
1961
Brian5b01c5e2006-12-19 18:02:03 -07001962 any two active samplers in the current program object are of
1963 different types, but refer to the same texture image unit,
1964
1965 any active sampler in the current program object refers to a texture
1966 image unit where fixed-function fragment processing accesses a
1967 texture target that does not match the sampler type, or
1968
1969 the sum of the number of active samplers in the program and the
1970 number of texture image units enabled for fixed-function fragment
1971 processing exceeds the combined limit on the total number of texture
1972 image units allowed.
1973 */
Brian Paulbc985b52008-07-21 14:16:07 -06001974
1975 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001976}
Brian Paulfd59f192008-05-18 16:04:55 -06001977
1978
1979/**
1980 * Plug in Mesa's GLSL functions into the device driver function table.
1981 */
1982void
1983_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1984{
1985 driver->AttachShader = _mesa_attach_shader;
1986 driver->BindAttribLocation = _mesa_bind_attrib_location;
1987 driver->CompileShader = _mesa_compile_shader;
1988 driver->CreateProgram = _mesa_create_program;
1989 driver->CreateShader = _mesa_create_shader;
1990 driver->DeleteProgram2 = _mesa_delete_program2;
1991 driver->DeleteShader = _mesa_delete_shader;
1992 driver->DetachShader = _mesa_detach_shader;
1993 driver->GetActiveAttrib = _mesa_get_active_attrib;
1994 driver->GetActiveUniform = _mesa_get_active_uniform;
1995 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1996 driver->GetAttribLocation = _mesa_get_attrib_location;
1997 driver->GetHandle = _mesa_get_handle;
1998 driver->GetProgramiv = _mesa_get_programiv;
1999 driver->GetProgramInfoLog = _mesa_get_program_info_log;
2000 driver->GetShaderiv = _mesa_get_shaderiv;
2001 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
2002 driver->GetShaderSource = _mesa_get_shader_source;
2003 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06002004 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06002005 driver->GetUniformLocation = _mesa_get_uniform_location;
2006 driver->IsProgram = _mesa_is_program;
2007 driver->IsShader = _mesa_is_shader;
2008 driver->LinkProgram = _mesa_link_program;
2009 driver->ShaderSource = _mesa_shader_source;
2010 driver->Uniform = _mesa_uniform;
2011 driver->UniformMatrix = _mesa_uniform_matrix;
2012 driver->UseProgram = _mesa_use_program;
2013 driver->ValidateProgram = _mesa_validate_program;
2014}