blob: 61289db2d2e6278a497b219624d271a416ca09f7 [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();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600413
414 /* Default pragma settings */
415 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
416 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
417 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
418 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700419}
420
421
Brian5b01c5e2006-12-19 18:02:03 -0700422/**
Brian935f93f2007-03-24 16:20:02 -0600423 * Free the per-context shader-related state.
424 */
425void
426_mesa_free_shader_state(GLcontext *ctx)
427{
Brian3c008a02007-04-12 15:22:32 -0600428 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600429}
430
431
432/**
Brian5b01c5e2006-12-19 18:02:03 -0700433 * Copy string from <src> to <dst>, up to maxLength characters, returning
434 * length of <dst> in <length>.
435 * \param src the strings source
436 * \param maxLength max chars to copy
437 * \param length returns number of chars copied
438 * \param dst the string destination
439 */
440static void
441copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
442{
443 GLsizei len;
444 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
445 dst[len] = src[len];
446 if (maxLength > 0)
447 dst[len] = 0;
448 if (length)
449 *length = len;
450}
451
452
Brian Paul7acb7c12008-07-03 13:49:48 -0600453static GLboolean
454_mesa_is_program(GLcontext *ctx, GLuint name)
455{
456 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
457 return shProg ? GL_TRUE : GL_FALSE;
458}
459
460
461static GLboolean
462_mesa_is_shader(GLcontext *ctx, GLuint name)
463{
464 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
465 return shader ? GL_TRUE : GL_FALSE;
466}
467
468
Brian5b01c5e2006-12-19 18:02:03 -0700469/**
470 * Called via ctx->Driver.AttachShader()
471 */
Brian Paulfd59f192008-05-18 16:04:55 -0600472static void
Brian5b01c5e2006-12-19 18:02:03 -0700473_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
474{
Brian Paul530df582008-07-03 16:21:11 -0600475 struct gl_shader_program *shProg;
476 struct gl_shader *sh;
477 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700478
Brian Paul530df582008-07-03 16:21:11 -0600479 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
480 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700481 return;
Brian5b01c5e2006-12-19 18:02:03 -0700482
Brian Paul530df582008-07-03 16:21:11 -0600483 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600484 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600485 return;
486 }
487
Brian237b9852007-08-07 21:48:31 +0100488 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700489 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700490 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700491 /* The shader is already attched to this program. The
492 * GL_ARB_shader_objects spec says:
493 *
494 * "The error INVALID_OPERATION is generated by AttachObjectARB
495 * if <obj> is already attached to <containerObj>."
496 */
497 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700498 return;
Brian34ae99d2006-12-18 08:28:54 -0700499 }
500 }
Brian5b01c5e2006-12-19 18:02:03 -0700501
502 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700503 shProg->Shaders = (struct gl_shader **)
504 _mesa_realloc(shProg->Shaders,
505 n * sizeof(struct gl_shader *),
506 (n + 1) * sizeof(struct gl_shader *));
507 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700508 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
509 return;
510 }
511
512 /* append */
Brian3c008a02007-04-12 15:22:32 -0600513 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
514 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700515 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700516}
517
518
Brian Paulfd59f192008-05-18 16:04:55 -0600519static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600520_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
521 const GLchar *name)
522{
523 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600524 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600525
526 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600527 return -1;
528 }
529
530 if (!shProg->LinkStatus) {
531 _mesa_error(ctx, GL_INVALID_OPERATION,
532 "glGetAttribLocation(program not linked)");
533 return -1;
534 }
535
536 if (!name)
537 return -1;
538
Brian Paul27341a92008-09-16 16:28:36 -0600539 if (shProg->VertexProgram) {
540 const struct gl_program_parameter_list *attribs =
541 shProg->VertexProgram->Base.Attributes;
542 if (attribs) {
543 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
544 if (i >= 0) {
545 return attribs->Parameters[i].StateIndexes[0];
546 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600547 }
548 }
549 return -1;
550}
551
552
Brian Paulfd59f192008-05-18 16:04:55 -0600553static void
Brian5b01c5e2006-12-19 18:02:03 -0700554_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
555 const GLchar *name)
556{
Brian Paul530df582008-07-03 16:21:11 -0600557 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700558 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600559 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600560 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700561
Brian Paul530df582008-07-03 16:21:11 -0600562 shProg = _mesa_lookup_shader_program_err(ctx, program,
563 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700564 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700565 return;
566 }
567
Brian9e4bae92006-12-20 09:27:42 -0700568 if (!name)
569 return;
570
571 if (strncmp(name, "gl_", 3) == 0) {
572 _mesa_error(ctx, GL_INVALID_OPERATION,
573 "glBindAttribLocation(illegal name)");
574 return;
575 }
576
Brian Paul7acb7c12008-07-03 13:49:48 -0600577 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
578 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
579 return;
580 }
581
Brian Paul6bc87492008-07-25 08:34:54 -0600582 if (shProg->LinkStatus) {
583 /* get current index/location for the attribute */
584 oldIndex = _mesa_get_attrib_location(ctx, program, name);
585 }
586 else {
587 oldIndex = -1;
588 }
589
Brian3209c3e2007-01-09 17:49:24 -0700590 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600591 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700592 if (i < 0) {
593 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600594 return;
Brian3209c3e2007-01-09 17:49:24 -0700595 }
596
Brian Paul27341a92008-09-16 16:28:36 -0600597 /*
598 * Note that this attribute binding won't go into effect until
599 * glLinkProgram is called again.
600 */
Brian34ae99d2006-12-18 08:28:54 -0700601}
602
603
Brian Paulfd59f192008-05-18 16:04:55 -0600604static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700605_mesa_create_shader(GLcontext *ctx, GLenum type)
606{
Brian65a18442006-12-19 18:46:56 -0700607 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700608 GLuint name;
609
610 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
611
612 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700613 case GL_FRAGMENT_SHADER:
614 case GL_VERTEX_SHADER:
615 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700616 break;
617 default:
618 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
619 return 0;
620 }
621
Brian65a18442006-12-19 18:46:56 -0700622 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700623
624 return name;
625}
626
627
Brian Paulfd59f192008-05-18 16:04:55 -0600628static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700629_mesa_create_program(GLcontext *ctx)
630{
631 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700632 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700633
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800634 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700635 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700636
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800637 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700638
Brian3c008a02007-04-12 15:22:32 -0600639 assert(shProg->RefCount == 1);
640
Brian5b01c5e2006-12-19 18:02:03 -0700641 return name;
642}
643
644
Brian3c008a02007-04-12 15:22:32 -0600645/**
646 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
647 * DeleteProgramARB.
648 */
Brian Paulfd59f192008-05-18 16:04:55 -0600649static void
Brian5b01c5e2006-12-19 18:02:03 -0700650_mesa_delete_program2(GLcontext *ctx, GLuint name)
651{
Brian3c008a02007-04-12 15:22:32 -0600652 /*
653 * NOTE: deleting shaders/programs works a bit differently than
654 * texture objects (and buffer objects, etc). Shader/program
655 * handles/IDs exist in the hash table until the object is really
656 * deleted (refcount==0). With texture objects, the handle/ID is
657 * removed from the hash table in glDeleteTextures() while the tex
658 * object itself might linger until its refcount goes to zero.
659 */
Brian65a18442006-12-19 18:46:56 -0700660 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700661
Brian Paul530df582008-07-03 16:21:11 -0600662 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
663 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700664 return;
Brian5b01c5e2006-12-19 18:02:03 -0700665
Brian9e4bae92006-12-20 09:27:42 -0700666 shProg->DeletePending = GL_TRUE;
667
Brian3c008a02007-04-12 15:22:32 -0600668 /* effectively, decr shProg's refcount */
669 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700670}
671
672
Brian Paulfd59f192008-05-18 16:04:55 -0600673static void
Brian5b01c5e2006-12-19 18:02:03 -0700674_mesa_delete_shader(GLcontext *ctx, GLuint shader)
675{
Brian Paul530df582008-07-03 16:21:11 -0600676 struct gl_shader *sh;
677
678 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
679 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700680 return;
Brian5b01c5e2006-12-19 18:02:03 -0700681
Brian9e4bae92006-12-20 09:27:42 -0700682 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600683
684 /* effectively, decr sh's refcount */
685 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700686}
687
688
Brian Paulfd59f192008-05-18 16:04:55 -0600689static void
Brian5b01c5e2006-12-19 18:02:03 -0700690_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
691{
Brian Paul530df582008-07-03 16:21:11 -0600692 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100693 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700694 GLuint i, j;
695
Brian Paul530df582008-07-03 16:21:11 -0600696 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
697 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700698 return;
Brian5b01c5e2006-12-19 18:02:03 -0700699
Brian237b9852007-08-07 21:48:31 +0100700 n = shProg->NumShaders;
701
Brian5b01c5e2006-12-19 18:02:03 -0700702 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700703 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700704 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600705 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700706
Brian Paul530df582008-07-03 16:21:11 -0600707 /* release */
Brian3c008a02007-04-12 15:22:32 -0600708 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700709
Brian5b01c5e2006-12-19 18:02:03 -0700710 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700711 newList = (struct gl_shader **)
712 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700713 if (!newList) {
714 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
715 return;
716 }
717 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700718 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700719 }
720 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700721 newList[j++] = shProg->Shaders[i];
722 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700723
Brian65a18442006-12-19 18:46:56 -0700724 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600725 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600726
727#ifdef DEBUG
728 /* sanity check */
729 {
730 for (j = 0; j < shProg->NumShaders; j++) {
731 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
732 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
733 assert(shProg->Shaders[j]->RefCount > 0);
734 }
735 }
736#endif
737
Brian5b01c5e2006-12-19 18:02:03 -0700738 return;
739 }
740 }
741
742 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600743 {
744 GLenum err;
745 if (_mesa_is_shader(ctx, shader))
746 err = GL_INVALID_OPERATION;
747 else if (_mesa_is_program(ctx, shader))
748 err = GL_INVALID_OPERATION;
749 else
750 err = GL_INVALID_VALUE;
751 _mesa_error(ctx, err, "glDetachProgram(shader)");
752 return;
753 }
Brian5b01c5e2006-12-19 18:02:03 -0700754}
755
756
Brian Paulffbc66b2008-07-21 13:58:50 -0600757static GLint
758sizeof_glsl_type(GLenum type)
759{
760 switch (type) {
761 case GL_FLOAT:
762 case GL_INT:
763 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600764 case GL_SAMPLER_1D:
765 case GL_SAMPLER_2D:
766 case GL_SAMPLER_3D:
767 case GL_SAMPLER_CUBE:
768 case GL_SAMPLER_1D_SHADOW:
769 case GL_SAMPLER_2D_SHADOW:
770 case GL_SAMPLER_2D_RECT_ARB:
771 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
772 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
773 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
774 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600775 return 1;
776 case GL_FLOAT_VEC2:
777 case GL_INT_VEC2:
778 case GL_BOOL_VEC2:
779 return 2;
780 case GL_FLOAT_VEC3:
781 case GL_INT_VEC3:
782 case GL_BOOL_VEC3:
783 return 3;
784 case GL_FLOAT_VEC4:
785 case GL_INT_VEC4:
786 case GL_BOOL_VEC4:
787 return 4;
788 case GL_FLOAT_MAT2:
789 case GL_FLOAT_MAT2x3:
790 case GL_FLOAT_MAT2x4:
791 return 8; /* two float[4] vectors */
792 case GL_FLOAT_MAT3:
793 case GL_FLOAT_MAT3x2:
794 case GL_FLOAT_MAT3x4:
795 return 12; /* three float[4] vectors */
796 case GL_FLOAT_MAT4:
797 case GL_FLOAT_MAT4x2:
798 case GL_FLOAT_MAT4x3:
799 return 16; /* four float[4] vectors */
800 default:
801 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
802 return 1;
803 }
804}
805
806
Brian Pauleda291e2008-08-06 16:26:47 -0600807static GLboolean
808is_boolean_type(GLenum type)
809{
810 switch (type) {
811 case GL_BOOL:
812 case GL_BOOL_VEC2:
813 case GL_BOOL_VEC3:
814 case GL_BOOL_VEC4:
815 return GL_TRUE;
816 default:
817 return GL_FALSE;
818 }
819}
820
821
822static GLboolean
823is_integer_type(GLenum type)
824{
825 switch (type) {
826 case GL_INT:
827 case GL_INT_VEC2:
828 case GL_INT_VEC3:
829 case GL_INT_VEC4:
830 return GL_TRUE;
831 default:
832 return GL_FALSE;
833 }
834}
835
836
Brian Paulc4ffbf02009-02-18 17:46:00 -0700837static GLboolean
838is_sampler_type(GLenum type)
839{
840 switch (type) {
841 case GL_SAMPLER_1D:
842 case GL_SAMPLER_2D:
843 case GL_SAMPLER_3D:
844 case GL_SAMPLER_CUBE:
845 case GL_SAMPLER_1D_SHADOW:
846 case GL_SAMPLER_2D_SHADOW:
847 case GL_SAMPLER_2D_RECT_ARB:
848 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
849 case GL_SAMPLER_1D_ARRAY_EXT:
850 case GL_SAMPLER_2D_ARRAY_EXT:
851 return GL_TRUE;
852 default:
853 return GL_FALSE;
854 }
855}
856
857
Brian Paulfd59f192008-05-18 16:04:55 -0600858static void
Brian5b01c5e2006-12-19 18:02:03 -0700859_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
860 GLsizei maxLength, GLsizei *length, GLint *size,
861 GLenum *type, GLchar *nameOut)
862{
Brian Paul27341a92008-09-16 16:28:36 -0600863 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600864 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700865
Brian Paul530df582008-07-03 16:21:11 -0600866 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
867 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700868 return;
Brian5b01c5e2006-12-19 18:02:03 -0700869
Brian Paul27341a92008-09-16 16:28:36 -0600870 if (shProg->VertexProgram)
871 attribs = shProg->VertexProgram->Base.Attributes;
872
873 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600874 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700875 return;
876 }
877
Brian Paul27341a92008-09-16 16:28:36 -0600878 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
879
Brian5b01c5e2006-12-19 18:02:03 -0700880 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600881 *size = attribs->Parameters[index].Size
882 / sizeof_glsl_type(attribs->Parameters[index].DataType);
883
Brian Paulade50832008-05-14 16:09:46 -0600884 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600885 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700886}
887
888
Brian Pauleda291e2008-08-06 16:26:47 -0600889static struct gl_program_parameter *
890get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
891{
892 const struct gl_program *prog;
893 GLint progPos;
894
895 progPos = shProg->Uniforms->Uniforms[index].VertPos;
896 if (progPos >= 0) {
897 prog = &shProg->VertexProgram->Base;
898 }
899 else {
900 progPos = shProg->Uniforms->Uniforms[index].FragPos;
901 if (progPos >= 0) {
902 prog = &shProg->FragmentProgram->Base;
903 }
904 }
905
906 if (!prog || progPos < 0)
907 return NULL; /* should never happen */
908
909 return &prog->Parameters->Parameters[progPos];
910}
911
912
Brian5b01c5e2006-12-19 18:02:03 -0700913/**
914 * Called via ctx->Driver.GetActiveUniform().
915 */
Brian Paulfd59f192008-05-18 16:04:55 -0600916static void
Brian5b01c5e2006-12-19 18:02:03 -0700917_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
918 GLsizei maxLength, GLsizei *length, GLint *size,
919 GLenum *type, GLchar *nameOut)
920{
Brian Paul530df582008-07-03 16:21:11 -0600921 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600922 const struct gl_program *prog;
Brian Paul369d1852009-02-11 08:16:14 -0700923 const struct gl_program_parameter *param;
Brian Paulade50832008-05-14 16:09:46 -0600924 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700925
Brian Paul530df582008-07-03 16:21:11 -0600926 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
927 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700928 return;
Brian5b01c5e2006-12-19 18:02:03 -0700929
Brian Paulade50832008-05-14 16:09:46 -0600930 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700931 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
932 return;
933 }
934
Brian Paulade50832008-05-14 16:09:46 -0600935 progPos = shProg->Uniforms->Uniforms[index].VertPos;
936 if (progPos >= 0) {
937 prog = &shProg->VertexProgram->Base;
938 }
939 else {
940 progPos = shProg->Uniforms->Uniforms[index].FragPos;
941 if (progPos >= 0) {
942 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600943 }
944 }
945
Brian Paulade50832008-05-14 16:09:46 -0600946 if (!prog || progPos < 0)
947 return; /* should never happen */
948
Brian Paul369d1852009-02-11 08:16:14 -0700949 ASSERT(progPos < prog->Parameters->NumParameters);
950 param = &prog->Parameters->Parameters[progPos];
951
952 if (nameOut) {
953 copy_string(nameOut, maxLength, length, param->Name);
954 }
955
956 if (size) {
957 GLint typeSize = sizeof_glsl_type(param->DataType);
958 if (param->Size > typeSize) {
959 /* This is an array.
960 * Array elements are placed on vector[4] boundaries so they're
961 * a multiple of four floats. We round typeSize up to next multiple
962 * of four to get the right size below.
963 */
964 typeSize = (typeSize + 3) & ~3;
965 }
966 /* Note that the returned size is in units of the <type>, not bytes */
967 *size = param->Size / typeSize;
968 }
969
970 if (type) {
971 *type = param->DataType;
972 }
Brian5b01c5e2006-12-19 18:02:03 -0700973}
974
975
976/**
977 * Called via ctx->Driver.GetAttachedShaders().
978 */
Brian Paulfd59f192008-05-18 16:04:55 -0600979static void
Brian5b01c5e2006-12-19 18:02:03 -0700980_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
981 GLsizei *count, GLuint *obj)
982{
Brian Paul530df582008-07-03 16:21:11 -0600983 struct gl_shader_program *shProg =
984 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700985 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600986 GLuint i;
987 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700988 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700989 }
990 if (count)
991 *count = i;
992 }
Brian5b01c5e2006-12-19 18:02:03 -0700993}
994
995
Brian Paulfd59f192008-05-18 16:04:55 -0600996static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700997_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700998{
Ian Romanick905d8e02008-09-29 12:27:00 -0700999 GLint handle = 0;
1000
1001 if (pname == GL_PROGRAM_OBJECT_ARB) {
1002 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
1003 } else {
Brian34ae99d2006-12-18 08:28:54 -07001004 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
1005 }
Ian Romanick905d8e02008-09-29 12:27:00 -07001006
1007 return handle;
Brian34ae99d2006-12-18 08:28:54 -07001008}
1009
1010
Brian Paulfd59f192008-05-18 16:04:55 -06001011static void
Brian5b01c5e2006-12-19 18:02:03 -07001012_mesa_get_programiv(GLcontext *ctx, GLuint program,
1013 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -07001014{
Brian Paul27341a92008-09-16 16:28:36 -06001015 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -07001016 struct gl_shader_program *shProg
1017 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -07001018
Brian65a18442006-12-19 18:46:56 -07001019 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001020 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -07001021 return;
1022 }
1023
Brian Paul27341a92008-09-16 16:28:36 -06001024 if (shProg->VertexProgram)
1025 attribs = shProg->VertexProgram->Base.Attributes;
1026 else
1027 attribs = NULL;
1028
Brian5b01c5e2006-12-19 18:02:03 -07001029 switch (pname) {
1030 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001031 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -07001032 break;
1033 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -07001034 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -07001035 break;
Brian5b01c5e2006-12-19 18:02:03 -07001036 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001037 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -07001038 break;
1039 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001040 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001041 break;
1042 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -07001043 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -07001044 break;
1045 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -06001046 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001047 break;
1048 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -06001049 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -07001050 break;
1051 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -06001052 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001053 break;
1054 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -06001055 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -06001056 if (*params > 0)
1057 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -07001058 break;
Brian Paulbda6ad22008-08-06 12:45:14 -06001059 case GL_PROGRAM_BINARY_LENGTH_OES:
1060 *params = 0;
1061 break;
Brian34ae99d2006-12-18 08:28:54 -07001062 default:
Brian5b01c5e2006-12-19 18:02:03 -07001063 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
1064 return;
Brian34ae99d2006-12-18 08:28:54 -07001065 }
Brian5b01c5e2006-12-19 18:02:03 -07001066}
Brian34ae99d2006-12-18 08:28:54 -07001067
Brian34ae99d2006-12-18 08:28:54 -07001068
Brian Paulfd59f192008-05-18 16:04:55 -06001069static void
Brian5b01c5e2006-12-19 18:02:03 -07001070_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
1071{
Brian Paul530df582008-07-03 16:21:11 -06001072 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -07001073
1074 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -07001075 return;
1076 }
Brian65a18442006-12-19 18:46:56 -07001077
Brian5b01c5e2006-12-19 18:02:03 -07001078 switch (pname) {
1079 case GL_SHADER_TYPE:
1080 *params = shader->Type;
1081 break;
1082 case GL_DELETE_STATUS:
1083 *params = shader->DeletePending;
1084 break;
1085 case GL_COMPILE_STATUS:
1086 *params = shader->CompileStatus;
1087 break;
1088 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001089 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001090 break;
1091 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001092 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001093 break;
1094 default:
1095 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1096 return;
1097 }
1098}
1099
1100
Brian Paulfd59f192008-05-18 16:04:55 -06001101static void
Brian5b01c5e2006-12-19 18:02:03 -07001102_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1103 GLsizei *length, GLchar *infoLog)
1104{
Brian65a18442006-12-19 18:46:56 -07001105 struct gl_shader_program *shProg
1106 = _mesa_lookup_shader_program(ctx, program);
1107 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001108 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1109 return;
1110 }
Brian65a18442006-12-19 18:46:56 -07001111 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001112}
1113
1114
Brian Paulfd59f192008-05-18 16:04:55 -06001115static void
Brian5b01c5e2006-12-19 18:02:03 -07001116_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1117 GLsizei *length, GLchar *infoLog)
1118{
Brian65a18442006-12-19 18:46:56 -07001119 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1120 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001121 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1122 return;
1123 }
Brian65a18442006-12-19 18:46:56 -07001124 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001125}
1126
1127
1128/**
1129 * Called via ctx->Driver.GetShaderSource().
1130 */
Brian Paulfd59f192008-05-18 16:04:55 -06001131static void
Brian5b01c5e2006-12-19 18:02:03 -07001132_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1133 GLsizei *length, GLchar *sourceOut)
1134{
Brian Paul530df582008-07-03 16:21:11 -06001135 struct gl_shader *sh;
1136 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001137 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001138 return;
1139 }
Brian65a18442006-12-19 18:46:56 -07001140 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001141}
1142
1143
Brian Paul5b982362008-08-06 13:07:09 -06001144static void
1145get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1146{
1147 switch (type) {
1148 case GL_FLOAT_MAT2:
1149 *rows = *cols = 2;
1150 break;
1151 case GL_FLOAT_MAT2x3:
1152 *rows = 3;
1153 *cols = 2;
1154 break;
1155 case GL_FLOAT_MAT2x4:
1156 *rows = 4;
1157 *cols = 2;
1158 break;
1159 case GL_FLOAT_MAT3:
1160 *rows = 3;
1161 *cols = 3;
1162 break;
1163 case GL_FLOAT_MAT3x2:
1164 *rows = 2;
1165 *cols = 3;
1166 break;
1167 case GL_FLOAT_MAT3x4:
1168 *rows = 4;
1169 *cols = 3;
1170 break;
1171 case GL_FLOAT_MAT4:
1172 *rows = 4;
1173 *cols = 4;
1174 break;
1175 case GL_FLOAT_MAT4x2:
1176 *rows = 2;
1177 *cols = 4;
1178 break;
1179 case GL_FLOAT_MAT4x3:
1180 *rows = 3;
1181 *cols = 4;
1182 break;
1183 default:
1184 *rows = *cols = 0;
1185 }
1186}
1187
1188
1189/**
1190 * Determine the number of rows and columns occupied by a uniform
Brian Paulea9568d2008-09-16 08:55:54 -06001191 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
1192 * the number of rows = 1 and cols = number of elements in the vector.
Brian Paul5b982362008-08-06 13:07:09 -06001193 */
1194static void
1195get_uniform_rows_cols(const struct gl_program_parameter *p,
1196 GLint *rows, GLint *cols)
1197{
1198 get_matrix_dims(p->DataType, rows, cols);
1199 if (*rows == 0 && *cols == 0) {
1200 /* not a matrix type, probably a float or vector */
Brian Paulea9568d2008-09-16 08:55:54 -06001201 if (p->Size <= 4) {
1202 *rows = 1;
1203 *cols = p->Size;
1204 }
1205 else {
1206 *rows = p->Size / 4 + 1;
1207 if (p->Size % 4 == 0)
1208 *cols = 4;
1209 else
1210 *cols = p->Size % 4;
1211 }
Brian Paul5b982362008-08-06 13:07:09 -06001212 }
1213}
1214
1215
Brian5b01c5e2006-12-19 18:02:03 -07001216/**
Brian Paul4ef7a932009-02-11 09:03:16 -07001217 * Helper for get_uniform[fi]v() functions.
1218 * Given a shader program name and uniform location, return a pointer
1219 * to the shader program and return the program parameter position.
Brian5b01c5e2006-12-19 18:02:03 -07001220 */
Brian Paul4ef7a932009-02-11 09:03:16 -07001221static void
1222lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
1223 struct gl_program **progOut, GLint *paramPosOut)
Brian5b01c5e2006-12-19 18:02:03 -07001224{
Brian65a18442006-12-19 18:46:56 -07001225 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001226 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian Paul4ef7a932009-02-11 09:03:16 -07001227 struct gl_program *prog = NULL;
1228 GLint progPos = -1;
Brian Paulade50832008-05-14 16:09:46 -06001229
Brian Paul4ef7a932009-02-11 09:03:16 -07001230 /* if shProg is NULL, we'll have already recorded an error */
1231
1232 if (shProg) {
1233 if (!shProg->Uniforms ||
1234 location < 0 ||
1235 location >= (GLint) shProg->Uniforms->NumUniforms) {
1236 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1237 }
1238 else {
1239 /* OK, find the gl_program and program parameter location */
Brian Paulade50832008-05-14 16:09:46 -06001240 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1241 if (progPos >= 0) {
1242 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001243 }
Brian Paulade50832008-05-14 16:09:46 -06001244 else {
1245 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1246 if (progPos >= 0) {
1247 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001248 }
Brian Paulade50832008-05-14 16:09:46 -06001249 }
Brian5b01c5e2006-12-19 18:02:03 -07001250 }
1251 }
Brian Paul4ef7a932009-02-11 09:03:16 -07001252
1253 *progOut = prog;
1254 *paramPosOut = progPos;
Brian Paul2be54a82008-07-08 16:17:04 -06001255}
1256
1257
1258/**
1259 * Called via ctx->Driver.GetUniformfv().
1260 */
1261static void
1262_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1263 GLfloat *params)
1264{
Brian Paul4ef7a932009-02-11 09:03:16 -07001265 struct gl_program *prog;
1266 GLint paramPos;
1267
1268 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1269
1270 if (prog) {
1271 const struct gl_program_parameter *p =
1272 &prog->Parameters->Parameters[paramPos];
1273 GLint rows, cols, i, j, k;
1274
1275 get_uniform_rows_cols(p, &rows, &cols);
1276
1277 k = 0;
1278 for (i = 0; i < rows; i++) {
1279 for (j = 0; j < cols; j++ ) {
1280 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
1281 }
1282 }
1283 }
Brian Paul2be54a82008-07-08 16:17:04 -06001284}
1285
1286
1287/**
1288 * Called via ctx->Driver.GetUniformiv().
Brian Paul4ef7a932009-02-11 09:03:16 -07001289 * \sa _mesa_get_uniformfv, only difference is a cast.
Brian Paul2be54a82008-07-08 16:17:04 -06001290 */
1291static void
1292_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1293 GLint *params)
1294{
Brian Paul4ef7a932009-02-11 09:03:16 -07001295 struct gl_program *prog;
1296 GLint paramPos;
1297
1298 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1299
1300 if (prog) {
1301 const struct gl_program_parameter *p =
1302 &prog->Parameters->Parameters[paramPos];
1303 GLint rows, cols, i, j, k;
1304
1305 get_uniform_rows_cols(p, &rows, &cols);
1306
1307 k = 0;
1308 for (i = 0; i < rows; i++) {
1309 for (j = 0; j < cols; j++ ) {
1310 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
1311 }
1312 }
Brian Paul2be54a82008-07-08 16:17:04 -06001313 }
Brian5b01c5e2006-12-19 18:02:03 -07001314}
1315
1316
1317/**
Brian Pauleda291e2008-08-06 16:26:47 -06001318 * The value returned by GetUniformLocation actually encodes two things:
1319 * 1. the index into the prog->Uniforms[] array for the uniform
1320 * 2. an offset in the prog->ParameterValues[] array for specifying array
1321 * elements or structure fields.
1322 * This function merges those two values.
1323 */
1324static void
1325merge_location_offset(GLint *location, GLint offset)
1326{
1327 *location = *location | (offset << 16);
1328}
1329
1330
1331/**
1332 * Seperate the uniform location and parameter offset. See above.
1333 */
1334static void
1335split_location_offset(GLint *location, GLint *offset)
1336{
1337 *offset = (*location >> 16);
1338 *location = *location & 0xffff;
1339}
1340
1341
1342/**
Brian5b01c5e2006-12-19 18:02:03 -07001343 * Called via ctx->Driver.GetUniformLocation().
Brian Pauleda291e2008-08-06 16:26:47 -06001344 *
1345 * The return value will encode two values, the uniform location and an
1346 * offset (used for arrays, structs).
Brian5b01c5e2006-12-19 18:02:03 -07001347 */
Brian Paulfd59f192008-05-18 16:04:55 -06001348static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001349_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1350{
Brian Pauleda291e2008-08-06 16:26:47 -06001351 GLint offset = 0, location = -1;
1352
Brian Paul530df582008-07-03 16:21:11 -06001353 struct gl_shader_program *shProg =
1354 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1355
Brian Paulade50832008-05-14 16:09:46 -06001356 if (!shProg)
1357 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001358
Brian Paule06565b2008-07-04 09:58:55 -06001359 if (shProg->LinkStatus == GL_FALSE) {
1360 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1361 return -1;
1362 }
1363
Brian Paul530df582008-07-03 16:21:11 -06001364 /* XXX we should return -1 if the uniform was declared, but not
1365 * actually used.
1366 */
1367
Brian Pauleda291e2008-08-06 16:26:47 -06001368 /* XXX we need to be able to parse uniform names for structs and arrays
1369 * such as:
1370 * mymatrix[1]
1371 * mystruct.field1
1372 */
1373
1374 {
1375 /* handle 1-dimension arrays here... */
1376 char *c = strchr(name, '[');
1377 if (c) {
1378 /* truncate name at [ */
1379 const GLint len = c - name;
1380 GLchar *newName = _mesa_malloc(len + 1);
1381 if (!newName)
1382 return -1; /* out of mem */
1383 _mesa_memcpy(newName, name, len);
1384 newName[len] = 0;
1385
1386 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1387 if (location >= 0) {
1388 const GLint element = _mesa_atoi(c + 1);
1389 if (element > 0) {
1390 /* get type of the uniform array element */
1391 struct gl_program_parameter *p;
1392 p = get_uniform_parameter(shProg, location);
1393 if (p) {
1394 GLint rows, cols;
1395 get_matrix_dims(p->DataType, &rows, &cols);
1396 if (rows < 1)
1397 rows = 1;
1398 offset = element * rows;
1399 }
1400 }
1401 }
1402
1403 _mesa_free(newName);
1404 }
1405 }
1406
1407 if (location < 0) {
1408 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1409 }
1410
1411 if (location >= 0) {
1412 merge_location_offset(&location, offset);
1413 }
1414
1415 return location;
Brian5b01c5e2006-12-19 18:02:03 -07001416}
1417
1418
Brian34ae99d2006-12-18 08:28:54 -07001419
Brian5b01c5e2006-12-19 18:02:03 -07001420/**
1421 * Called via ctx->Driver.ShaderSource()
1422 */
Brian Paulfd59f192008-05-18 16:04:55 -06001423static void
Brian5b01c5e2006-12-19 18:02:03 -07001424_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001425{
Brian Paul530df582008-07-03 16:21:11 -06001426 struct gl_shader *sh;
1427
1428 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1429 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001430 return;
Brian34ae99d2006-12-18 08:28:54 -07001431
Brian34ae99d2006-12-18 08:28:54 -07001432 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001433 if (sh->Source) {
1434 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001435 }
Brian65a18442006-12-19 18:46:56 -07001436 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001437 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001438}
1439
1440
Brian5b01c5e2006-12-19 18:02:03 -07001441/**
1442 * Called via ctx->Driver.CompileShader()
1443 */
Brian Paulfd59f192008-05-18 16:04:55 -06001444static void
Brian5b01c5e2006-12-19 18:02:03 -07001445_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001446{
Brian Paul530df582008-07-03 16:21:11 -06001447 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001448
Brian Paul530df582008-07-03 16:21:11 -06001449 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1450 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001451 return;
Brian34ae99d2006-12-18 08:28:54 -07001452
Brian Paul65fc2ca2009-03-19 10:25:24 -06001453 /* set default pragma state for shader */
1454 sh->Pragmas = ctx->Shader.DefaultPragmas;
1455
Brian Paulcb136e02009-01-22 10:34:15 -07001456 /* this call will set the sh->CompileStatus field to indicate if
1457 * compilation was successful.
1458 */
1459 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001460}
1461
1462
Brian5b01c5e2006-12-19 18:02:03 -07001463/**
1464 * Called via ctx->Driver.LinkProgram()
1465 */
Brian Paulfd59f192008-05-18 16:04:55 -06001466static void
Brian5b01c5e2006-12-19 18:02:03 -07001467_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001468{
Brian65a18442006-12-19 18:46:56 -07001469 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001470
Brian Paul530df582008-07-03 16:21:11 -06001471 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1472 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001473 return;
Brian34ae99d2006-12-18 08:28:54 -07001474
Briandf43fb62008-05-06 23:08:51 -06001475 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1476
Brianc1771912007-02-16 09:56:19 -07001477 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001478}
1479
1480
1481/**
Brian5b01c5e2006-12-19 18:02:03 -07001482 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001483 */
Brian5b01c5e2006-12-19 18:02:03 -07001484void
1485_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001486{
Brian3c008a02007-04-12 15:22:32 -06001487 struct gl_shader_program *shProg;
1488
Brian00d63aa2007-02-03 11:35:02 -07001489 if (ctx->Shader.CurrentProgram &&
1490 ctx->Shader.CurrentProgram->Name == program) {
1491 /* no-op */
1492 return;
1493 }
1494
1495 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1496
Brian5b01c5e2006-12-19 18:02:03 -07001497 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001498 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001499 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001500 return;
1501 }
1502 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001503 _mesa_error(ctx, GL_INVALID_OPERATION,
1504 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001505 return;
1506 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001507
1508 /* debug code */
1509 if (0) {
1510 GLuint i;
1511 _mesa_printf("Use Shader %u\n", shProg->Name);
1512 for (i = 0; i < shProg->NumShaders; i++) {
1513 _mesa_printf(" shader %u, type 0x%x\n",
1514 shProg->Shaders[i]->Name,
1515 shProg->Shaders[i]->Type);
1516 }
1517 }
Brian5b01c5e2006-12-19 18:02:03 -07001518 }
1519 else {
Brian3c008a02007-04-12 15:22:32 -06001520 shProg = NULL;
1521 }
1522
1523 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001524}
Brian34ae99d2006-12-18 08:28:54 -07001525
Brian5b01c5e2006-12-19 18:02:03 -07001526
Brian Paulade50832008-05-14 16:09:46 -06001527
1528/**
Brian Paul517401a2008-11-06 15:04:11 -07001529 * Update the vertex/fragment program's TexturesUsed array.
1530 *
1531 * This needs to be called after glUniform(set sampler var) is called.
1532 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1533 * particular texture unit. We know the sampler's texture target
1534 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1535 * set by glUniform() calls.
1536 *
1537 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1538 * information to update the prog->TexturesUsed[] values.
1539 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1540 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1541 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001542 */
Brian Paul517401a2008-11-06 15:04:11 -07001543void
1544_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001545{
1546 GLuint s;
1547
1548 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1549
1550 for (s = 0; s < MAX_SAMPLERS; s++) {
1551 if (prog->SamplersUsed & (1 << s)) {
1552 GLuint u = prog->SamplerUnits[s];
1553 GLuint t = prog->SamplerTargets[s];
1554 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1555 prog->TexturesUsed[u] |= (1 << t);
1556 }
1557 }
1558}
1559
1560
1561/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001562 * Check if the type given by userType is allowed to set a uniform of the
1563 * target type. Generally, equivalence is required, but setting Boolean
1564 * uniforms can be done with glUniformiv or glUniformfv.
1565 */
1566static GLboolean
1567compatible_types(GLenum userType, GLenum targetType)
1568{
1569 if (userType == targetType)
1570 return GL_TRUE;
1571
1572 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1573 return GL_TRUE;
1574
1575 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1576 userType == GL_INT_VEC2))
1577 return GL_TRUE;
1578
1579 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1580 userType == GL_INT_VEC3))
1581 return GL_TRUE;
1582
1583 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1584 userType == GL_INT_VEC4))
1585 return GL_TRUE;
1586
Brianb36749d2008-07-21 20:42:05 -06001587 if (is_sampler_type(targetType) && userType == GL_INT)
1588 return GL_TRUE;
1589
Brian Paulffbc66b2008-07-21 13:58:50 -06001590 return GL_FALSE;
1591}
1592
1593
1594/**
Brian Paulade50832008-05-14 16:09:46 -06001595 * Set the value of a program's uniform variable.
1596 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001597 * \param index the index of the program parameter for the uniform
1598 * \param offset additional parameter slot offset (for arrays)
Brian Paulc4ffbf02009-02-18 17:46:00 -07001599 * \param type the incoming datatype of 'values'
Brian Paulade50832008-05-14 16:09:46 -06001600 * \param count the number of uniforms to set
Brian Paulc4ffbf02009-02-18 17:46:00 -07001601 * \param elems number of elements per uniform (1, 2, 3 or 4)
1602 * \param values the new values, of datatype 'type'
Brian Paulade50832008-05-14 16:09:46 -06001603 */
1604static void
Brian Pauleda291e2008-08-06 16:26:47 -06001605set_program_uniform(GLcontext *ctx, struct gl_program *program,
1606 GLint index, GLint offset,
1607 GLenum type, GLsizei count, GLint elems,
1608 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001609{
Brian Paul949e7382008-11-05 09:17:55 -07001610 struct gl_program_parameter *param =
1611 &program->Parameters->Parameters[index];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001612 const GLboolean isUniformBool = is_boolean_type(param->DataType);
1613 const GLboolean areIntValues = is_integer_type(type);
Brian Paul949e7382008-11-05 09:17:55 -07001614
Brian Pauleda291e2008-08-06 16:26:47 -06001615 assert(offset >= 0);
Brian Paulc4ffbf02009-02-18 17:46:00 -07001616 assert(elems >= 1);
1617 assert(elems <= 4);
Brian Pauleda291e2008-08-06 16:26:47 -06001618
Brian Paul949e7382008-11-05 09:17:55 -07001619 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001620 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1621 return;
1622 }
1623
Michal Krolc5c71302008-08-07 16:23:15 +02001624 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001625 /* out of bounds! */
1626 return;
1627 }
1628
Brian Paul949e7382008-11-05 09:17:55 -07001629 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001630 /* This controls which texture unit which is used by a sampler */
1631 GLuint texUnit, sampler;
Brian Paul2b4f0212009-02-11 09:12:34 -07001632 GLint i;
Brian Paulade50832008-05-14 16:09:46 -06001633
1634 /* data type for setting samplers must be int */
Brian Paul2b4f0212009-02-11 09:12:34 -07001635 if (type != GL_INT) {
Brian Paulade50832008-05-14 16:09:46 -06001636 _mesa_error(ctx, GL_INVALID_OPERATION,
1637 "glUniform(only glUniform1i can be used "
1638 "to set sampler uniforms)");
1639 return;
1640 }
1641
Brian Paul2b4f0212009-02-11 09:12:34 -07001642 /* XXX arrays of samplers haven't been tested much, but it's not a
1643 * common thing...
1644 */
1645 for (i = 0; i < count; i++) {
1646 sampler = (GLuint) program->Parameters->ParameterValues[index + i][0];
1647 texUnit = ((GLuint *) values)[i];
Brian Paulade50832008-05-14 16:09:46 -06001648
Brian Paul2b4f0212009-02-11 09:12:34 -07001649 /* check that the sampler (tex unit index) is legal */
1650 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1651 _mesa_error(ctx, GL_INVALID_VALUE,
1652 "glUniform1(invalid sampler/tex unit index)");
1653 return;
1654 }
1655
1656 /* This maps a sampler to a texture unit: */
1657 if (sampler < MAX_SAMPLERS) {
1658 program->SamplerUnits[sampler] = texUnit;
1659 }
Brian Paulade50832008-05-14 16:09:46 -06001660 }
1661
Brian Paul517401a2008-11-06 15:04:11 -07001662 _mesa_update_shader_textures_used(program);
Brian Paulade50832008-05-14 16:09:46 -06001663
1664 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1665 }
1666 else {
1667 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001668 GLsizei k, i;
Brian Paul2c1ea072009-02-11 08:46:21 -07001669 const GLint slots = (param->Size + 3) / 4;
1670 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paulade50832008-05-14 16:09:46 -06001671
Brian Paul2c1ea072009-02-11 08:46:21 -07001672 if (param->Size > typeSize) {
1673 /* an array */
1674 /* we'll ignore extra data below */
1675 }
1676 else {
1677 /* non-array: count must be one */
1678 if (count != 1) {
1679 _mesa_error(ctx, GL_INVALID_OPERATION,
1680 "glUniform(uniform is not an array)");
1681 return;
1682 }
Brian Paulade50832008-05-14 16:09:46 -06001683 }
1684
Brian Paulc4ffbf02009-02-18 17:46:00 -07001685 /* loop over number of array elements */
Brian Paulade50832008-05-14 16:09:46 -06001686 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001687 GLfloat *uniformVal;
1688
Brian Paulb9d8f712009-02-18 17:40:44 -07001689 if (offset + k >= slots) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001690 /* Extra array data is ignored */
1691 break;
1692 }
1693
Brian Paulc4ffbf02009-02-18 17:46:00 -07001694 /* uniformVal (the destination) is always float[4] */
Brian Paul2c1ea072009-02-11 08:46:21 -07001695 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001696
1697 if (areIntValues) {
1698 /* convert user's ints to floats */
Brian Paulade50832008-05-14 16:09:46 -06001699 const GLint *iValues = ((const GLint *) values) + k * elems;
1700 for (i = 0; i < elems; i++) {
1701 uniformVal[i] = (GLfloat) iValues[i];
1702 }
1703 }
1704 else {
1705 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1706 for (i = 0; i < elems; i++) {
1707 uniformVal[i] = fValues[i];
1708 }
1709 }
Brian Pauleda291e2008-08-06 16:26:47 -06001710
1711 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paulc4ffbf02009-02-18 17:46:00 -07001712 if (isUniformBool) {
Brian Pauleda291e2008-08-06 16:26:47 -06001713 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001714 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001715 }
1716 }
Brian Paulade50832008-05-14 16:09:46 -06001717 }
1718 }
1719}
1720
1721
Brian5b01c5e2006-12-19 18:02:03 -07001722/**
1723 * Called via ctx->Driver.Uniform().
1724 */
Brian Paulfd59f192008-05-18 16:04:55 -06001725static void
Brian5b01c5e2006-12-19 18:02:03 -07001726_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1727 const GLvoid *values, GLenum type)
1728{
Brian3a8e2772006-12-20 17:19:16 -07001729 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001730 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001731 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001732 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001733
1734 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001735 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001736 return;
1737 }
1738
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001739 if (location == -1)
1740 return; /* The standard specifies this as a no-op */
1741
Brian Paul234f03e2009-02-11 09:05:08 -07001742 if (location < -1) {
1743 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
1744 return;
1745 }
1746
Brian Pauleda291e2008-08-06 16:26:47 -06001747 split_location_offset(&location, &offset);
1748
Brian Paulade50832008-05-14 16:09:46 -06001749 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1750 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001751 return;
1752 }
1753
Brian52363952007-03-13 16:50:24 -06001754 if (count < 0) {
1755 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1756 return;
1757 }
1758
Brian98650bd2007-03-13 16:32:48 -06001759 switch (type) {
1760 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001761 basicType = GL_FLOAT;
1762 elems = 1;
1763 break;
Brian98650bd2007-03-13 16:32:48 -06001764 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001765 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001766 elems = 1;
1767 break;
1768 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001769 basicType = GL_FLOAT;
1770 elems = 2;
1771 break;
Brian98650bd2007-03-13 16:32:48 -06001772 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001773 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001774 elems = 2;
1775 break;
1776 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001777 basicType = GL_FLOAT;
1778 elems = 3;
1779 break;
Brian98650bd2007-03-13 16:32:48 -06001780 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001781 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001782 elems = 3;
1783 break;
1784 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001785 basicType = GL_FLOAT;
1786 elems = 4;
1787 break;
Brian98650bd2007-03-13 16:32:48 -06001788 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001789 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001790 elems = 4;
1791 break;
1792 default:
1793 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1794 return;
Brian89dc4852007-01-04 14:35:44 -07001795 }
Brian98650bd2007-03-13 16:32:48 -06001796
Brian Paulade50832008-05-14 16:09:46 -06001797 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001798
Brian Paul2d76a0d2008-11-10 12:33:17 -07001799 uniform = &shProg->Uniforms->Uniforms[location];
1800
Brian Paule01a03d2009-02-06 10:21:36 -07001801 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1802 GLint i;
1803 _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
1804 shProg->Name, uniform->Name, location);
1805 if (basicType == GL_INT) {
1806 const GLint *v = (const GLint *) values;
1807 for (i = 0; i < count * elems; i++) {
1808 _mesa_printf("%d ", v[i]);
1809 }
1810 }
1811 else {
1812 const GLfloat *v = (const GLfloat *) values;
1813 for (i = 0; i < count * elems; i++) {
1814 _mesa_printf("%g ", v[i]);
1815 }
1816 }
1817 _mesa_printf("\n");
1818 }
1819
Brian Paulade50832008-05-14 16:09:46 -06001820 /* A uniform var may be used by both a vertex shader and a fragment
1821 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001822 */
Brian Paulade50832008-05-14 16:09:46 -06001823 if (shProg->VertexProgram) {
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->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001826 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001827 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001828 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001829 }
Brian5b01c5e2006-12-19 18:02:03 -07001830 }
Brian5cf73262007-01-05 16:02:45 -07001831
Brian Paulade50832008-05-14 16:09:46 -06001832 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001833 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001834 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001835 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001836 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001837 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06001838 }
1839 }
Brian Paul949e7382008-11-05 09:17:55 -07001840
Brian Paul2d76a0d2008-11-10 12:33:17 -07001841 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06001842}
1843
1844
Brian Pauleda291e2008-08-06 16:26:47 -06001845/**
1846 * Set a matrix-valued program parameter.
1847 */
Brian Paulade50832008-05-14 16:09:46 -06001848static void
1849set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06001850 GLuint index, GLuint offset,
1851 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001852 GLboolean transpose, const GLfloat *values)
1853{
Brian Paulffbc66b2008-07-21 13:58:50 -06001854 GLuint mat, row, col;
Brian Pauleda291e2008-08-06 16:26:47 -06001855 GLuint dst = index + offset, src = 0;
Brian Paulffbc66b2008-07-21 13:58:50 -06001856 GLint nr, nc;
1857
1858 /* check that the number of rows, columns is correct */
Brian Pauleda291e2008-08-06 16:26:47 -06001859 get_matrix_dims(program->Parameters->Parameters[index].DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06001860 if (rows != nr || cols != nc) {
1861 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06001862 "glUniformMatrix(matrix size mismatch)");
1863 return;
1864 }
1865
1866 if (index + offset > program->Parameters->Size) {
1867 /* out of bounds! */
Brian Paulffbc66b2008-07-21 13:58:50 -06001868 return;
1869 }
1870
Brian Paulade50832008-05-14 16:09:46 -06001871 /*
1872 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001873 * the rows. So, the loops below look a little funny.
1874 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001875 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001876
1877 /* loop over matrices */
1878 for (mat = 0; mat < count; mat++) {
1879
1880 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001881 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001882 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001883 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001884 if (transpose) {
1885 v[row] = values[src + row * cols + col];
1886 }
1887 else {
1888 v[row] = values[src + col * rows + row];
1889 }
Brian Paulade50832008-05-14 16:09:46 -06001890 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001891 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001892 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001893
1894 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001895 }
Brian34ae99d2006-12-18 08:28:54 -07001896}
1897
1898
1899/**
Brian5b01c5e2006-12-19 18:02:03 -07001900 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001901 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001902 */
Brian Paulfd59f192008-05-18 16:04:55 -06001903static void
Brian5b01c5e2006-12-19 18:02:03 -07001904_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1905 GLenum matrixType, GLint location, GLsizei count,
1906 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001907{
Brian3a8e2772006-12-20 17:19:16 -07001908 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001909 struct gl_uniform *uniform;
1910 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06001911
Brian3a8e2772006-12-20 17:19:16 -07001912 if (!shProg || !shProg->LinkStatus) {
1913 _mesa_error(ctx, GL_INVALID_OPERATION,
1914 "glUniformMatrix(program not linked)");
1915 return;
1916 }
Brian Paulade50832008-05-14 16:09:46 -06001917
Bruce Merry89b80322007-12-21 15:20:17 +02001918 if (location == -1)
1919 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001920
Brian Paul234f03e2009-02-11 09:05:08 -07001921 if (location < -1) {
1922 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1923 return;
1924 }
1925
Brian Pauleda291e2008-08-06 16:26:47 -06001926 split_location_offset(&location, &offset);
1927
Brian Paul016701f2008-07-29 17:43:35 -06001928 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001929 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001930 return;
1931 }
Brian34ae99d2006-12-18 08:28:54 -07001932 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001933 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001934 return;
1935 }
1936
1937 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1938
Brian Paul2d76a0d2008-11-10 12:33:17 -07001939 uniform = &shProg->Uniforms->Uniforms[location];
1940
Brian Paulade50832008-05-14 16:09:46 -06001941 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001942 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001943 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001944 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001945 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001946 index, offset,
1947 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001948 }
Brian Paulade50832008-05-14 16:09:46 -06001949 }
1950
1951 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001952 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001953 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001954 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001955 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001956 index, offset,
1957 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001958 }
Brian34ae99d2006-12-18 08:28:54 -07001959 }
Brian Paul949e7382008-11-05 09:17:55 -07001960
Brian Paul2d76a0d2008-11-10 12:33:17 -07001961 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001962}
1963
1964
Brian Paulfd59f192008-05-18 16:04:55 -06001965static void
Brian5b01c5e2006-12-19 18:02:03 -07001966_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001967{
Brian65a18442006-12-19 18:46:56 -07001968 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001969
1970 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001971 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001972 return;
1973 }
1974
Brian Paulbc985b52008-07-21 14:16:07 -06001975 if (!shProg->LinkStatus) {
1976 shProg->Validated = GL_FALSE;
1977 return;
1978 }
1979
1980 /* From the GL spec, a program is invalid if any of these are true:
1981
Brian5b01c5e2006-12-19 18:02:03 -07001982 any two active samplers in the current program object are of
1983 different types, but refer to the same texture image unit,
1984
1985 any active sampler in the current program object refers to a texture
1986 image unit where fixed-function fragment processing accesses a
1987 texture target that does not match the sampler type, or
1988
1989 the sum of the number of active samplers in the program and the
1990 number of texture image units enabled for fixed-function fragment
1991 processing exceeds the combined limit on the total number of texture
1992 image units allowed.
1993 */
Brian Paulbc985b52008-07-21 14:16:07 -06001994
1995 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001996}
Brian Paulfd59f192008-05-18 16:04:55 -06001997
1998
1999/**
2000 * Plug in Mesa's GLSL functions into the device driver function table.
2001 */
2002void
2003_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
2004{
2005 driver->AttachShader = _mesa_attach_shader;
2006 driver->BindAttribLocation = _mesa_bind_attrib_location;
2007 driver->CompileShader = _mesa_compile_shader;
2008 driver->CreateProgram = _mesa_create_program;
2009 driver->CreateShader = _mesa_create_shader;
2010 driver->DeleteProgram2 = _mesa_delete_program2;
2011 driver->DeleteShader = _mesa_delete_shader;
2012 driver->DetachShader = _mesa_detach_shader;
2013 driver->GetActiveAttrib = _mesa_get_active_attrib;
2014 driver->GetActiveUniform = _mesa_get_active_uniform;
2015 driver->GetAttachedShaders = _mesa_get_attached_shaders;
2016 driver->GetAttribLocation = _mesa_get_attrib_location;
2017 driver->GetHandle = _mesa_get_handle;
2018 driver->GetProgramiv = _mesa_get_programiv;
2019 driver->GetProgramInfoLog = _mesa_get_program_info_log;
2020 driver->GetShaderiv = _mesa_get_shaderiv;
2021 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
2022 driver->GetShaderSource = _mesa_get_shader_source;
2023 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06002024 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06002025 driver->GetUniformLocation = _mesa_get_uniform_location;
2026 driver->IsProgram = _mesa_is_program;
2027 driver->IsShader = _mesa_is_shader;
2028 driver->LinkProgram = _mesa_link_program;
2029 driver->ShaderSource = _mesa_shader_source;
2030 driver->Uniform = _mesa_uniform;
2031 driver->UniformMatrix = _mesa_uniform_matrix;
2032 driver->UseProgram = _mesa_use_program;
2033 driver->ValidateProgram = _mesa_validate_program;
2034}