blob: 453cd3964afe6919eabfb0509fb02d900894b412 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian Paulc90fca32009-08-25 17:42:47 -06003 * Version: 7.6
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian Paul8c51e002008-08-11 15:09:47 -06005 * Copyright (C) 2004-2008 Brian Paul All Rights Reserved.
Brian Paulc4ffbf02009-02-18 17:46:00 -07006 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
Brian34ae99d2006-12-18 08:28:54 -07007 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * \file shader_api.c
Brian5b01c5e2006-12-19 18:02:03 -070028 * Implementation of GLSL-related API functions
Brian34ae99d2006-12-18 08:28:54 -070029 * \author Brian Paul
30 */
31
32/**
33 * XXX things to do:
34 * 1. Check that the right error code is generated for all _mesa_error() calls.
Brian5b01c5e2006-12-19 18:02:03 -070035 * 2. Insert FLUSH_VERTICES calls in various places
Brian34ae99d2006-12-18 08:28:54 -070036 */
37
38
Brian Paulbbd28712008-09-18 12:26:54 -060039#include "main/glheader.h"
40#include "main/context.h"
41#include "main/hash.h"
42#include "main/macros.h"
43#include "shader/program.h"
44#include "shader/prog_parameter.h"
45#include "shader/prog_print.h"
46#include "shader/prog_statevars.h"
47#include "shader/prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060048#include "shader/shader_api.h"
49#include "shader/slang/slang_compile.h"
50#include "shader/slang/slang_link.h"
Ian Romanick905d8e02008-09-29 12:27:00 -070051#include "glapi/dispatch.h"
Brian34ae99d2006-12-18 08:28:54 -070052
53
Brianf2923612006-12-20 09:56:44 -070054/**
55 * Allocate a new gl_shader_program object, initialize it.
56 */
Brian Paulfd59f192008-05-18 16:04:55 -060057static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070058_mesa_new_shader_program(GLcontext *ctx, GLuint name)
59{
60 struct gl_shader_program *shProg;
61 shProg = CALLOC_STRUCT(gl_shader_program);
62 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060063 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070064 shProg->Name = name;
65 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070066 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070067 }
68 return shProg;
69}
70
71
Brianb9fbedd2007-03-26 09:23:44 -060072/**
Brian3c008a02007-04-12 15:22:32 -060073 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060074 */
Brianf2923612006-12-20 09:56:44 -070075void
Brian3c008a02007-04-12 15:22:32 -060076_mesa_clear_shader_program_data(GLcontext *ctx,
77 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070078{
Brian Paul8bdf5b62008-05-16 09:56:59 -060079 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
80 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070081
Brianf2923612006-12-20 09:56:44 -070082 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060083 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070084 shProg->Uniforms = NULL;
85 }
86
87 if (shProg->Varying) {
88 _mesa_free_parameter_list(shProg->Varying);
89 shProg->Varying = NULL;
90 }
91}
92
93
Brianb9fbedd2007-03-26 09:23:44 -060094/**
Brian3c008a02007-04-12 15:22:32 -060095 * Free all the data that hangs off a shader program object, but not the
96 * object itself.
97 */
98void
99_mesa_free_shader_program_data(GLcontext *ctx,
100 struct gl_shader_program *shProg)
101{
102 GLuint i;
103
Brianf3e8c322007-04-18 14:53:23 -0600104 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600105
106 _mesa_clear_shader_program_data(ctx, shProg);
107
Brian4b7c6fc2007-04-19 15:23:34 -0600108 if (shProg->Attributes) {
109 _mesa_free_parameter_list(shProg->Attributes);
110 shProg->Attributes = NULL;
111 }
112
Brian3c008a02007-04-12 15:22:32 -0600113 /* detach shaders */
114 for (i = 0; i < shProg->NumShaders; i++) {
115 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
116 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800117 shProg->NumShaders = 0;
118
Brian3c008a02007-04-12 15:22:32 -0600119 if (shProg->Shaders) {
120 _mesa_free(shProg->Shaders);
121 shProg->Shaders = NULL;
122 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100123
124 if (shProg->InfoLog) {
125 _mesa_free(shProg->InfoLog);
126 shProg->InfoLog = NULL;
127 }
Brian3c008a02007-04-12 15:22:32 -0600128}
129
130
131/**
Brianb9fbedd2007-03-26 09:23:44 -0600132 * Free/delete a shader program object.
133 */
Brianf2923612006-12-20 09:56:44 -0700134void
135_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
136{
137 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100138
Brianf2923612006-12-20 09:56:44 -0700139 _mesa_free(shProg);
140}
141
142
143/**
Brian3c008a02007-04-12 15:22:32 -0600144 * Set ptr to point to shProg.
145 * If ptr is pointing to another object, decrement its refcount (and delete
146 * if refcount hits zero).
147 * Then set ptr to point to shProg, incrementing its refcount.
148 */
149/* XXX this could be static */
150void
151_mesa_reference_shader_program(GLcontext *ctx,
152 struct gl_shader_program **ptr,
153 struct gl_shader_program *shProg)
154{
155 assert(ptr);
156 if (*ptr == shProg) {
157 /* no-op */
158 return;
159 }
160 if (*ptr) {
161 /* Unreference the old shader program */
162 GLboolean deleteFlag = GL_FALSE;
163 struct gl_shader_program *old = *ptr;
164
165 ASSERT(old->RefCount > 0);
166 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600167#if 0
168 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
169 (void *) old, old->Name, old->RefCount);
170#endif
Brian3c008a02007-04-12 15:22:32 -0600171 deleteFlag = (old->RefCount == 0);
172
173 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800174 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600175 _mesa_free_shader_program(ctx, old);
176 }
177
178 *ptr = NULL;
179 }
180 assert(!*ptr);
181
182 if (shProg) {
183 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600184#if 0
185 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
186 (void *) shProg, shProg->Name, shProg->RefCount);
187#endif
Brian3c008a02007-04-12 15:22:32 -0600188 *ptr = shProg;
189 }
190}
191
192
193/**
Brianf2923612006-12-20 09:56:44 -0700194 * Lookup a GLSL program object.
195 */
196struct gl_shader_program *
197_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
198{
199 struct gl_shader_program *shProg;
200 if (name) {
201 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800202 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700203 /* Note that both gl_shader and gl_shader_program objects are kept
204 * in the same hash table. Check the object's type to be sure it's
205 * what we're expecting.
206 */
Brianf3e8c322007-04-18 14:53:23 -0600207 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700208 return NULL;
209 }
210 return shProg;
211 }
212 return NULL;
213}
214
215
216/**
Brian Paul530df582008-07-03 16:21:11 -0600217 * As above, but record an error if program is not found.
218 */
219static struct gl_shader_program *
220_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
221 const char *caller)
222{
223 if (!name) {
224 _mesa_error(ctx, GL_INVALID_VALUE, caller);
225 return NULL;
226 }
227 else {
228 struct gl_shader_program *shProg = (struct gl_shader_program *)
229 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
230 if (!shProg) {
231 _mesa_error(ctx, GL_INVALID_VALUE, caller);
232 return NULL;
233 }
234 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
235 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
236 return NULL;
237 }
238 return shProg;
239 }
240}
241
242
243
244
245/**
Brianf2923612006-12-20 09:56:44 -0700246 * Allocate a new gl_shader object, initialize it.
247 */
248struct gl_shader *
249_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
250{
251 struct gl_shader *shader;
252 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
253 shader = CALLOC_STRUCT(gl_shader);
254 if (shader) {
255 shader->Type = type;
256 shader->Name = name;
257 shader->RefCount = 1;
258 }
259 return shader;
260}
261
262
263void
264_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
265{
Brianf2923612006-12-20 09:56:44 -0700266 if (sh->Source)
267 _mesa_free((void *) sh->Source);
268 if (sh->InfoLog)
269 _mesa_free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600270 _mesa_reference_program(ctx, &sh->Program, NULL);
Brianf2923612006-12-20 09:56:44 -0700271 _mesa_free(sh);
272}
273
274
275/**
Brian3c008a02007-04-12 15:22:32 -0600276 * Set ptr to point to sh.
277 * If ptr is pointing to another shader, decrement its refcount (and delete
278 * if refcount hits zero).
279 * Then set ptr to point to sh, incrementing its refcount.
280 */
281/* XXX this could be static */
282void
283_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
284 struct gl_shader *sh)
285{
286 assert(ptr);
287 if (*ptr == sh) {
288 /* no-op */
289 return;
290 }
291 if (*ptr) {
292 /* Unreference the old shader */
293 GLboolean deleteFlag = GL_FALSE;
294 struct gl_shader *old = *ptr;
295
296 ASSERT(old->RefCount > 0);
297 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600298 /*printf("SHADER DECR %p (%d) to %d\n",
299 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600300 deleteFlag = (old->RefCount == 0);
301
302 if (deleteFlag) {
303 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
304 _mesa_free_shader(ctx, old);
305 }
306
307 *ptr = NULL;
308 }
309 assert(!*ptr);
310
311 if (sh) {
312 /* reference new */
313 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600314 /*printf("SHADER INCR %p (%d) to %d\n",
315 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600316 *ptr = sh;
317 }
318}
319
320
321/**
Brianf2923612006-12-20 09:56:44 -0700322 * Lookup a GLSL shader object.
323 */
324struct gl_shader *
325_mesa_lookup_shader(GLcontext *ctx, GLuint name)
326{
327 if (name) {
328 struct gl_shader *sh = (struct gl_shader *)
329 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
330 /* Note that both gl_shader and gl_shader_program objects are kept
331 * in the same hash table. Check the object's type to be sure it's
332 * what we're expecting.
333 */
Brianf3e8c322007-04-18 14:53:23 -0600334 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700335 return NULL;
336 }
337 return sh;
338 }
339 return NULL;
340}
341
342
Brianfa4d0362007-02-26 18:33:50 -0700343/**
Brian Paul530df582008-07-03 16:21:11 -0600344 * As above, but record an error if shader is not found.
345 */
346static struct gl_shader *
347_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
348{
349 if (!name) {
350 _mesa_error(ctx, GL_INVALID_VALUE, caller);
351 return NULL;
352 }
353 else {
354 struct gl_shader *sh = (struct gl_shader *)
355 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
356 if (!sh) {
357 _mesa_error(ctx, GL_INVALID_VALUE, caller);
358 return NULL;
359 }
360 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
361 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
362 return NULL;
363 }
364 return sh;
365 }
366}
367
368
Brian Paule01a03d2009-02-06 10:21:36 -0700369/**
370 * Return mask of GLSL_x flags by examining the MESA_GLSL env var.
371 */
372static GLbitfield
373get_shader_flags(void)
374{
375 GLbitfield flags = 0x0;
376 const char *env = _mesa_getenv("MESA_GLSL");
377
378 if (env) {
379 if (_mesa_strstr(env, "dump"))
380 flags |= GLSL_DUMP;
381 if (_mesa_strstr(env, "log"))
382 flags |= GLSL_LOG;
Brian Paulcb0de062009-09-29 10:22:32 -0600383 if (_mesa_strstr(env, "nopvert"))
384 flags |= GLSL_NOP_VERT;
385 if (_mesa_strstr(env, "nopfrag"))
386 flags |= GLSL_NOP_FRAG;
Brian Paule01a03d2009-02-06 10:21:36 -0700387 if (_mesa_strstr(env, "nopt"))
388 flags |= GLSL_NO_OPT;
389 else if (_mesa_strstr(env, "opt"))
390 flags |= GLSL_OPT;
391 if (_mesa_strstr(env, "uniform"))
392 flags |= GLSL_UNIFORMS;
Brian Paul2ee7fd82009-10-15 15:25:52 -0600393 if (_mesa_strstr(env, "useprog"))
394 flags |= GLSL_USE_PROG;
Brian Paule01a03d2009-02-06 10:21:36 -0700395 }
396
397 return flags;
398}
399
Brian Paul530df582008-07-03 16:21:11 -0600400
401/**
Brianfa4d0362007-02-26 18:33:50 -0700402 * Initialize context's shader state.
403 */
Brianf2923612006-12-20 09:56:44 -0700404void
405_mesa_init_shader_state(GLcontext * ctx)
406{
Brianfa4d0362007-02-26 18:33:50 -0700407 /* Device drivers may override these to control what kind of instructions
408 * are generated by the GLSL compiler.
409 */
410 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian Paul4031ea12009-06-17 11:57:39 -0600411 ctx->Shader.EmitContReturn = GL_TRUE;
Brian Paulc5c38352009-02-16 11:50:05 -0700412 ctx->Shader.EmitCondCodes = GL_FALSE;
Brianfa4d0362007-02-26 18:33:50 -0700413 ctx->Shader.EmitComments = GL_FALSE;
Brian Paule01a03d2009-02-06 10:21:36 -0700414 ctx->Shader.Flags = get_shader_flags();
Brian Paul65fc2ca2009-03-19 10:25:24 -0600415
416 /* Default pragma settings */
417 ctx->Shader.DefaultPragmas.IgnoreOptimize = GL_FALSE;
418 ctx->Shader.DefaultPragmas.IgnoreDebug = GL_FALSE;
419 ctx->Shader.DefaultPragmas.Optimize = GL_TRUE;
420 ctx->Shader.DefaultPragmas.Debug = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700421}
422
423
Brian5b01c5e2006-12-19 18:02:03 -0700424/**
Brian935f93f2007-03-24 16:20:02 -0600425 * Free the per-context shader-related state.
426 */
427void
428_mesa_free_shader_state(GLcontext *ctx)
429{
Brian3c008a02007-04-12 15:22:32 -0600430 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600431}
432
433
434/**
Brian5b01c5e2006-12-19 18:02:03 -0700435 * Copy string from <src> to <dst>, up to maxLength characters, returning
436 * length of <dst> in <length>.
437 * \param src the strings source
438 * \param maxLength max chars to copy
439 * \param length returns number of chars copied
440 * \param dst the string destination
441 */
442static void
443copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
444{
445 GLsizei len;
446 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
447 dst[len] = src[len];
448 if (maxLength > 0)
449 dst[len] = 0;
450 if (length)
451 *length = len;
452}
453
454
Brian Paul7acb7c12008-07-03 13:49:48 -0600455static GLboolean
456_mesa_is_program(GLcontext *ctx, GLuint name)
457{
458 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
459 return shProg ? GL_TRUE : GL_FALSE;
460}
461
462
463static GLboolean
464_mesa_is_shader(GLcontext *ctx, GLuint name)
465{
466 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
467 return shader ? GL_TRUE : GL_FALSE;
468}
469
470
Brian5b01c5e2006-12-19 18:02:03 -0700471/**
472 * Called via ctx->Driver.AttachShader()
473 */
Brian Paulfd59f192008-05-18 16:04:55 -0600474static void
Brian5b01c5e2006-12-19 18:02:03 -0700475_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
476{
Brian Paul530df582008-07-03 16:21:11 -0600477 struct gl_shader_program *shProg;
478 struct gl_shader *sh;
479 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700480
Brian Paul530df582008-07-03 16:21:11 -0600481 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
482 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700483 return;
Brian5b01c5e2006-12-19 18:02:03 -0700484
Brian Paul530df582008-07-03 16:21:11 -0600485 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600486 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600487 return;
488 }
489
Brian237b9852007-08-07 21:48:31 +0100490 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700491 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700492 if (shProg->Shaders[i] == sh) {
Ian Romanickd806d452008-09-29 12:18:06 -0700493 /* The shader is already attched to this program. The
494 * GL_ARB_shader_objects spec says:
495 *
496 * "The error INVALID_OPERATION is generated by AttachObjectARB
497 * if <obj> is already attached to <containerObj>."
498 */
499 _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader");
Brian5b01c5e2006-12-19 18:02:03 -0700500 return;
Brian34ae99d2006-12-18 08:28:54 -0700501 }
502 }
Brian5b01c5e2006-12-19 18:02:03 -0700503
504 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700505 shProg->Shaders = (struct gl_shader **)
506 _mesa_realloc(shProg->Shaders,
507 n * sizeof(struct gl_shader *),
508 (n + 1) * sizeof(struct gl_shader *));
509 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700510 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
511 return;
512 }
513
514 /* append */
Brian3c008a02007-04-12 15:22:32 -0600515 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
516 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700517 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700518}
519
520
Brian Paulfd59f192008-05-18 16:04:55 -0600521static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600522_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
523 const GLchar *name)
524{
525 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600526 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600527
528 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600529 return -1;
530 }
531
532 if (!shProg->LinkStatus) {
533 _mesa_error(ctx, GL_INVALID_OPERATION,
534 "glGetAttribLocation(program not linked)");
535 return -1;
536 }
537
538 if (!name)
539 return -1;
540
Brian Paul27341a92008-09-16 16:28:36 -0600541 if (shProg->VertexProgram) {
542 const struct gl_program_parameter_list *attribs =
543 shProg->VertexProgram->Base.Attributes;
544 if (attribs) {
545 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
546 if (i >= 0) {
547 return attribs->Parameters[i].StateIndexes[0];
548 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600549 }
550 }
551 return -1;
552}
553
554
Brian Paulfd59f192008-05-18 16:04:55 -0600555static void
Brian5b01c5e2006-12-19 18:02:03 -0700556_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
557 const GLchar *name)
558{
Brian Paul530df582008-07-03 16:21:11 -0600559 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700560 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600561 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600562 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700563
Brian Paul530df582008-07-03 16:21:11 -0600564 shProg = _mesa_lookup_shader_program_err(ctx, program,
565 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700566 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700567 return;
568 }
569
Brian9e4bae92006-12-20 09:27:42 -0700570 if (!name)
571 return;
572
573 if (strncmp(name, "gl_", 3) == 0) {
574 _mesa_error(ctx, GL_INVALID_OPERATION,
575 "glBindAttribLocation(illegal name)");
576 return;
577 }
578
Brian Paul7acb7c12008-07-03 13:49:48 -0600579 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
580 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
581 return;
582 }
583
Brian Paul6bc87492008-07-25 08:34:54 -0600584 if (shProg->LinkStatus) {
585 /* get current index/location for the attribute */
586 oldIndex = _mesa_get_attrib_location(ctx, program, name);
587 }
588 else {
589 oldIndex = -1;
590 }
591
Brian3209c3e2007-01-09 17:49:24 -0700592 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600593 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700594 if (i < 0) {
595 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600596 return;
Brian3209c3e2007-01-09 17:49:24 -0700597 }
598
Brian Paul27341a92008-09-16 16:28:36 -0600599 /*
600 * Note that this attribute binding won't go into effect until
601 * glLinkProgram is called again.
602 */
Brian34ae99d2006-12-18 08:28:54 -0700603}
604
605
Brian Paulfd59f192008-05-18 16:04:55 -0600606static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700607_mesa_create_shader(GLcontext *ctx, GLenum type)
608{
Brian65a18442006-12-19 18:46:56 -0700609 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700610 GLuint name;
611
612 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
613
614 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700615 case GL_FRAGMENT_SHADER:
616 case GL_VERTEX_SHADER:
617 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700618 break;
619 default:
620 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
621 return 0;
622 }
623
Brian65a18442006-12-19 18:46:56 -0700624 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700625
626 return name;
627}
628
629
Brian Paulfd59f192008-05-18 16:04:55 -0600630static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700631_mesa_create_program(GLcontext *ctx)
632{
633 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700634 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700635
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800636 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700637 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700638
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800639 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700640
Brian3c008a02007-04-12 15:22:32 -0600641 assert(shProg->RefCount == 1);
642
Brian5b01c5e2006-12-19 18:02:03 -0700643 return name;
644}
645
646
Brian3c008a02007-04-12 15:22:32 -0600647/**
648 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
649 * DeleteProgramARB.
650 */
Brian Paulfd59f192008-05-18 16:04:55 -0600651static void
Brian5b01c5e2006-12-19 18:02:03 -0700652_mesa_delete_program2(GLcontext *ctx, GLuint name)
653{
Brian3c008a02007-04-12 15:22:32 -0600654 /*
655 * NOTE: deleting shaders/programs works a bit differently than
656 * texture objects (and buffer objects, etc). Shader/program
657 * handles/IDs exist in the hash table until the object is really
658 * deleted (refcount==0). With texture objects, the handle/ID is
659 * removed from the hash table in glDeleteTextures() while the tex
660 * object itself might linger until its refcount goes to zero.
661 */
Brian65a18442006-12-19 18:46:56 -0700662 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700663
Brian Paul530df582008-07-03 16:21:11 -0600664 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
665 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700666 return;
Brian5b01c5e2006-12-19 18:02:03 -0700667
Brian9e4bae92006-12-20 09:27:42 -0700668 shProg->DeletePending = GL_TRUE;
669
Brian3c008a02007-04-12 15:22:32 -0600670 /* effectively, decr shProg's refcount */
671 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700672}
673
674
Brian Paulfd59f192008-05-18 16:04:55 -0600675static void
Brian5b01c5e2006-12-19 18:02:03 -0700676_mesa_delete_shader(GLcontext *ctx, GLuint shader)
677{
Brian Paul530df582008-07-03 16:21:11 -0600678 struct gl_shader *sh;
679
680 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
681 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700682 return;
Brian5b01c5e2006-12-19 18:02:03 -0700683
Brian9e4bae92006-12-20 09:27:42 -0700684 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600685
686 /* effectively, decr sh's refcount */
687 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700688}
689
690
Brian Paulfd59f192008-05-18 16:04:55 -0600691static void
Brian5b01c5e2006-12-19 18:02:03 -0700692_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
693{
Brian Paul530df582008-07-03 16:21:11 -0600694 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100695 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700696 GLuint i, j;
697
Brian Paul530df582008-07-03 16:21:11 -0600698 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
699 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700700 return;
Brian5b01c5e2006-12-19 18:02:03 -0700701
Brian237b9852007-08-07 21:48:31 +0100702 n = shProg->NumShaders;
703
Brian5b01c5e2006-12-19 18:02:03 -0700704 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700705 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700706 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600707 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700708
Brian Paul530df582008-07-03 16:21:11 -0600709 /* release */
Brian3c008a02007-04-12 15:22:32 -0600710 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700711
Brian5b01c5e2006-12-19 18:02:03 -0700712 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700713 newList = (struct gl_shader **)
714 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700715 if (!newList) {
716 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
717 return;
718 }
719 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700720 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700721 }
722 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700723 newList[j++] = shProg->Shaders[i];
724 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700725
Brian65a18442006-12-19 18:46:56 -0700726 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600727 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600728
729#ifdef DEBUG
730 /* sanity check */
731 {
732 for (j = 0; j < shProg->NumShaders; j++) {
733 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
734 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
735 assert(shProg->Shaders[j]->RefCount > 0);
736 }
737 }
738#endif
739
Brian5b01c5e2006-12-19 18:02:03 -0700740 return;
741 }
742 }
743
744 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600745 {
746 GLenum err;
747 if (_mesa_is_shader(ctx, shader))
748 err = GL_INVALID_OPERATION;
749 else if (_mesa_is_program(ctx, shader))
750 err = GL_INVALID_OPERATION;
751 else
752 err = GL_INVALID_VALUE;
753 _mesa_error(ctx, err, "glDetachProgram(shader)");
754 return;
755 }
Brian5b01c5e2006-12-19 18:02:03 -0700756}
757
758
Brian Paulffbc66b2008-07-21 13:58:50 -0600759static GLint
760sizeof_glsl_type(GLenum type)
761{
762 switch (type) {
763 case GL_FLOAT:
764 case GL_INT:
765 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600766 case GL_SAMPLER_1D:
767 case GL_SAMPLER_2D:
768 case GL_SAMPLER_3D:
769 case GL_SAMPLER_CUBE:
770 case GL_SAMPLER_1D_SHADOW:
771 case GL_SAMPLER_2D_SHADOW:
772 case GL_SAMPLER_2D_RECT_ARB:
773 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
774 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
775 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
776 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600777 return 1;
778 case GL_FLOAT_VEC2:
779 case GL_INT_VEC2:
780 case GL_BOOL_VEC2:
781 return 2;
782 case GL_FLOAT_VEC3:
783 case GL_INT_VEC3:
784 case GL_BOOL_VEC3:
785 return 3;
786 case GL_FLOAT_VEC4:
787 case GL_INT_VEC4:
788 case GL_BOOL_VEC4:
789 return 4;
790 case GL_FLOAT_MAT2:
791 case GL_FLOAT_MAT2x3:
792 case GL_FLOAT_MAT2x4:
793 return 8; /* two float[4] vectors */
794 case GL_FLOAT_MAT3:
795 case GL_FLOAT_MAT3x2:
796 case GL_FLOAT_MAT3x4:
797 return 12; /* three float[4] vectors */
798 case GL_FLOAT_MAT4:
799 case GL_FLOAT_MAT4x2:
800 case GL_FLOAT_MAT4x3:
801 return 16; /* four float[4] vectors */
802 default:
803 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
804 return 1;
805 }
806}
807
808
Brian Pauleda291e2008-08-06 16:26:47 -0600809static GLboolean
810is_boolean_type(GLenum type)
811{
812 switch (type) {
813 case GL_BOOL:
814 case GL_BOOL_VEC2:
815 case GL_BOOL_VEC3:
816 case GL_BOOL_VEC4:
817 return GL_TRUE;
818 default:
819 return GL_FALSE;
820 }
821}
822
823
824static GLboolean
825is_integer_type(GLenum type)
826{
827 switch (type) {
828 case GL_INT:
829 case GL_INT_VEC2:
830 case GL_INT_VEC3:
831 case GL_INT_VEC4:
832 return GL_TRUE;
833 default:
834 return GL_FALSE;
835 }
836}
837
838
Brian Paulc4ffbf02009-02-18 17:46:00 -0700839static GLboolean
840is_sampler_type(GLenum type)
841{
842 switch (type) {
843 case GL_SAMPLER_1D:
844 case GL_SAMPLER_2D:
845 case GL_SAMPLER_3D:
846 case GL_SAMPLER_CUBE:
847 case GL_SAMPLER_1D_SHADOW:
848 case GL_SAMPLER_2D_SHADOW:
849 case GL_SAMPLER_2D_RECT_ARB:
850 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
851 case GL_SAMPLER_1D_ARRAY_EXT:
852 case GL_SAMPLER_2D_ARRAY_EXT:
853 return GL_TRUE;
854 default:
855 return GL_FALSE;
856 }
857}
858
859
Brian Paulfd59f192008-05-18 16:04:55 -0600860static void
Brian5b01c5e2006-12-19 18:02:03 -0700861_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
862 GLsizei maxLength, GLsizei *length, GLint *size,
863 GLenum *type, GLchar *nameOut)
864{
Brian Paul27341a92008-09-16 16:28:36 -0600865 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600866 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700867
Brian Paul530df582008-07-03 16:21:11 -0600868 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
869 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700870 return;
Brian5b01c5e2006-12-19 18:02:03 -0700871
Brian Paul27341a92008-09-16 16:28:36 -0600872 if (shProg->VertexProgram)
873 attribs = shProg->VertexProgram->Base.Attributes;
874
875 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600876 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700877 return;
878 }
879
Brian Paul27341a92008-09-16 16:28:36 -0600880 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
881
Brian5b01c5e2006-12-19 18:02:03 -0700882 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600883 *size = attribs->Parameters[index].Size
884 / sizeof_glsl_type(attribs->Parameters[index].DataType);
885
Brian Paulade50832008-05-14 16:09:46 -0600886 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600887 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700888}
889
890
Brian Pauleda291e2008-08-06 16:26:47 -0600891static struct gl_program_parameter *
892get_uniform_parameter(const struct gl_shader_program *shProg, GLuint index)
893{
Brian Paula531a5c2009-08-13 13:44:01 -0600894 const struct gl_program *prog = NULL;
Brian Pauleda291e2008-08-06 16:26:47 -0600895 GLint progPos;
896
897 progPos = shProg->Uniforms->Uniforms[index].VertPos;
898 if (progPos >= 0) {
899 prog = &shProg->VertexProgram->Base;
900 }
901 else {
902 progPos = shProg->Uniforms->Uniforms[index].FragPos;
903 if (progPos >= 0) {
904 prog = &shProg->FragmentProgram->Base;
905 }
906 }
907
908 if (!prog || progPos < 0)
909 return NULL; /* should never happen */
910
911 return &prog->Parameters->Parameters[progPos];
912}
913
914
Brian5b01c5e2006-12-19 18:02:03 -0700915/**
916 * Called via ctx->Driver.GetActiveUniform().
917 */
Brian Paulfd59f192008-05-18 16:04:55 -0600918static void
Brian5b01c5e2006-12-19 18:02:03 -0700919_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
920 GLsizei maxLength, GLsizei *length, GLint *size,
921 GLenum *type, GLchar *nameOut)
922{
Brian Paul530df582008-07-03 16:21:11 -0600923 const struct gl_shader_program *shProg;
Brian Paula531a5c2009-08-13 13:44:01 -0600924 const struct gl_program *prog = NULL;
Brian Paul369d1852009-02-11 08:16:14 -0700925 const struct gl_program_parameter *param;
Brian Paulade50832008-05-14 16:09:46 -0600926 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700927
Brian Paul530df582008-07-03 16:21:11 -0600928 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
929 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700930 return;
Brian5b01c5e2006-12-19 18:02:03 -0700931
Brian Paulade50832008-05-14 16:09:46 -0600932 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700933 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
934 return;
935 }
936
Brian Paulade50832008-05-14 16:09:46 -0600937 progPos = shProg->Uniforms->Uniforms[index].VertPos;
938 if (progPos >= 0) {
939 prog = &shProg->VertexProgram->Base;
940 }
941 else {
942 progPos = shProg->Uniforms->Uniforms[index].FragPos;
943 if (progPos >= 0) {
944 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600945 }
946 }
947
Brian Paulade50832008-05-14 16:09:46 -0600948 if (!prog || progPos < 0)
949 return; /* should never happen */
950
Brian Paul369d1852009-02-11 08:16:14 -0700951 ASSERT(progPos < prog->Parameters->NumParameters);
952 param = &prog->Parameters->Parameters[progPos];
953
954 if (nameOut) {
955 copy_string(nameOut, maxLength, length, param->Name);
956 }
957
958 if (size) {
959 GLint typeSize = sizeof_glsl_type(param->DataType);
960 if (param->Size > typeSize) {
961 /* This is an array.
962 * Array elements are placed on vector[4] boundaries so they're
963 * a multiple of four floats. We round typeSize up to next multiple
964 * of four to get the right size below.
965 */
966 typeSize = (typeSize + 3) & ~3;
967 }
968 /* Note that the returned size is in units of the <type>, not bytes */
969 *size = param->Size / typeSize;
970 }
971
972 if (type) {
973 *type = param->DataType;
974 }
Brian5b01c5e2006-12-19 18:02:03 -0700975}
976
977
978/**
979 * Called via ctx->Driver.GetAttachedShaders().
980 */
Brian Paulfd59f192008-05-18 16:04:55 -0600981static void
Brian5b01c5e2006-12-19 18:02:03 -0700982_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
983 GLsizei *count, GLuint *obj)
984{
Brian Paul530df582008-07-03 16:21:11 -0600985 struct gl_shader_program *shProg =
986 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700987 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600988 GLuint i;
989 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700990 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700991 }
992 if (count)
993 *count = i;
994 }
Brian5b01c5e2006-12-19 18:02:03 -0700995}
996
997
Brian Paulfd59f192008-05-18 16:04:55 -0600998static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700999_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -07001000{
Ian Romanick905d8e02008-09-29 12:27:00 -07001001 GLint handle = 0;
1002
1003 if (pname == GL_PROGRAM_OBJECT_ARB) {
1004 CALL_GetIntegerv(ctx->Exec, (GL_CURRENT_PROGRAM, &handle));
1005 } else {
Brian34ae99d2006-12-18 08:28:54 -07001006 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
1007 }
Ian Romanick905d8e02008-09-29 12:27:00 -07001008
1009 return handle;
Brian34ae99d2006-12-18 08:28:54 -07001010}
1011
1012
Brian Paulfd59f192008-05-18 16:04:55 -06001013static void
Brian5b01c5e2006-12-19 18:02:03 -07001014_mesa_get_programiv(GLcontext *ctx, GLuint program,
1015 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -07001016{
Brian Paul27341a92008-09-16 16:28:36 -06001017 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -07001018 struct gl_shader_program *shProg
1019 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -07001020
Brian65a18442006-12-19 18:46:56 -07001021 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001022 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -07001023 return;
1024 }
1025
Brian Paul27341a92008-09-16 16:28:36 -06001026 if (shProg->VertexProgram)
1027 attribs = shProg->VertexProgram->Base.Attributes;
1028 else
1029 attribs = NULL;
1030
Brian5b01c5e2006-12-19 18:02:03 -07001031 switch (pname) {
1032 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001033 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -07001034 break;
1035 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -07001036 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -07001037 break;
Brian5b01c5e2006-12-19 18:02:03 -07001038 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -07001039 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -07001040 break;
1041 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001042 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001043 break;
1044 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -07001045 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -07001046 break;
1047 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -06001048 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001049 break;
1050 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -06001051 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -07001052 break;
1053 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -06001054 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001055 break;
1056 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -06001057 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -06001058 if (*params > 0)
1059 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -07001060 break;
Brian Paulbda6ad22008-08-06 12:45:14 -06001061 case GL_PROGRAM_BINARY_LENGTH_OES:
1062 *params = 0;
1063 break;
Brian34ae99d2006-12-18 08:28:54 -07001064 default:
Brian5b01c5e2006-12-19 18:02:03 -07001065 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
1066 return;
Brian34ae99d2006-12-18 08:28:54 -07001067 }
Brian5b01c5e2006-12-19 18:02:03 -07001068}
Brian34ae99d2006-12-18 08:28:54 -07001069
Brian34ae99d2006-12-18 08:28:54 -07001070
Brian Paulfd59f192008-05-18 16:04:55 -06001071static void
Brian5b01c5e2006-12-19 18:02:03 -07001072_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
1073{
Brian Paul530df582008-07-03 16:21:11 -06001074 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -07001075
1076 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -07001077 return;
1078 }
Brian65a18442006-12-19 18:46:56 -07001079
Brian5b01c5e2006-12-19 18:02:03 -07001080 switch (pname) {
1081 case GL_SHADER_TYPE:
1082 *params = shader->Type;
1083 break;
1084 case GL_DELETE_STATUS:
1085 *params = shader->DeletePending;
1086 break;
1087 case GL_COMPILE_STATUS:
1088 *params = shader->CompileStatus;
1089 break;
1090 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001091 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001092 break;
1093 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -06001094 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -07001095 break;
1096 default:
1097 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
1098 return;
1099 }
1100}
1101
1102
Brian Paulfd59f192008-05-18 16:04:55 -06001103static void
Brian5b01c5e2006-12-19 18:02:03 -07001104_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
1105 GLsizei *length, GLchar *infoLog)
1106{
Brian65a18442006-12-19 18:46:56 -07001107 struct gl_shader_program *shProg
1108 = _mesa_lookup_shader_program(ctx, program);
1109 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -07001110 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
1111 return;
1112 }
Brian65a18442006-12-19 18:46:56 -07001113 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001114}
1115
1116
Brian Paulfd59f192008-05-18 16:04:55 -06001117static void
Brian5b01c5e2006-12-19 18:02:03 -07001118_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
1119 GLsizei *length, GLchar *infoLog)
1120{
Brian65a18442006-12-19 18:46:56 -07001121 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1122 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001123 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1124 return;
1125 }
Brian65a18442006-12-19 18:46:56 -07001126 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001127}
1128
1129
1130/**
1131 * Called via ctx->Driver.GetShaderSource().
1132 */
Brian Paulfd59f192008-05-18 16:04:55 -06001133static void
Brian5b01c5e2006-12-19 18:02:03 -07001134_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1135 GLsizei *length, GLchar *sourceOut)
1136{
Brian Paul530df582008-07-03 16:21:11 -06001137 struct gl_shader *sh;
1138 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001139 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001140 return;
1141 }
Brian65a18442006-12-19 18:46:56 -07001142 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001143}
1144
1145
Brian Paul5b982362008-08-06 13:07:09 -06001146static void
1147get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1148{
1149 switch (type) {
1150 case GL_FLOAT_MAT2:
1151 *rows = *cols = 2;
1152 break;
1153 case GL_FLOAT_MAT2x3:
1154 *rows = 3;
1155 *cols = 2;
1156 break;
1157 case GL_FLOAT_MAT2x4:
1158 *rows = 4;
1159 *cols = 2;
1160 break;
1161 case GL_FLOAT_MAT3:
1162 *rows = 3;
1163 *cols = 3;
1164 break;
1165 case GL_FLOAT_MAT3x2:
1166 *rows = 2;
1167 *cols = 3;
1168 break;
1169 case GL_FLOAT_MAT3x4:
1170 *rows = 4;
1171 *cols = 3;
1172 break;
1173 case GL_FLOAT_MAT4:
1174 *rows = 4;
1175 *cols = 4;
1176 break;
1177 case GL_FLOAT_MAT4x2:
1178 *rows = 2;
1179 *cols = 4;
1180 break;
1181 case GL_FLOAT_MAT4x3:
1182 *rows = 3;
1183 *cols = 4;
1184 break;
1185 default:
1186 *rows = *cols = 0;
1187 }
1188}
1189
1190
1191/**
1192 * Determine the number of rows and columns occupied by a uniform
Brian Paulea9568d2008-09-16 08:55:54 -06001193 * according to its datatype. For non-matrix types (such as GL_FLOAT_VEC4),
1194 * the number of rows = 1 and cols = number of elements in the vector.
Brian Paul5b982362008-08-06 13:07:09 -06001195 */
1196static void
1197get_uniform_rows_cols(const struct gl_program_parameter *p,
1198 GLint *rows, GLint *cols)
1199{
1200 get_matrix_dims(p->DataType, rows, cols);
1201 if (*rows == 0 && *cols == 0) {
1202 /* not a matrix type, probably a float or vector */
Brian Paulea9568d2008-09-16 08:55:54 -06001203 if (p->Size <= 4) {
1204 *rows = 1;
1205 *cols = p->Size;
1206 }
1207 else {
1208 *rows = p->Size / 4 + 1;
1209 if (p->Size % 4 == 0)
1210 *cols = 4;
1211 else
1212 *cols = p->Size % 4;
1213 }
Brian Paul5b982362008-08-06 13:07:09 -06001214 }
1215}
1216
1217
Brian5b01c5e2006-12-19 18:02:03 -07001218/**
Brian Paul4ef7a932009-02-11 09:03:16 -07001219 * Helper for get_uniform[fi]v() functions.
1220 * Given a shader program name and uniform location, return a pointer
1221 * to the shader program and return the program parameter position.
Brian5b01c5e2006-12-19 18:02:03 -07001222 */
Brian Paul4ef7a932009-02-11 09:03:16 -07001223static void
1224lookup_uniform_parameter(GLcontext *ctx, GLuint program, GLint location,
1225 struct gl_program **progOut, GLint *paramPosOut)
Brian5b01c5e2006-12-19 18:02:03 -07001226{
Brian65a18442006-12-19 18:46:56 -07001227 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001228 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian Paul4ef7a932009-02-11 09:03:16 -07001229 struct gl_program *prog = NULL;
1230 GLint progPos = -1;
Brian Paulade50832008-05-14 16:09:46 -06001231
Brian Paul4ef7a932009-02-11 09:03:16 -07001232 /* if shProg is NULL, we'll have already recorded an error */
1233
1234 if (shProg) {
1235 if (!shProg->Uniforms ||
1236 location < 0 ||
1237 location >= (GLint) shProg->Uniforms->NumUniforms) {
1238 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
1239 }
1240 else {
1241 /* OK, find the gl_program and program parameter location */
Brian Paulade50832008-05-14 16:09:46 -06001242 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1243 if (progPos >= 0) {
1244 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001245 }
Brian Paulade50832008-05-14 16:09:46 -06001246 else {
1247 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1248 if (progPos >= 0) {
1249 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001250 }
Brian Paulade50832008-05-14 16:09:46 -06001251 }
Brian5b01c5e2006-12-19 18:02:03 -07001252 }
1253 }
Brian Paul4ef7a932009-02-11 09:03:16 -07001254
1255 *progOut = prog;
1256 *paramPosOut = progPos;
Brian Paul2be54a82008-07-08 16:17:04 -06001257}
1258
1259
1260/**
1261 * Called via ctx->Driver.GetUniformfv().
1262 */
1263static void
1264_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1265 GLfloat *params)
1266{
Brian Paul4ef7a932009-02-11 09:03:16 -07001267 struct gl_program *prog;
1268 GLint paramPos;
1269
1270 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1271
1272 if (prog) {
1273 const struct gl_program_parameter *p =
1274 &prog->Parameters->Parameters[paramPos];
1275 GLint rows, cols, i, j, k;
1276
1277 get_uniform_rows_cols(p, &rows, &cols);
1278
1279 k = 0;
1280 for (i = 0; i < rows; i++) {
1281 for (j = 0; j < cols; j++ ) {
1282 params[k++] = prog->Parameters->ParameterValues[paramPos+i][j];
1283 }
1284 }
1285 }
Brian Paul2be54a82008-07-08 16:17:04 -06001286}
1287
1288
1289/**
1290 * Called via ctx->Driver.GetUniformiv().
Brian Paul4ef7a932009-02-11 09:03:16 -07001291 * \sa _mesa_get_uniformfv, only difference is a cast.
Brian Paul2be54a82008-07-08 16:17:04 -06001292 */
1293static void
1294_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1295 GLint *params)
1296{
Brian Paul4ef7a932009-02-11 09:03:16 -07001297 struct gl_program *prog;
1298 GLint paramPos;
1299
1300 lookup_uniform_parameter(ctx, program, location, &prog, &paramPos);
1301
1302 if (prog) {
1303 const struct gl_program_parameter *p =
1304 &prog->Parameters->Parameters[paramPos];
1305 GLint rows, cols, i, j, k;
1306
1307 get_uniform_rows_cols(p, &rows, &cols);
1308
1309 k = 0;
1310 for (i = 0; i < rows; i++) {
1311 for (j = 0; j < cols; j++ ) {
1312 params[k++] = (GLint) prog->Parameters->ParameterValues[paramPos+i][j];
1313 }
1314 }
Brian Paul2be54a82008-07-08 16:17:04 -06001315 }
Brian5b01c5e2006-12-19 18:02:03 -07001316}
1317
1318
1319/**
Brian Pauleda291e2008-08-06 16:26:47 -06001320 * The value returned by GetUniformLocation actually encodes two things:
1321 * 1. the index into the prog->Uniforms[] array for the uniform
1322 * 2. an offset in the prog->ParameterValues[] array for specifying array
1323 * elements or structure fields.
1324 * This function merges those two values.
1325 */
1326static void
1327merge_location_offset(GLint *location, GLint offset)
1328{
1329 *location = *location | (offset << 16);
1330}
1331
1332
1333/**
1334 * Seperate the uniform location and parameter offset. See above.
1335 */
1336static void
1337split_location_offset(GLint *location, GLint *offset)
1338{
1339 *offset = (*location >> 16);
1340 *location = *location & 0xffff;
1341}
1342
1343
1344/**
Brian5b01c5e2006-12-19 18:02:03 -07001345 * Called via ctx->Driver.GetUniformLocation().
Brian Pauleda291e2008-08-06 16:26:47 -06001346 *
1347 * The return value will encode two values, the uniform location and an
1348 * offset (used for arrays, structs).
Brian5b01c5e2006-12-19 18:02:03 -07001349 */
Brian Paulfd59f192008-05-18 16:04:55 -06001350static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001351_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1352{
Brian Pauleda291e2008-08-06 16:26:47 -06001353 GLint offset = 0, location = -1;
1354
Brian Paul530df582008-07-03 16:21:11 -06001355 struct gl_shader_program *shProg =
1356 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1357
Brian Paulade50832008-05-14 16:09:46 -06001358 if (!shProg)
1359 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001360
Brian Paule06565b2008-07-04 09:58:55 -06001361 if (shProg->LinkStatus == GL_FALSE) {
1362 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1363 return -1;
1364 }
1365
Brian Paul530df582008-07-03 16:21:11 -06001366 /* XXX we should return -1 if the uniform was declared, but not
1367 * actually used.
1368 */
1369
Brian Pauleda291e2008-08-06 16:26:47 -06001370 /* XXX we need to be able to parse uniform names for structs and arrays
1371 * such as:
1372 * mymatrix[1]
1373 * mystruct.field1
1374 */
1375
1376 {
1377 /* handle 1-dimension arrays here... */
1378 char *c = strchr(name, '[');
1379 if (c) {
1380 /* truncate name at [ */
1381 const GLint len = c - name;
1382 GLchar *newName = _mesa_malloc(len + 1);
1383 if (!newName)
1384 return -1; /* out of mem */
1385 _mesa_memcpy(newName, name, len);
1386 newName[len] = 0;
1387
1388 location = _mesa_lookup_uniform(shProg->Uniforms, newName);
1389 if (location >= 0) {
1390 const GLint element = _mesa_atoi(c + 1);
1391 if (element > 0) {
1392 /* get type of the uniform array element */
1393 struct gl_program_parameter *p;
1394 p = get_uniform_parameter(shProg, location);
1395 if (p) {
1396 GLint rows, cols;
1397 get_matrix_dims(p->DataType, &rows, &cols);
1398 if (rows < 1)
1399 rows = 1;
1400 offset = element * rows;
1401 }
1402 }
1403 }
1404
1405 _mesa_free(newName);
1406 }
1407 }
1408
1409 if (location < 0) {
1410 location = _mesa_lookup_uniform(shProg->Uniforms, name);
1411 }
1412
1413 if (location >= 0) {
1414 merge_location_offset(&location, offset);
1415 }
1416
1417 return location;
Brian5b01c5e2006-12-19 18:02:03 -07001418}
1419
1420
Brian34ae99d2006-12-18 08:28:54 -07001421
Brian5b01c5e2006-12-19 18:02:03 -07001422/**
1423 * Called via ctx->Driver.ShaderSource()
1424 */
Brian Paulfd59f192008-05-18 16:04:55 -06001425static void
Brian5b01c5e2006-12-19 18:02:03 -07001426_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001427{
Brian Paul530df582008-07-03 16:21:11 -06001428 struct gl_shader *sh;
1429
1430 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1431 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001432 return;
Brian34ae99d2006-12-18 08:28:54 -07001433
Brian34ae99d2006-12-18 08:28:54 -07001434 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001435 if (sh->Source) {
1436 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001437 }
Brian65a18442006-12-19 18:46:56 -07001438 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001439 sh->CompileStatus = GL_FALSE;
Brian Paulf7783ba2009-08-04 15:35:48 -06001440#ifdef DEBUG
1441 sh->SourceChecksum = _mesa_str_checksum(sh->Source);
1442#endif
Brian34ae99d2006-12-18 08:28:54 -07001443}
1444
1445
Brian5b01c5e2006-12-19 18:02:03 -07001446/**
1447 * Called via ctx->Driver.CompileShader()
1448 */
Brian Paulfd59f192008-05-18 16:04:55 -06001449static void
Brian5b01c5e2006-12-19 18:02:03 -07001450_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001451{
Brian Paul530df582008-07-03 16:21:11 -06001452 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001453
Brian Paul530df582008-07-03 16:21:11 -06001454 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1455 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001456 return;
Brian34ae99d2006-12-18 08:28:54 -07001457
Brian Paul65fc2ca2009-03-19 10:25:24 -06001458 /* set default pragma state for shader */
1459 sh->Pragmas = ctx->Shader.DefaultPragmas;
1460
Brian Paulcb136e02009-01-22 10:34:15 -07001461 /* this call will set the sh->CompileStatus field to indicate if
1462 * compilation was successful.
1463 */
1464 (void) _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001465}
1466
1467
Brian5b01c5e2006-12-19 18:02:03 -07001468/**
1469 * Called via ctx->Driver.LinkProgram()
1470 */
Brian Paulfd59f192008-05-18 16:04:55 -06001471static void
Brian5b01c5e2006-12-19 18:02:03 -07001472_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001473{
Brian65a18442006-12-19 18:46:56 -07001474 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001475
Brian Paul530df582008-07-03 16:21:11 -06001476 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1477 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001478 return;
Brian34ae99d2006-12-18 08:28:54 -07001479
Briandf43fb62008-05-06 23:08:51 -06001480 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1481
Brianc1771912007-02-16 09:56:19 -07001482 _slang_link(ctx, program, shProg);
Brian Paulac3c8e32009-09-14 17:32:03 -06001483
1484 /* debug code */
1485 if (0) {
1486 GLuint i;
1487
1488 _mesa_printf("Link %u shaders in program %u: %s\n",
1489 shProg->NumShaders, shProg->Name,
1490 shProg->LinkStatus ? "Success" : "Failed");
1491
1492 for (i = 0; i < shProg->NumShaders; i++) {
1493 _mesa_printf(" shader %u, type 0x%x\n",
1494 shProg->Shaders[i]->Name,
1495 shProg->Shaders[i]->Type);
1496 }
1497 }
Brian34ae99d2006-12-18 08:28:54 -07001498}
1499
1500
1501/**
Brian Paul346250b2009-10-23 16:31:48 -06001502 * Print basic shader info (for debug).
1503 */
1504static void
1505print_shader_info(const struct gl_shader_program *shProg)
1506{
1507 GLuint i;
1508
1509 _mesa_printf("Mesa: glUseProgram(%u)\n", shProg->Name);
1510 for (i = 0; i < shProg->NumShaders; i++) {
1511 const char *s;
1512 switch (shProg->Shaders[i]->Type) {
1513 case GL_VERTEX_SHADER:
1514 s = "vertex";
1515 break;
1516 case GL_FRAGMENT_SHADER:
1517 s = "fragment";
1518 break;
1519 case GL_GEOMETRY_SHADER:
1520 s = "geometry";
1521 break;
1522 default:
1523 s = "";
1524 }
1525 _mesa_printf(" %s shader %u, checksum %u\n", s,
1526 shProg->Shaders[i]->Name,
1527 shProg->Shaders[i]->SourceChecksum);
1528 }
1529 if (shProg->VertexProgram)
1530 _mesa_printf(" vert prog %u\n", shProg->VertexProgram->Base.Id);
1531 if (shProg->FragmentProgram)
1532 _mesa_printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id);
1533}
1534
1535
1536/**
Brian5b01c5e2006-12-19 18:02:03 -07001537 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001538 */
Brian5b01c5e2006-12-19 18:02:03 -07001539void
1540_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001541{
Brian3c008a02007-04-12 15:22:32 -06001542 struct gl_shader_program *shProg;
1543
Brian00d63aa2007-02-03 11:35:02 -07001544 if (ctx->Shader.CurrentProgram &&
1545 ctx->Shader.CurrentProgram->Name == program) {
1546 /* no-op */
1547 return;
1548 }
1549
Brian5b01c5e2006-12-19 18:02:03 -07001550 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001551 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001552 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001553 return;
1554 }
1555 if (!shProg->LinkStatus) {
Brian Paul621c9992009-02-18 13:28:12 -07001556 _mesa_error(ctx, GL_INVALID_OPERATION,
1557 "glUseProgram(program %u not linked)", program);
Brian5b01c5e2006-12-19 18:02:03 -07001558 return;
1559 }
Brian Paul4eda17d2009-03-13 09:11:42 -06001560
1561 /* debug code */
Brian Paul2ee7fd82009-10-15 15:25:52 -06001562 if (ctx->Shader.Flags & GLSL_USE_PROG) {
Brian Paul346250b2009-10-23 16:31:48 -06001563 print_shader_info(shProg);
Brian Paul4eda17d2009-03-13 09:11:42 -06001564 }
Brian5b01c5e2006-12-19 18:02:03 -07001565 }
1566 else {
Brian3c008a02007-04-12 15:22:32 -06001567 shProg = NULL;
1568 }
1569
Brian Paulb44304e2009-10-27 20:09:33 -06001570 if (ctx->Shader.CurrentProgram != shProg) {
1571 FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS);
1572 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
1573 }
Brian5b01c5e2006-12-19 18:02:03 -07001574}
Brian34ae99d2006-12-18 08:28:54 -07001575
Brian5b01c5e2006-12-19 18:02:03 -07001576
Brian Paulade50832008-05-14 16:09:46 -06001577
1578/**
Brian Paul517401a2008-11-06 15:04:11 -07001579 * Update the vertex/fragment program's TexturesUsed array.
1580 *
1581 * This needs to be called after glUniform(set sampler var) is called.
1582 * A call to glUniform(samplerVar, value) causes a sampler to point to a
1583 * particular texture unit. We know the sampler's texture target
1584 * (1D/2D/3D/etc) from compile time but the sampler's texture unit is
1585 * set by glUniform() calls.
1586 *
1587 * So, scan the program->SamplerUnits[] and program->SamplerTargets[]
1588 * information to update the prog->TexturesUsed[] values.
1589 * Each value of TexturesUsed[unit] is one of zero, TEXTURE_1D_INDEX,
1590 * TEXTURE_2D_INDEX, TEXTURE_3D_INDEX, etc.
1591 * We'll use that info for state validation before rendering.
Brian Paulade50832008-05-14 16:09:46 -06001592 */
Brian Paul517401a2008-11-06 15:04:11 -07001593void
1594_mesa_update_shader_textures_used(struct gl_program *prog)
Brian Paulade50832008-05-14 16:09:46 -06001595{
1596 GLuint s;
1597
1598 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1599
1600 for (s = 0; s < MAX_SAMPLERS; s++) {
1601 if (prog->SamplersUsed & (1 << s)) {
Brian Paulf05344f2009-08-26 10:58:06 -06001602 GLuint unit = prog->SamplerUnits[s];
1603 GLuint tgt = prog->SamplerTargets[s];
1604 assert(unit < MAX_TEXTURE_IMAGE_UNITS);
1605 assert(tgt < NUM_TEXTURE_TARGETS);
1606 prog->TexturesUsed[unit] |= (1 << tgt);
Brian Paulade50832008-05-14 16:09:46 -06001607 }
1608 }
1609}
1610
1611
1612/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001613 * Check if the type given by userType is allowed to set a uniform of the
1614 * target type. Generally, equivalence is required, but setting Boolean
1615 * uniforms can be done with glUniformiv or glUniformfv.
1616 */
1617static GLboolean
1618compatible_types(GLenum userType, GLenum targetType)
1619{
1620 if (userType == targetType)
1621 return GL_TRUE;
1622
1623 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1624 return GL_TRUE;
1625
1626 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1627 userType == GL_INT_VEC2))
1628 return GL_TRUE;
1629
1630 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1631 userType == GL_INT_VEC3))
1632 return GL_TRUE;
1633
1634 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1635 userType == GL_INT_VEC4))
1636 return GL_TRUE;
1637
Brianb36749d2008-07-21 20:42:05 -06001638 if (is_sampler_type(targetType) && userType == GL_INT)
1639 return GL_TRUE;
1640
Brian Paulffbc66b2008-07-21 13:58:50 -06001641 return GL_FALSE;
1642}
1643
1644
1645/**
Brian Paulade50832008-05-14 16:09:46 -06001646 * Set the value of a program's uniform variable.
1647 * \param program the program whose uniform to update
Brian Pauleda291e2008-08-06 16:26:47 -06001648 * \param index the index of the program parameter for the uniform
1649 * \param offset additional parameter slot offset (for arrays)
Brian Paulc4ffbf02009-02-18 17:46:00 -07001650 * \param type the incoming datatype of 'values'
Brian Paulade50832008-05-14 16:09:46 -06001651 * \param count the number of uniforms to set
Brian Paulc4ffbf02009-02-18 17:46:00 -07001652 * \param elems number of elements per uniform (1, 2, 3 or 4)
1653 * \param values the new values, of datatype 'type'
Brian Paulade50832008-05-14 16:09:46 -06001654 */
1655static void
Brian Pauleda291e2008-08-06 16:26:47 -06001656set_program_uniform(GLcontext *ctx, struct gl_program *program,
1657 GLint index, GLint offset,
1658 GLenum type, GLsizei count, GLint elems,
1659 const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001660{
Brian Paul6df38e62009-08-26 14:35:45 -06001661 const struct gl_program_parameter *param =
Brian Paul949e7382008-11-05 09:17:55 -07001662 &program->Parameters->Parameters[index];
1663
Brian Pauleda291e2008-08-06 16:26:47 -06001664 assert(offset >= 0);
Brian Paulc4ffbf02009-02-18 17:46:00 -07001665 assert(elems >= 1);
1666 assert(elems <= 4);
Brian Pauleda291e2008-08-06 16:26:47 -06001667
Brian Paul949e7382008-11-05 09:17:55 -07001668 if (!compatible_types(type, param->DataType)) {
Brian Paulffbc66b2008-07-21 13:58:50 -06001669 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1670 return;
1671 }
1672
Michal Krolc5c71302008-08-07 16:23:15 +02001673 if (index + offset > (GLint) program->Parameters->Size) {
Brian Pauleda291e2008-08-06 16:26:47 -06001674 /* out of bounds! */
1675 return;
1676 }
1677
Brian Paul949e7382008-11-05 09:17:55 -07001678 if (param->Type == PROGRAM_SAMPLER) {
Brian Paulade50832008-05-14 16:09:46 -06001679 /* This controls which texture unit which is used by a sampler */
Brian Paulbabb5ba2009-08-26 14:29:50 -06001680 GLboolean changed = GL_FALSE;
Brian Paul2b4f0212009-02-11 09:12:34 -07001681 GLint i;
Brian Paulade50832008-05-14 16:09:46 -06001682
Brian Paul6df38e62009-08-26 14:35:45 -06001683 /* this should have been caught by the compatible_types() check */
1684 ASSERT(type == GL_INT);
Brian Paulade50832008-05-14 16:09:46 -06001685
Brian Paul6df38e62009-08-26 14:35:45 -06001686 /* loop over number of samplers to change */
Brian Paul2b4f0212009-02-11 09:12:34 -07001687 for (i = 0; i < count; i++) {
Brian Paul04d17072009-08-26 11:39:24 -06001688 GLuint sampler =
1689 (GLuint) program->Parameters->ParameterValues[index + offset + i][0];
1690 GLuint texUnit = ((GLuint *) values)[i];
Brian Paulade50832008-05-14 16:09:46 -06001691
Brian Paul2b4f0212009-02-11 09:12:34 -07001692 /* check that the sampler (tex unit index) is legal */
1693 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1694 _mesa_error(ctx, GL_INVALID_VALUE,
1695 "glUniform1(invalid sampler/tex unit index)");
1696 return;
1697 }
1698
1699 /* This maps a sampler to a texture unit: */
1700 if (sampler < MAX_SAMPLERS) {
Brian Paul04d17072009-08-26 11:39:24 -06001701#if 0
1702 _mesa_printf("Set program %p sampler %d '%s' to unit %u\n",
1703 program, sampler, param->Name, texUnit);
1704#endif
Brian Paulbabb5ba2009-08-26 14:29:50 -06001705 if (program->SamplerUnits[sampler] != texUnit) {
1706 program->SamplerUnits[sampler] = texUnit;
1707 changed = GL_TRUE;
1708 }
Brian Paul2b4f0212009-02-11 09:12:34 -07001709 }
Brian Paulade50832008-05-14 16:09:46 -06001710 }
1711
Brian Paulbabb5ba2009-08-26 14:29:50 -06001712 if (changed) {
1713 /* When a sampler's value changes it usually requires rewriting
1714 * a GPU program's TEX instructions since there may not be a
1715 * sampler->texture lookup table. We signal this with the
1716 * ProgramStringNotify() callback.
1717 */
1718 FLUSH_VERTICES(ctx, _NEW_TEXTURE | _NEW_PROGRAM);
1719 _mesa_update_shader_textures_used(program);
1720 ctx->Driver.ProgramStringNotify(ctx, program->Target, program);
1721 }
Brian Paulade50832008-05-14 16:09:46 -06001722 }
1723 else {
1724 /* ordinary uniform variable */
Brian Paul6df38e62009-08-26 14:35:45 -06001725 const GLboolean isUniformBool = is_boolean_type(param->DataType);
1726 const GLboolean areIntValues = is_integer_type(type);
Brian Paul2c1ea072009-02-11 08:46:21 -07001727 const GLint slots = (param->Size + 3) / 4;
1728 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paul6df38e62009-08-26 14:35:45 -06001729 GLsizei k, i;
Brian Paulade50832008-05-14 16:09:46 -06001730
Brian Paul2c1ea072009-02-11 08:46:21 -07001731 if (param->Size > typeSize) {
1732 /* an array */
1733 /* we'll ignore extra data below */
1734 }
1735 else {
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001736 /* non-array: count must be at most one; count == 0 is handled by the loop below */
1737 if (count > 1) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001738 _mesa_error(ctx, GL_INVALID_OPERATION,
1739 "glUniform(uniform is not an array)");
1740 return;
1741 }
Brian Paulade50832008-05-14 16:09:46 -06001742 }
1743
Brian Paulc4ffbf02009-02-18 17:46:00 -07001744 /* loop over number of array elements */
Brian Paulade50832008-05-14 16:09:46 -06001745 for (k = 0; k < count; k++) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001746 GLfloat *uniformVal;
1747
Brian Paulb9d8f712009-02-18 17:40:44 -07001748 if (offset + k >= slots) {
Brian Paul2c1ea072009-02-11 08:46:21 -07001749 /* Extra array data is ignored */
1750 break;
1751 }
1752
Brian Paulc4ffbf02009-02-18 17:46:00 -07001753 /* uniformVal (the destination) is always float[4] */
Brian Paul2c1ea072009-02-11 08:46:21 -07001754 uniformVal = program->Parameters->ParameterValues[index + offset + k];
Brian Paulc4ffbf02009-02-18 17:46:00 -07001755
1756 if (areIntValues) {
1757 /* convert user's ints to floats */
Brian Paulade50832008-05-14 16:09:46 -06001758 const GLint *iValues = ((const GLint *) values) + k * elems;
1759 for (i = 0; i < elems; i++) {
1760 uniformVal[i] = (GLfloat) iValues[i];
1761 }
1762 }
1763 else {
1764 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1765 for (i = 0; i < elems; i++) {
1766 uniformVal[i] = fValues[i];
1767 }
1768 }
Brian Pauleda291e2008-08-06 16:26:47 -06001769
1770 /* if the uniform is bool-valued, convert to 1.0 or 0.0 */
Brian Paulc4ffbf02009-02-18 17:46:00 -07001771 if (isUniformBool) {
Brian Pauleda291e2008-08-06 16:26:47 -06001772 for (i = 0; i < elems; i++) {
Michal Krolc5c71302008-08-07 16:23:15 +02001773 uniformVal[i] = uniformVal[i] ? 1.0f : 0.0f;
Brian Pauleda291e2008-08-06 16:26:47 -06001774 }
1775 }
Brian Paulade50832008-05-14 16:09:46 -06001776 }
1777 }
1778}
1779
1780
Brian5b01c5e2006-12-19 18:02:03 -07001781/**
1782 * Called via ctx->Driver.Uniform().
1783 */
Brian Paulfd59f192008-05-18 16:04:55 -06001784static void
Brian5b01c5e2006-12-19 18:02:03 -07001785_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1786 const GLvoid *values, GLenum type)
1787{
Brian3a8e2772006-12-20 17:19:16 -07001788 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001789 struct gl_uniform *uniform;
Brian Pauleda291e2008-08-06 16:26:47 -06001790 GLint elems, offset;
Brian Paule01a03d2009-02-06 10:21:36 -07001791 GLenum basicType;
Brian3a8e2772006-12-20 17:19:16 -07001792
1793 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001794 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001795 return;
1796 }
1797
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001798 if (location == -1)
1799 return; /* The standard specifies this as a no-op */
1800
Brian Paul234f03e2009-02-11 09:05:08 -07001801 if (location < -1) {
1802 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(location)");
1803 return;
1804 }
1805
Brian Pauleda291e2008-08-06 16:26:47 -06001806 split_location_offset(&location, &offset);
1807
Brian Paulade50832008-05-14 16:09:46 -06001808 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1809 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001810 return;
1811 }
1812
Brian52363952007-03-13 16:50:24 -06001813 if (count < 0) {
1814 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1815 return;
1816 }
1817
Brian98650bd2007-03-13 16:32:48 -06001818 switch (type) {
1819 case GL_FLOAT:
Brian Paule01a03d2009-02-06 10:21:36 -07001820 basicType = GL_FLOAT;
1821 elems = 1;
1822 break;
Brian98650bd2007-03-13 16:32:48 -06001823 case GL_INT:
Brian Paule01a03d2009-02-06 10:21:36 -07001824 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001825 elems = 1;
1826 break;
1827 case GL_FLOAT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001828 basicType = GL_FLOAT;
1829 elems = 2;
1830 break;
Brian98650bd2007-03-13 16:32:48 -06001831 case GL_INT_VEC2:
Brian Paule01a03d2009-02-06 10:21:36 -07001832 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001833 elems = 2;
1834 break;
1835 case GL_FLOAT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001836 basicType = GL_FLOAT;
1837 elems = 3;
1838 break;
Brian98650bd2007-03-13 16:32:48 -06001839 case GL_INT_VEC3:
Brian Paule01a03d2009-02-06 10:21:36 -07001840 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001841 elems = 3;
1842 break;
1843 case GL_FLOAT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001844 basicType = GL_FLOAT;
1845 elems = 4;
1846 break;
Brian98650bd2007-03-13 16:32:48 -06001847 case GL_INT_VEC4:
Brian Paule01a03d2009-02-06 10:21:36 -07001848 basicType = GL_INT;
Brian98650bd2007-03-13 16:32:48 -06001849 elems = 4;
1850 break;
1851 default:
1852 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1853 return;
Brian89dc4852007-01-04 14:35:44 -07001854 }
Brian98650bd2007-03-13 16:32:48 -06001855
Brian Paul027ed1b2009-04-24 09:43:44 -06001856 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Brian98650bd2007-03-13 16:32:48 -06001857
Brian Paul2d76a0d2008-11-10 12:33:17 -07001858 uniform = &shProg->Uniforms->Uniforms[location];
1859
Brian Paule01a03d2009-02-06 10:21:36 -07001860 if (ctx->Shader.Flags & GLSL_UNIFORMS) {
1861 GLint i;
1862 _mesa_printf("Mesa: set program %u uniform %s (loc %d) to: ",
1863 shProg->Name, uniform->Name, location);
1864 if (basicType == GL_INT) {
1865 const GLint *v = (const GLint *) values;
1866 for (i = 0; i < count * elems; i++) {
1867 _mesa_printf("%d ", v[i]);
1868 }
1869 }
1870 else {
1871 const GLfloat *v = (const GLfloat *) values;
1872 for (i = 0; i < count * elems; i++) {
1873 _mesa_printf("%g ", v[i]);
1874 }
1875 }
1876 _mesa_printf("\n");
1877 }
1878
Brian Paulade50832008-05-14 16:09:46 -06001879 /* A uniform var may be used by both a vertex shader and a fragment
1880 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001881 */
Brian Paulade50832008-05-14 16:09:46 -06001882 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001883 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001884 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001885 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001886 set_program_uniform(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001887 index, offset, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001888 }
Brian5b01c5e2006-12-19 18:02:03 -07001889 }
Brian5cf73262007-01-05 16:02:45 -07001890
Brian Paulade50832008-05-14 16:09:46 -06001891 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06001892 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07001893 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06001894 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06001895 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06001896 index, offset, type, count, elems, values);
Brian Paulade50832008-05-14 16:09:46 -06001897 }
1898 }
Brian Paul949e7382008-11-05 09:17:55 -07001899
Brian Paul2d76a0d2008-11-10 12:33:17 -07001900 uniform->Initialized = GL_TRUE;
Brian Paulade50832008-05-14 16:09:46 -06001901}
1902
1903
Brian Pauleda291e2008-08-06 16:26:47 -06001904/**
1905 * Set a matrix-valued program parameter.
1906 */
Brian Paulade50832008-05-14 16:09:46 -06001907static void
1908set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Pauleda291e2008-08-06 16:26:47 -06001909 GLuint index, GLuint offset,
1910 GLuint count, GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001911 GLboolean transpose, const GLfloat *values)
1912{
Brian Paulffbc66b2008-07-21 13:58:50 -06001913 GLuint mat, row, col;
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001914 GLuint src = 0;
1915 const struct gl_program_parameter * param = &program->Parameters->Parameters[index];
1916 const GLint slots = (param->Size + 3) / 4;
1917 const GLint typeSize = sizeof_glsl_type(param->DataType);
Brian Paulffbc66b2008-07-21 13:58:50 -06001918 GLint nr, nc;
1919
1920 /* check that the number of rows, columns is correct */
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001921 get_matrix_dims(param->DataType, &nr, &nc);
Brian Paulffbc66b2008-07-21 13:58:50 -06001922 if (rows != nr || cols != nc) {
1923 _mesa_error(ctx, GL_INVALID_OPERATION,
Brian Pauleda291e2008-08-06 16:26:47 -06001924 "glUniformMatrix(matrix size mismatch)");
1925 return;
1926 }
1927
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001928 if (param->Size <= typeSize) {
1929 /* non-array: count must be at most one; count == 0 is handled by the loop below */
1930 if (count > 1) {
1931 _mesa_error(ctx, GL_INVALID_OPERATION,
1932 "glUniformMatrix(uniform is not an array)");
1933 return;
1934 }
Brian Paulffbc66b2008-07-21 13:58:50 -06001935 }
1936
Brian Paulade50832008-05-14 16:09:46 -06001937 /*
1938 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001939 * the rows. So, the loops below look a little funny.
1940 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001941 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001942
1943 /* loop over matrices */
1944 for (mat = 0; mat < count; mat++) {
1945
1946 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001947 for (col = 0; col < cols; col++) {
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001948 GLfloat *v;
1949 if (offset >= slots) {
1950 /* Ignore writes beyond the end of (the used part of) an array */
1951 return;
1952 }
1953 v = program->Parameters->ParameterValues[index + offset];
Brian Paulade50832008-05-14 16:09:46 -06001954 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001955 if (transpose) {
1956 v[row] = values[src + row * cols + col];
1957 }
1958 else {
1959 v[row] = values[src + col * rows + row];
1960 }
Brian Paulade50832008-05-14 16:09:46 -06001961 }
Nicolai Hähnle9fde81b2009-10-03 16:30:16 +02001962
1963 offset++;
Brian Paulade50832008-05-14 16:09:46 -06001964 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001965
1966 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001967 }
Brian34ae99d2006-12-18 08:28:54 -07001968}
1969
1970
1971/**
Brian5b01c5e2006-12-19 18:02:03 -07001972 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001973 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001974 */
Brian Paulfd59f192008-05-18 16:04:55 -06001975static void
Brian5b01c5e2006-12-19 18:02:03 -07001976_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
Brian Paul0115a4f2009-04-14 20:00:28 -06001977 GLint location, GLsizei count,
Brian5b01c5e2006-12-19 18:02:03 -07001978 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001979{
Brian3a8e2772006-12-20 17:19:16 -07001980 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paul2d76a0d2008-11-10 12:33:17 -07001981 struct gl_uniform *uniform;
1982 GLint offset;
Brian Paulade50832008-05-14 16:09:46 -06001983
Brian3a8e2772006-12-20 17:19:16 -07001984 if (!shProg || !shProg->LinkStatus) {
1985 _mesa_error(ctx, GL_INVALID_OPERATION,
1986 "glUniformMatrix(program not linked)");
1987 return;
1988 }
Brian Paulade50832008-05-14 16:09:46 -06001989
Bruce Merry89b80322007-12-21 15:20:17 +02001990 if (location == -1)
1991 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001992
Brian Paul234f03e2009-02-11 09:05:08 -07001993 if (location < -1) {
1994 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformMatrix(location)");
1995 return;
1996 }
1997
Brian Pauleda291e2008-08-06 16:26:47 -06001998 split_location_offset(&location, &offset);
1999
Brian Paul016701f2008-07-29 17:43:35 -06002000 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06002001 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07002002 return;
2003 }
Brian34ae99d2006-12-18 08:28:54 -07002004 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07002005 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07002006 return;
2007 }
2008
Brian Paul027ed1b2009-04-24 09:43:44 -06002009 FLUSH_VERTICES(ctx, _NEW_PROGRAM_CONSTANTS);
Brian34ae99d2006-12-18 08:28:54 -07002010
Brian Paul2d76a0d2008-11-10 12:33:17 -07002011 uniform = &shProg->Uniforms->Uniforms[location];
2012
Brian Paulade50832008-05-14 16:09:46 -06002013 if (shProg->VertexProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06002014 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07002015 GLint index = uniform->VertPos;
Brian Pauleda291e2008-08-06 16:26:47 -06002016 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06002017 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06002018 index, offset,
2019 count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07002020 }
Brian Paulade50832008-05-14 16:09:46 -06002021 }
2022
2023 if (shProg->FragmentProgram) {
Brian Pauleda291e2008-08-06 16:26:47 -06002024 /* convert uniform location to program parameter index */
Brian Paul2d76a0d2008-11-10 12:33:17 -07002025 GLint index = uniform->FragPos;
Brian Pauleda291e2008-08-06 16:26:47 -06002026 if (index >= 0) {
Brian Paulade50832008-05-14 16:09:46 -06002027 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Pauleda291e2008-08-06 16:26:47 -06002028 index, offset,
2029 count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07002030 }
Brian34ae99d2006-12-18 08:28:54 -07002031 }
Brian Paul949e7382008-11-05 09:17:55 -07002032
Brian Paul2d76a0d2008-11-10 12:33:17 -07002033 uniform->Initialized = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07002034}
2035
2036
Brian Paulc90fca32009-08-25 17:42:47 -06002037/**
2038 * Validate a program's samplers.
2039 * Specifically, check that there aren't two samplers of different types
2040 * pointing to the same texture unit.
2041 * \return GL_TRUE if valid, GL_FALSE if invalid
2042 */
2043static GLboolean
2044validate_samplers(GLcontext *ctx, const struct gl_program *prog, char *errMsg)
Brian34ae99d2006-12-18 08:28:54 -07002045{
Brian Paulc90fca32009-08-25 17:42:47 -06002046 static const char *targetName[] = {
2047 "TEXTURE_2D_ARRAY",
2048 "TEXTURE_1D_ARRAY",
2049 "TEXTURE_CUBE",
2050 "TEXTURE_3D",
2051 "TEXTURE_RECT",
2052 "TEXTURE_2D",
2053 "TEXTURE_1D",
2054 };
2055 GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS];
2056 GLbitfield samplersUsed = prog->SamplersUsed;
2057 GLuint i;
Brian Paulbc985b52008-07-21 14:16:07 -06002058
Brian Paulc90fca32009-08-25 17:42:47 -06002059 assert(Elements(targetName) == NUM_TEXTURE_TARGETS);
2060
2061 if (samplersUsed == 0x0)
2062 return GL_TRUE;
2063
2064 for (i = 0; i < Elements(targetUsed); i++)
2065 targetUsed[i] = -1;
2066
2067 /* walk over bits which are set in 'samplers' */
2068 while (samplersUsed) {
2069 GLuint unit;
2070 gl_texture_index target;
2071 GLint sampler = _mesa_ffs(samplersUsed) - 1;
2072 assert(sampler >= 0);
2073 assert(sampler < MAX_TEXTURE_IMAGE_UNITS);
2074 unit = prog->SamplerUnits[sampler];
2075 target = prog->SamplerTargets[sampler];
2076 if (targetUsed[unit] != -1 && targetUsed[unit] != target) {
2077 _mesa_snprintf(errMsg, 100,
2078 "Texture unit %d is accessed both as %s and %s",
2079 unit, targetName[targetUsed[unit]], targetName[target]);
2080 return GL_FALSE;
2081 }
2082 targetUsed[unit] = target;
2083 samplersUsed ^= (1 << sampler);
Brian34ae99d2006-12-18 08:28:54 -07002084 }
2085
Brian Paulc90fca32009-08-25 17:42:47 -06002086 return GL_TRUE;
2087}
2088
2089
2090/**
2091 * Do validation of the given shader program.
2092 * \param errMsg returns error message if validation fails.
2093 * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg)
2094 */
2095GLboolean
2096_mesa_validate_shader_program(GLcontext *ctx,
2097 const struct gl_shader_program *shProg,
2098 char *errMsg)
2099{
2100 const struct gl_vertex_program *vp = shProg->VertexProgram;
2101 const struct gl_fragment_program *fp = shProg->FragmentProgram;
2102
Brian Paulbc985b52008-07-21 14:16:07 -06002103 if (!shProg->LinkStatus) {
Brian Paulc90fca32009-08-25 17:42:47 -06002104 return GL_FALSE;
Brian Paulbc985b52008-07-21 14:16:07 -06002105 }
2106
2107 /* From the GL spec, a program is invalid if any of these are true:
2108
Brian5b01c5e2006-12-19 18:02:03 -07002109 any two active samplers in the current program object are of
2110 different types, but refer to the same texture image unit,
2111
2112 any active sampler in the current program object refers to a texture
2113 image unit where fixed-function fragment processing accesses a
2114 texture target that does not match the sampler type, or
2115
2116 the sum of the number of active samplers in the program and the
2117 number of texture image units enabled for fixed-function fragment
2118 processing exceeds the combined limit on the total number of texture
2119 image units allowed.
2120 */
Brian Paulbc985b52008-07-21 14:16:07 -06002121
Brian Paulc90fca32009-08-25 17:42:47 -06002122
2123 /*
2124 * Check: any two active samplers in the current program object are of
2125 * different types, but refer to the same texture image unit,
2126 */
2127 if (vp && !validate_samplers(ctx, &vp->Base, errMsg)) {
2128 return GL_FALSE;
2129 }
2130 if (fp && !validate_samplers(ctx, &fp->Base, errMsg)) {
2131 return GL_FALSE;
2132 }
2133
2134 return GL_TRUE;
2135}
2136
2137
2138/**
2139 * Called via glValidateProgram()
2140 */
2141static void
2142_mesa_validate_program(GLcontext *ctx, GLuint program)
2143{
2144 struct gl_shader_program *shProg;
2145 char errMsg[100];
2146
2147 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
2148 if (!shProg) {
2149 return;
2150 }
2151
2152 shProg->Validated = _mesa_validate_shader_program(ctx, shProg, errMsg);
2153 if (!shProg->Validated) {
2154 /* update info log */
2155 if (shProg->InfoLog) {
2156 _mesa_free(shProg->InfoLog);
2157 }
2158 shProg->InfoLog = _mesa_strdup(errMsg);
2159 }
Brian34ae99d2006-12-18 08:28:54 -07002160}
Brian Paulfd59f192008-05-18 16:04:55 -06002161
2162
2163/**
2164 * Plug in Mesa's GLSL functions into the device driver function table.
2165 */
2166void
2167_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
2168{
2169 driver->AttachShader = _mesa_attach_shader;
2170 driver->BindAttribLocation = _mesa_bind_attrib_location;
2171 driver->CompileShader = _mesa_compile_shader;
2172 driver->CreateProgram = _mesa_create_program;
2173 driver->CreateShader = _mesa_create_shader;
2174 driver->DeleteProgram2 = _mesa_delete_program2;
2175 driver->DeleteShader = _mesa_delete_shader;
2176 driver->DetachShader = _mesa_detach_shader;
2177 driver->GetActiveAttrib = _mesa_get_active_attrib;
2178 driver->GetActiveUniform = _mesa_get_active_uniform;
2179 driver->GetAttachedShaders = _mesa_get_attached_shaders;
2180 driver->GetAttribLocation = _mesa_get_attrib_location;
2181 driver->GetHandle = _mesa_get_handle;
2182 driver->GetProgramiv = _mesa_get_programiv;
2183 driver->GetProgramInfoLog = _mesa_get_program_info_log;
2184 driver->GetShaderiv = _mesa_get_shaderiv;
2185 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
2186 driver->GetShaderSource = _mesa_get_shader_source;
2187 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06002188 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06002189 driver->GetUniformLocation = _mesa_get_uniform_location;
2190 driver->IsProgram = _mesa_is_program;
2191 driver->IsShader = _mesa_is_shader;
2192 driver->LinkProgram = _mesa_link_program;
2193 driver->ShaderSource = _mesa_shader_source;
2194 driver->Uniform = _mesa_uniform;
2195 driver->UniformMatrix = _mesa_uniform_matrix;
2196 driver->UseProgram = _mesa_use_program;
2197 driver->ValidateProgram = _mesa_validate_program;
2198}