blob: 9900acc75b4bd4ac41b57ab8c0bc3fb25d805495 [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 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001498
1499 /* debug code */
1500 if (0) {
1501 GLuint i;
1502 _mesa_printf("Use Shader %u\n", shProg->Name);
1503 for (i = 0; i < shProg->NumShaders; i++) {
1504 _mesa_printf(" shader %u, type 0x%x\n",
1505 shProg->Shaders[i]->Name,
1506 shProg->Shaders[i]->Type);
1507 }
1508 }
Brian5b01c5e2006-12-19 18:02:03 -07001509 }
1510 else {
Brian3c008a02007-04-12 15:22:32 -06001511 shProg = NULL;
1512 }
1513
1514 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001515}
Brian34ae99d2006-12-18 08:28:54 -07001516
Brian5b01c5e2006-12-19 18:02:03 -07001517
Brian Paulade50832008-05-14 16:09:46 -06001518
1519/**
Brian Paul517401a2008-11-06 15:04:11 -07001520 * Update the vertex/fragment program's TexturesUsed array.
1521 *
1522 * This needs to be called after glUniform(set sampler var) is called.
1523 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1524 * particular texture unit. We know the sampler's texture target
1525 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1526 * set by glUniform() calls.
1527 *
1528 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1529 * information to update the prog->TexturesUsed[] values.
1530 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1531 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1532 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001533 */
Brian Paul517401a2008-11-06 15:04:11 -07001534void
1535_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001536{
1537 GLuint s;
1538
1539 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1540
1541 for (s = 0; s < MAX_SAMPLERS; s++) {
1542 if (prog->SamplersUsed & (1 << s)) {
1543 GLuint u = prog->SamplerUnits[s];
1544 GLuint t = prog->SamplerTargets[s];
1545 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1546 prog->TexturesUsed[u] |= (1 << t);
1547 }
1548 }
1549}
1550
1551
1552/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001553 * Check if the type given by userType is allowed to set a uniform of the
1554 * target type. Generally, equivalence is required, but setting Boolean
1555 * uniforms can be done with glUniformiv or glUniformfv.
1556 */
1557static GLboolean
1558compatible_types(GLenum userType, GLenum targetType)
1559{
1560 if (userType == targetType)
1561 return GL_TRUE;
1562
1563 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1564 return GL_TRUE;
1565
1566 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1567 userType == GL_INT_VEC2))
1568 return GL_TRUE;
1569
1570 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1571 userType == GL_INT_VEC3))
1572 return GL_TRUE;
1573
1574 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1575 userType == GL_INT_VEC4))
1576 return GL_TRUE;
1577
Brianb36749d2008-07-21 20:42:05 -06001578 if (is_sampler_type(targetType) && userType == GL_INT)
1579 return GL_TRUE;
1580
Brian Paulffbc66b2008-07-21 13:58:50 -06001581 return GL_FALSE;
1582}
1583
1584
1585/**
Brian Paulade50832008-05-14 16:09:46 -06001586 * Set the value of a program's uniform variable.
1587 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001588 * \param index the index of the program parameter for the uniform
1589 * \param offset additional parameter slot offset (for arrays)
Brian Paulc4ffbf02009-02-18 17:46:00 -07001590 * \param type the incoming datatype of 'values'
Brian Paulade50832008-05-14 16:09:46 -06001591 * \param count the number of uniforms to set
Brian Paulc4ffbf02009-02-18 17:46:00 -07001592 * \param elems number of elements per uniform (1, 2, 3 or 4)
1593 * \param values the new values, of datatype 'type'
Brian Paulade50832008-05-14 16:09:46 -06001594 */
1595static void
Brian Pauleda291e2008-08-06 16:26:47 -06001596set_program_uniform(GLcontext *ctx, struct gl_program *program,
1597 GLint index, GLint offset,
1598 GLenum type, GLsizei count, GLint elems,
1599 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001600{
Brian Paul949e7382008-11-05 09:17:55 -07001601 struct gl_program_parameter *param =
1602 &program->Parameters->Parameters[index];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001603 const GLboolean isUniformBool = is_boolean_type(param->DataType);
1604 const GLboolean areIntValues = is_integer_type(type);
Brian Paul949e7382008-11-05 09:17:55 -07001605
Brian Pauleda291e2008-08-06 16:26:47 -06001606 assert(offset >= 0);
Brian Paulc4ffbf02009-02-18 17:46:00 -07001607 assert(elems >= 1);
1608 assert(elems <= 4);
Brian Pauleda291e2008-08-06 16:26:47 -06001609
Brian Paul949e7382008-11-05 09:17:55 -07001610 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001611 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1612 return;
1613 }
1614
Michal Krolc5c71302008-08-07 16:23:15 +02001615 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001616 /* out of bounds! */
1617 return;
1618 }
1619
Brian Paul949e7382008-11-05 09:17:55 -07001620 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001621 /* This controls which texture unit which is used by a sampler */
1622 GLuint texUnit, sampler;
Brian Paul2b4f0212009-02-11 09:12:34 -07001623 GLint i;
Brian Paulade50832008-05-14 16:09:46 -06001624
1625 /* data type for setting samplers must be int */
Brian Paul2b4f0212009-02-11 09:12:34 -07001626 if (type != GL_INT) {
Brian Paulade50832008-05-14 16:09:46 -06001627 _mesa_error(ctx, GL_INVALID_OPERATION,
1628 "glUniform(only glUniform1i can be used "
1629 "to set sampler uniforms)");
1630 return;
1631 }
1632
Brian Paul2b4f0212009-02-11 09:12:34 -07001633 /* XXX arrays of samplers haven't been tested much, but it's not a
1634 * common thing...
1635 */
1636 for (i = 0; i < count; i++) {
1637 sampler = (GLuint) program->Parameters->ParameterValues[index + i][0];
1638 texUnit = ((GLuint *) values)[i];
Brian Paulade50832008-05-14 16:09:46 -06001639
Brian Paul2b4f0212009-02-11 09:12:34 -07001640 /* check that the sampler (tex unit index) is legal */
1641 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1642 _mesa_error(ctx, GL_INVALID_VALUE,
1643 "glUniform1(invalid sampler/tex unit index)");
1644 return;
1645 }
1646
1647 /* This maps a sampler to a texture unit: */
1648 if (sampler < MAX_SAMPLERS) {
1649 program->SamplerUnits[sampler] = texUnit;
1650 }
Brian Paulade50832008-05-14 16:09:46 -06001651 }
1652
Brian Paul517401a2008-11-06 15:04:11 -07001653 _mesa_update_shader_textures_used(program);
Brian Paulade50832008-05-14 16:09:46 -06001654
1655 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1656 }
1657 else {
1658 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001659 GLsizei k, i;
Brian Paul2c1ea072009-02-11 08:46:21 -07001660 const GLint slots = (param->Size + 3) / 4;
1661 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paulade50832008-05-14 16:09:46 -06001662
Brian Paul2c1ea072009-02-11 08:46:21 -07001663 if (param->Size > typeSize) {
1664 /* an array */
1665 /* we'll ignore extra data below */
1666 }
1667 else {
1668 /* non-array: count must be one */
1669 if (count != 1) {
1670 _mesa_error(ctx, GL_INVALID_OPERATION,
1671 "glUniform(uniform is not an array)");
1672 return;
1673 }
Brian Paulade50832008-05-14 16:09:46 -06001674 }
1675
Brian Paulc4ffbf02009-02-18 17:46:00 -07001676 /* loop over number of array elements */
Brian Paulade50832008-05-14 16:09:46 -06001677 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001678 GLfloat *uniformVal;
1679
Brian Paulb9d8f712009-02-18 17:40:44 -07001680 if (offset + k >= slots) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001681 /* Extra array data is ignored */
1682 break;
1683 }
1684
Brian Paulc4ffbf02009-02-18 17:46:00 -07001685 /* uniformVal (the destination) is always float[4] */
Brian Paul2c1ea072009-02-11 08:46:21 -07001686 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001687
1688 if (areIntValues) {
1689 /* convert user's ints to floats */
Brian Paulade50832008-05-14 16:09:46 -06001690 const GLint *iValues = ((const GLint *) values) + k * elems;
1691 for (i = 0; i < elems; i++) {
1692 uniformVal[i] = (GLfloat) iValues[i];
1693 }
1694 }
1695 else {
1696 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1697 for (i = 0; i < elems; i++) {
1698 uniformVal[i] = fValues[i];
1699 }
1700 }
Brian Pauleda291e2008-08-06 16:26:47 -06001701
1702 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paulc4ffbf02009-02-18 17:46:00 -07001703 if (isUniformBool) {
Brian Pauleda291e2008-08-06 16:26:47 -06001704 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001705 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001706 }
1707 }
Brian Paulade50832008-05-14 16:09:46 -06001708 }
1709 }
1710}
1711
1712
Brian5b01c5e2006-12-19 18:02:03 -07001713/**
1714 * Called via ctx->Driver.Uniform().
1715 */
Brian Paulfd59f192008-05-18 16:04:55 -06001716static void
Brian5b01c5e2006-12-19 18:02:03 -07001717_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1718 const GLvoid *values, GLenum type)
1719{
Brian3a8e2772006-12-20 17:19:16 -07001720 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001721 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001722 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001723 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001724
1725 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001726 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001727 return;
1728 }
1729
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001730 if (location == -1)
1731 return; /* The standard specifies this as a no-op */
1732
Brian Paul234f03e2009-02-11 09:05:08 -07001733 if (location < -1) {
1734 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
1735 return;
1736 }
1737
Brian Pauleda291e2008-08-06 16:26:47 -06001738 split_location_offset(&location, &offset);
1739
Brian Paulade50832008-05-14 16:09:46 -06001740 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1741 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001742 return;
1743 }
1744
Brian52363952007-03-13 16:50:24 -06001745 if (count < 0) {
1746 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1747 return;
1748 }
1749
Brian98650bd2007-03-13 16:32:48 -06001750 switch (type) {
1751 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001752 basicType = GL_FLOAT;
1753 elems = 1;
1754 break;
Brian98650bd2007-03-13 16:32:48 -06001755 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001756 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001757 elems = 1;
1758 break;
1759 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001760 basicType = GL_FLOAT;
1761 elems = 2;
1762 break;
Brian98650bd2007-03-13 16:32:48 -06001763 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001764 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001765 elems = 2;
1766 break;
1767 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001768 basicType = GL_FLOAT;
1769 elems = 3;
1770 break;
Brian98650bd2007-03-13 16:32:48 -06001771 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001772 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001773 elems = 3;
1774 break;
1775 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001776 basicType = GL_FLOAT;
1777 elems = 4;
1778 break;
Brian98650bd2007-03-13 16:32:48 -06001779 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001780 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001781 elems = 4;
1782 break;
1783 default:
1784 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1785 return;
Brian89dc4852007-01-04 14:35:44 -07001786 }
Brian98650bd2007-03-13 16:32:48 -06001787
Brian Paulade50832008-05-14 16:09:46 -06001788 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001789
Brian Paul2d76a0d2008-11-10 12:33:17 -07001790 uniform = &shProg->Uniforms->Uniforms[location];
1791
Brian Paule01a03d2009-02-06 10:21:36 -07001792 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1793 GLint i;
1794 _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
1795 shProg->Name, uniform->Name, location);
1796 if (basicType == GL_INT) {
1797 const GLint *v = (const GLint *) values;
1798 for (i = 0; i < count * elems; i++) {
1799 _mesa_printf("%d ", v[i]);
1800 }
1801 }
1802 else {
1803 const GLfloat *v = (const GLfloat *) values;
1804 for (i = 0; i < count * elems; i++) {
1805 _mesa_printf("%g ", v[i]);
1806 }
1807 }
1808 _mesa_printf("\n");
1809 }
1810
Brian Paulade50832008-05-14 16:09:46 -06001811 /* A uniform var may be used by both a vertex shader and a fragment
1812 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001813 */
Brian Paulade50832008-05-14 16:09:46 -06001814 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001815 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001816 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001817 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001818 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001819 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001820 }
Brian5b01c5e2006-12-19 18:02:03 -07001821 }
Brian5cf73262007-01-05 16:02:45 -07001822
Brian Paulade50832008-05-14 16:09:46 -06001823 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001824 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001825 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001826 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001827 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001828 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06001829 }
1830 }
Brian Paul949e7382008-11-05 09:17:55 -07001831
Brian Paul2d76a0d2008-11-10 12:33:17 -07001832 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06001833}
1834
1835
Brian Pauleda291e2008-08-06 16:26:47 -06001836/**
1837 * Set a matrix-valued program parameter.
1838 */
Brian Paulade50832008-05-14 16:09:46 -06001839static void
1840set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06001841 GLuint index, GLuint offset,
1842 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001843 GLboolean transpose, const GLfloat *values)
1844{
Brian Paulffbc66b2008-07-21 13:58:50 -06001845 GLuint mat, row, col;
Brian Pauleda291e2008-08-06 16:26:47 -06001846 GLuint dst = index + offset, src = 0;
Brian Paulffbc66b2008-07-21 13:58:50 -06001847 GLint nr, nc;
1848
1849 /* check that the number of rows, columns is correct */
Brian Pauleda291e2008-08-06 16:26:47 -06001850 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06001851 if (rows != nr || cols != nc) {
1852 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06001853 "glUniformMatrix(matrix size mismatch)");
1854 return;
1855 }
1856
1857 if (index + offset > program->Parameters->Size) {
1858 /* out of bounds! */
Brian Paulffbc66b2008-07-21 13:58:50 -06001859 return;
1860 }
1861
Brian Paulade50832008-05-14 16:09:46 -06001862 /*
1863 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001864 * the rows. So, the loops below look a little funny.
1865 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001866 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001867
1868 /* loop over matrices */
1869 for (mat = 0; mat < count; mat++) {
1870
1871 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001872 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001873 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001874 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001875 if (transpose) {
1876 v[row] = values[src + row * cols + col];
1877 }
1878 else {
1879 v[row] = values[src + col * rows + row];
1880 }
Brian Paulade50832008-05-14 16:09:46 -06001881 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001882 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001883 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001884
1885 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001886 }
Brian34ae99d2006-12-18 08:28:54 -07001887}
1888
1889
1890/**
Brian5b01c5e2006-12-19 18:02:03 -07001891 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001892 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001893 */
Brian Paulfd59f192008-05-18 16:04:55 -06001894static void
Brian5b01c5e2006-12-19 18:02:03 -07001895_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1896 GLenum matrixType, GLint location, GLsizei count,
1897 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001898{
Brian3a8e2772006-12-20 17:19:16 -07001899 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001900 struct gl_uniform *uniform;
1901 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06001902
Brian3a8e2772006-12-20 17:19:16 -07001903 if (!shProg || !shProg->LinkStatus) {
1904 _mesa_error(ctx, GL_INVALID_OPERATION,
1905 "glUniformMatrix(program not linked)");
1906 return;
1907 }
Brian Paulade50832008-05-14 16:09:46 -06001908
Bruce Merry89b80322007-12-21 15:20:17 +02001909 if (location == -1)
1910 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001911
Brian Paul234f03e2009-02-11 09:05:08 -07001912 if (location < -1) {
1913 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1914 return;
1915 }
1916
Brian Pauleda291e2008-08-06 16:26:47 -06001917 split_location_offset(&location, &offset);
1918
Brian Paul016701f2008-07-29 17:43:35 -06001919 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001920 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001921 return;
1922 }
Brian34ae99d2006-12-18 08:28:54 -07001923 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001924 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001925 return;
1926 }
1927
1928 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1929
Brian Paul2d76a0d2008-11-10 12:33:17 -07001930 uniform = &shProg->Uniforms->Uniforms[location];
1931
Brian Paulade50832008-05-14 16:09:46 -06001932 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001933 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001934 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001935 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001936 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001937 index, offset,
1938 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001939 }
Brian Paulade50832008-05-14 16:09:46 -06001940 }
1941
1942 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001943 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001944 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001945 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001946 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001947 index, offset,
1948 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001949 }
Brian34ae99d2006-12-18 08:28:54 -07001950 }
Brian Paul949e7382008-11-05 09:17:55 -07001951
Brian Paul2d76a0d2008-11-10 12:33:17 -07001952 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001953}
1954
1955
Brian Paulfd59f192008-05-18 16:04:55 -06001956static void
Brian5b01c5e2006-12-19 18:02:03 -07001957_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001958{
Brian65a18442006-12-19 18:46:56 -07001959 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001960
1961 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001962 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001963 return;
1964 }
1965
Brian Paulbc985b52008-07-21 14:16:07 -06001966 if (!shProg->LinkStatus) {
1967 shProg->Validated = GL_FALSE;
1968 return;
1969 }
1970
1971 /* From the GL spec, a program is invalid if any of these are true:
1972
Brian5b01c5e2006-12-19 18:02:03 -07001973 any two active samplers in the current program object are of
1974 different types, but refer to the same texture image unit,
1975
1976 any active sampler in the current program object refers to a texture
1977 image unit where fixed-function fragment processing accesses a
1978 texture target that does not match the sampler type, or
1979
1980 the sum of the number of active samplers in the program and the
1981 number of texture image units enabled for fixed-function fragment
1982 processing exceeds the combined limit on the total number of texture
1983 image units allowed.
1984 */
Brian Paulbc985b52008-07-21 14:16:07 -06001985
1986 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001987}
Brian Paulfd59f192008-05-18 16:04:55 -06001988
1989
1990/**
1991 * Plug in Mesa's GLSL functions into the device driver function table.
1992 */
1993void
1994_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1995{
1996 driver->AttachShader = _mesa_attach_shader;
1997 driver->BindAttribLocation = _mesa_bind_attrib_location;
1998 driver->CompileShader = _mesa_compile_shader;
1999 driver->CreateProgram = _mesa_create_program;
2000 driver->CreateShader = _mesa_create_shader;
2001 driver->DeleteProgram2 = _mesa_delete_program2;
2002 driver->DeleteShader = _mesa_delete_shader;
2003 driver->DetachShader = _mesa_detach_shader;
2004 driver->GetActiveAttrib = _mesa_get_active_attrib;
2005 driver->GetActiveUniform = _mesa_get_active_uniform;
2006 driver->GetAttachedShaders = _mesa_get_attached_shaders;
2007 driver->GetAttribLocation = _mesa_get_attrib_location;
2008 driver->GetHandle = _mesa_get_handle;
2009 driver->GetProgramiv = _mesa_get_programiv;
2010 driver->GetProgramInfoLog = _mesa_get_program_info_log;
2011 driver->GetShaderiv = _mesa_get_shaderiv;
2012 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
2013 driver->GetShaderSource = _mesa_get_shader_source;
2014 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06002015 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06002016 driver->GetUniformLocation = _mesa_get_uniform_location;
2017 driver->IsProgram = _mesa_is_program;
2018 driver->IsShader = _mesa_is_shader;
2019 driver->LinkProgram = _mesa_link_program;
2020 driver->ShaderSource = _mesa_shader_source;
2021 driver->Uniform = _mesa_uniform;
2022 driver->UniformMatrix = _mesa_uniform_matrix;
2023 driver->UseProgram = _mesa_use_program;
2024 driver->ValidateProgram = _mesa_validate_program;
2025}