blob: feb8363f503ed9b7de6628014789cda9d7b6d22d [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian3e4302f2007-05-09 08:04:32 -06003 * Version: 7.0
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian5b01c5e2006-12-19 18:02:03 -07005 * Copyright (C) 2004-2007 Brian Paul All Rights Reserved.
Brian34ae99d2006-12-18 08:28:54 -07006 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file shader_api.c
Brian5b01c5e2006-12-19 18:02:03 -070027 * Implementation of GLSL-related API functions
Brian34ae99d2006-12-18 08:28:54 -070028 * \author Brian Paul
29 */
30
31/**
32 * XXX things to do:
33 * 1. Check that the right error code is generated for all _mesa_error() calls.
Brian5b01c5e2006-12-19 18:02:03 -070034 * 2. Insert FLUSH_VERTICES calls in various places
Brian34ae99d2006-12-18 08:28:54 -070035 */
36
37
38#include "glheader.h"
39#include "context.h"
40#include "hash.h"
Brian274ac7a2007-04-18 16:05:53 -060041#include "macros.h"
Brian34ae99d2006-12-18 08:28:54 -070042#include "program.h"
43#include "prog_parameter.h"
Brian3209c3e2007-01-09 17:49:24 -070044#include "prog_print.h"
45#include "prog_statevars.h"
Brian Paulade50832008-05-14 16:09:46 -060046#include "prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060047#include "shader/shader_api.h"
48#include "shader/slang/slang_compile.h"
49#include "shader/slang/slang_link.h"
Brian34ae99d2006-12-18 08:28:54 -070050
51
52
Brianf2923612006-12-20 09:56:44 -070053/**
54 * Allocate a new gl_shader_program object, initialize it.
55 */
Brian Paulfd59f192008-05-18 16:04:55 -060056static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070057_mesa_new_shader_program(GLcontext *ctx, GLuint name)
58{
59 struct gl_shader_program *shProg;
60 shProg = CALLOC_STRUCT(gl_shader_program);
61 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060062 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070063 shProg->Name = name;
64 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070065 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070066 }
67 return shProg;
68}
69
70
Brianb9fbedd2007-03-26 09:23:44 -060071/**
Brian3c008a02007-04-12 15:22:32 -060072 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060073 */
Brianf2923612006-12-20 09:56:44 -070074void
Brian3c008a02007-04-12 15:22:32 -060075_mesa_clear_shader_program_data(GLcontext *ctx,
76 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070077{
Brian Paul8bdf5b62008-05-16 09:56:59 -060078 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
79 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070080
Brianf2923612006-12-20 09:56:44 -070081 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060082 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070083 shProg->Uniforms = NULL;
84 }
85
86 if (shProg->Varying) {
87 _mesa_free_parameter_list(shProg->Varying);
88 shProg->Varying = NULL;
89 }
90}
91
92
Brianb9fbedd2007-03-26 09:23:44 -060093/**
Brian3c008a02007-04-12 15:22:32 -060094 * Free all the data that hangs off a shader program object, but not the
95 * object itself.
96 */
97void
98_mesa_free_shader_program_data(GLcontext *ctx,
99 struct gl_shader_program *shProg)
100{
101 GLuint i;
102
Brianf3e8c322007-04-18 14:53:23 -0600103 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600104
105 _mesa_clear_shader_program_data(ctx, shProg);
106
Brian4b7c6fc2007-04-19 15:23:34 -0600107 if (shProg->Attributes) {
108 _mesa_free_parameter_list(shProg->Attributes);
109 shProg->Attributes = NULL;
110 }
111
Brian3c008a02007-04-12 15:22:32 -0600112 /* detach shaders */
113 for (i = 0; i < shProg->NumShaders; i++) {
114 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
115 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800116 shProg->NumShaders = 0;
117
Brian3c008a02007-04-12 15:22:32 -0600118 if (shProg->Shaders) {
119 _mesa_free(shProg->Shaders);
120 shProg->Shaders = NULL;
121 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100122
123 if (shProg->InfoLog) {
124 _mesa_free(shProg->InfoLog);
125 shProg->InfoLog = NULL;
126 }
Brian3c008a02007-04-12 15:22:32 -0600127}
128
129
130/**
Brianb9fbedd2007-03-26 09:23:44 -0600131 * Free/delete a shader program object.
132 */
Brianf2923612006-12-20 09:56:44 -0700133void
134_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
135{
136 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100137
Brianf2923612006-12-20 09:56:44 -0700138 _mesa_free(shProg);
139}
140
141
142/**
Brian3c008a02007-04-12 15:22:32 -0600143 * Set ptr to point to shProg.
144 * If ptr is pointing to another object, decrement its refcount (and delete
145 * if refcount hits zero).
146 * Then set ptr to point to shProg, incrementing its refcount.
147 */
148/* XXX this could be static */
149void
150_mesa_reference_shader_program(GLcontext *ctx,
151 struct gl_shader_program **ptr,
152 struct gl_shader_program *shProg)
153{
154 assert(ptr);
155 if (*ptr == shProg) {
156 /* no-op */
157 return;
158 }
159 if (*ptr) {
160 /* Unreference the old shader program */
161 GLboolean deleteFlag = GL_FALSE;
162 struct gl_shader_program *old = *ptr;
163
164 ASSERT(old->RefCount > 0);
165 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600166#if 0
167 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
168 (void *) old, old->Name, old->RefCount);
169#endif
Brian3c008a02007-04-12 15:22:32 -0600170 deleteFlag = (old->RefCount == 0);
171
172 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800173 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600174 _mesa_free_shader_program(ctx, old);
175 }
176
177 *ptr = NULL;
178 }
179 assert(!*ptr);
180
181 if (shProg) {
182 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600183#if 0
184 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
185 (void *) shProg, shProg->Name, shProg->RefCount);
186#endif
Brian3c008a02007-04-12 15:22:32 -0600187 *ptr = shProg;
188 }
189}
190
191
192/**
Brianf2923612006-12-20 09:56:44 -0700193 * Lookup a GLSL program object.
194 */
195struct gl_shader_program *
196_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
197{
198 struct gl_shader_program *shProg;
199 if (name) {
200 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800201 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700202 /* Note that both gl_shader and gl_shader_program objects are kept
203 * in the same hash table. Check the object's type to be sure it's
204 * what we're expecting.
205 */
Brianf3e8c322007-04-18 14:53:23 -0600206 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700207 return NULL;
208 }
209 return shProg;
210 }
211 return NULL;
212}
213
214
215/**
Brian Paul530df582008-07-03 16:21:11 -0600216 * As above, but record an error if program is not found.
217 */
218static struct gl_shader_program *
219_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
220 const char *caller)
221{
222 if (!name) {
223 _mesa_error(ctx, GL_INVALID_VALUE, caller);
224 return NULL;
225 }
226 else {
227 struct gl_shader_program *shProg = (struct gl_shader_program *)
228 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
229 if (!shProg) {
230 _mesa_error(ctx, GL_INVALID_VALUE, caller);
231 return NULL;
232 }
233 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
234 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
235 return NULL;
236 }
237 return shProg;
238 }
239}
240
241
242
243
244/**
Brianf2923612006-12-20 09:56:44 -0700245 * Allocate a new gl_shader object, initialize it.
246 */
247struct gl_shader *
248_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
249{
250 struct gl_shader *shader;
251 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
252 shader = CALLOC_STRUCT(gl_shader);
253 if (shader) {
254 shader->Type = type;
255 shader->Name = name;
256 shader->RefCount = 1;
257 }
258 return shader;
259}
260
261
262void
263_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
264{
Brianf2923612006-12-20 09:56:44 -0700265 if (sh->Source)
266 _mesa_free((void *) sh->Source);
267 if (sh->InfoLog)
268 _mesa_free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600269 _mesa_reference_program(ctx, &sh->Program, NULL);
Brianf2923612006-12-20 09:56:44 -0700270 _mesa_free(sh);
271}
272
273
274/**
Brian3c008a02007-04-12 15:22:32 -0600275 * Set ptr to point to sh.
276 * If ptr is pointing to another shader, decrement its refcount (and delete
277 * if refcount hits zero).
278 * Then set ptr to point to sh, incrementing its refcount.
279 */
280/* XXX this could be static */
281void
282_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
283 struct gl_shader *sh)
284{
285 assert(ptr);
286 if (*ptr == sh) {
287 /* no-op */
288 return;
289 }
290 if (*ptr) {
291 /* Unreference the old shader */
292 GLboolean deleteFlag = GL_FALSE;
293 struct gl_shader *old = *ptr;
294
295 ASSERT(old->RefCount > 0);
296 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600297 /*printf("SHADER DECR %p (%d) to %d\n",
298 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600299 deleteFlag = (old->RefCount == 0);
300
301 if (deleteFlag) {
302 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
303 _mesa_free_shader(ctx, old);
304 }
305
306 *ptr = NULL;
307 }
308 assert(!*ptr);
309
310 if (sh) {
311 /* reference new */
312 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600313 /*printf("SHADER INCR %p (%d) to %d\n",
314 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600315 *ptr = sh;
316 }
317}
318
319
320/**
Brianf2923612006-12-20 09:56:44 -0700321 * Lookup a GLSL shader object.
322 */
323struct gl_shader *
324_mesa_lookup_shader(GLcontext *ctx, GLuint name)
325{
326 if (name) {
327 struct gl_shader *sh = (struct gl_shader *)
328 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
329 /* Note that both gl_shader and gl_shader_program objects are kept
330 * in the same hash table. Check the object's type to be sure it's
331 * what we're expecting.
332 */
Brianf3e8c322007-04-18 14:53:23 -0600333 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700334 return NULL;
335 }
336 return sh;
337 }
338 return NULL;
339}
340
341
Brianfa4d0362007-02-26 18:33:50 -0700342/**
Brian Paul530df582008-07-03 16:21:11 -0600343 * As above, but record an error if shader is not found.
344 */
345static struct gl_shader *
346_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
347{
348 if (!name) {
349 _mesa_error(ctx, GL_INVALID_VALUE, caller);
350 return NULL;
351 }
352 else {
353 struct gl_shader *sh = (struct gl_shader *)
354 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
355 if (!sh) {
356 _mesa_error(ctx, GL_INVALID_VALUE, caller);
357 return NULL;
358 }
359 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
360 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
361 return NULL;
362 }
363 return sh;
364 }
365}
366
367
368
369/**
Brianfa4d0362007-02-26 18:33:50 -0700370 * Initialize context's shader state.
371 */
Brianf2923612006-12-20 09:56:44 -0700372void
373_mesa_init_shader_state(GLcontext * ctx)
374{
Brianfa4d0362007-02-26 18:33:50 -0700375 /* Device drivers may override these to control what kind of instructions
376 * are generated by the GLSL compiler.
377 */
378 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600379 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700380 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700381}
382
383
Brian5b01c5e2006-12-19 18:02:03 -0700384/**
Brian935f93f2007-03-24 16:20:02 -0600385 * Free the per-context shader-related state.
386 */
387void
388_mesa_free_shader_state(GLcontext *ctx)
389{
Brian3c008a02007-04-12 15:22:32 -0600390 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600391}
392
393
394/**
Brian5b01c5e2006-12-19 18:02:03 -0700395 * Copy string from <src> to <dst>, up to maxLength characters, returning
396 * length of <dst> in <length>.
397 * \param src the strings source
398 * \param maxLength max chars to copy
399 * \param length returns number of chars copied
400 * \param dst the string destination
401 */
402static void
403copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
404{
405 GLsizei len;
406 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
407 dst[len] = src[len];
408 if (maxLength > 0)
409 dst[len] = 0;
410 if (length)
411 *length = len;
412}
413
414
Brian Paul7acb7c12008-07-03 13:49:48 -0600415static GLboolean
416_mesa_is_program(GLcontext *ctx, GLuint name)
417{
418 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
419 return shProg ? GL_TRUE : GL_FALSE;
420}
421
422
423static GLboolean
424_mesa_is_shader(GLcontext *ctx, GLuint name)
425{
426 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
427 return shader ? GL_TRUE : GL_FALSE;
428}
429
430
Brian5b01c5e2006-12-19 18:02:03 -0700431/**
432 * Called via ctx->Driver.AttachShader()
433 */
Brian Paulfd59f192008-05-18 16:04:55 -0600434static void
Brian5b01c5e2006-12-19 18:02:03 -0700435_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
436{
Brian Paul530df582008-07-03 16:21:11 -0600437 struct gl_shader_program *shProg;
438 struct gl_shader *sh;
439 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700440
Brian Paul530df582008-07-03 16:21:11 -0600441 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
442 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700443 return;
Brian5b01c5e2006-12-19 18:02:03 -0700444
Brian Paul530df582008-07-03 16:21:11 -0600445 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600446 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600447 return;
448 }
449
Brian237b9852007-08-07 21:48:31 +0100450 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700451 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700452 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700453 /* already attached */
454 return;
Brian34ae99d2006-12-18 08:28:54 -0700455 }
456 }
Brian5b01c5e2006-12-19 18:02:03 -0700457
458 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700459 shProg->Shaders = (struct gl_shader **)
460 _mesa_realloc(shProg->Shaders,
461 n * sizeof(struct gl_shader *),
462 (n + 1) * sizeof(struct gl_shader *));
463 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700464 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
465 return;
466 }
467
468 /* append */
Brian3c008a02007-04-12 15:22:32 -0600469 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
470 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700471 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700472}
473
474
Brian Paulfd59f192008-05-18 16:04:55 -0600475static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600476_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
477 const GLchar *name)
478{
479 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600480 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600481
482 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600483 return -1;
484 }
485
486 if (!shProg->LinkStatus) {
487 _mesa_error(ctx, GL_INVALID_OPERATION,
488 "glGetAttribLocation(program not linked)");
489 return -1;
490 }
491
492 if (!name)
493 return -1;
494
495 if (shProg->Attributes) {
496 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
497 if (i >= 0) {
498 return shProg->Attributes->Parameters[i].StateIndexes[0];
499 }
500 }
501 return -1;
502}
503
504
Brian Paulfd59f192008-05-18 16:04:55 -0600505static void
Brian5b01c5e2006-12-19 18:02:03 -0700506_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
507 const GLchar *name)
508{
Brian Paul530df582008-07-03 16:21:11 -0600509 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700510 const GLint size = -1; /* unknown size */
511 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600512 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700513
Brian Paul530df582008-07-03 16:21:11 -0600514 shProg = _mesa_lookup_shader_program_err(ctx, program,
515 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700516 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700517 return;
518 }
519
Brian9e4bae92006-12-20 09:27:42 -0700520 if (!name)
521 return;
522
523 if (strncmp(name, "gl_", 3) == 0) {
524 _mesa_error(ctx, GL_INVALID_OPERATION,
525 "glBindAttribLocation(illegal name)");
526 return;
527 }
528
Brian Paul7acb7c12008-07-03 13:49:48 -0600529 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
530 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
531 return;
532 }
533
Brian9f660252007-04-11 09:00:56 -0600534 if (shProg->LinkStatus) {
535 /* get current index/location for the attribute */
536 oldIndex = _mesa_get_attrib_location(ctx, program, name);
537 }
538 else {
539 oldIndex = -1;
540 }
Brian3209c3e2007-01-09 17:49:24 -0700541
542 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600543 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700544 if (i < 0) {
545 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600546 return;
Brian3209c3e2007-01-09 17:49:24 -0700547 }
548
Brian9f660252007-04-11 09:00:56 -0600549 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
550 /* If the index changed, need to search/replace references to that attribute
551 * in the vertex program.
552 */
Brian3209c3e2007-01-09 17:49:24 -0700553 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
554 }
Brian34ae99d2006-12-18 08:28:54 -0700555}
556
557
Brian Paulfd59f192008-05-18 16:04:55 -0600558static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700559_mesa_create_shader(GLcontext *ctx, GLenum type)
560{
Brian65a18442006-12-19 18:46:56 -0700561 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700562 GLuint name;
563
564 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
565
566 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700567 case GL_FRAGMENT_SHADER:
568 case GL_VERTEX_SHADER:
569 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700570 break;
571 default:
572 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
573 return 0;
574 }
575
Brian65a18442006-12-19 18:46:56 -0700576 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700577
578 return name;
579}
580
581
Brian Paulfd59f192008-05-18 16:04:55 -0600582static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700583_mesa_create_program(GLcontext *ctx)
584{
585 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700586 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700587
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800588 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700589 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700590
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800591 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700592
Brian3c008a02007-04-12 15:22:32 -0600593 assert(shProg->RefCount == 1);
594
Brian5b01c5e2006-12-19 18:02:03 -0700595 return name;
596}
597
598
Brian3c008a02007-04-12 15:22:32 -0600599/**
600 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
601 * DeleteProgramARB.
602 */
Brian Paulfd59f192008-05-18 16:04:55 -0600603static void
Brian5b01c5e2006-12-19 18:02:03 -0700604_mesa_delete_program2(GLcontext *ctx, GLuint name)
605{
Brian3c008a02007-04-12 15:22:32 -0600606 /*
607 * NOTE: deleting shaders/programs works a bit differently than
608 * texture objects (and buffer objects, etc). Shader/program
609 * handles/IDs exist in the hash table until the object is really
610 * deleted (refcount==0). With texture objects, the handle/ID is
611 * removed from the hash table in glDeleteTextures() while the tex
612 * object itself might linger until its refcount goes to zero.
613 */
Brian65a18442006-12-19 18:46:56 -0700614 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700615
Brian Paul530df582008-07-03 16:21:11 -0600616 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
617 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700618 return;
Brian5b01c5e2006-12-19 18:02:03 -0700619
Brian9e4bae92006-12-20 09:27:42 -0700620 shProg->DeletePending = GL_TRUE;
621
Brian3c008a02007-04-12 15:22:32 -0600622 /* effectively, decr shProg's refcount */
623 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700624}
625
626
Brian Paulfd59f192008-05-18 16:04:55 -0600627static void
Brian5b01c5e2006-12-19 18:02:03 -0700628_mesa_delete_shader(GLcontext *ctx, GLuint shader)
629{
Brian Paul530df582008-07-03 16:21:11 -0600630 struct gl_shader *sh;
631
632 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
633 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700634 return;
Brian5b01c5e2006-12-19 18:02:03 -0700635
Brian9e4bae92006-12-20 09:27:42 -0700636 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600637
638 /* effectively, decr sh's refcount */
639 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700640}
641
642
Brian Paulfd59f192008-05-18 16:04:55 -0600643static void
Brian5b01c5e2006-12-19 18:02:03 -0700644_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
645{
Brian Paul530df582008-07-03 16:21:11 -0600646 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100647 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700648 GLuint i, j;
649
Brian Paul530df582008-07-03 16:21:11 -0600650 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
651 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700652 return;
Brian5b01c5e2006-12-19 18:02:03 -0700653
Brian237b9852007-08-07 21:48:31 +0100654 n = shProg->NumShaders;
655
Brian5b01c5e2006-12-19 18:02:03 -0700656 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700657 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700658 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600659 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700660
Brian Paul530df582008-07-03 16:21:11 -0600661 /* release */
Brian3c008a02007-04-12 15:22:32 -0600662 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700663
Brian5b01c5e2006-12-19 18:02:03 -0700664 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700665 newList = (struct gl_shader **)
666 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700667 if (!newList) {
668 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
669 return;
670 }
671 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700672 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700673 }
674 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700675 newList[j++] = shProg->Shaders[i];
676 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700677
Brian65a18442006-12-19 18:46:56 -0700678 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600679 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600680
681#ifdef DEBUG
682 /* sanity check */
683 {
684 for (j = 0; j < shProg->NumShaders; j++) {
685 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
686 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
687 assert(shProg->Shaders[j]->RefCount > 0);
688 }
689 }
690#endif
691
Brian5b01c5e2006-12-19 18:02:03 -0700692 return;
693 }
694 }
695
696 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600697 {
698 GLenum err;
699 if (_mesa_is_shader(ctx, shader))
700 err = GL_INVALID_OPERATION;
701 else if (_mesa_is_program(ctx, shader))
702 err = GL_INVALID_OPERATION;
703 else
704 err = GL_INVALID_VALUE;
705 _mesa_error(ctx, err, "glDetachProgram(shader)");
706 return;
707 }
Brian5b01c5e2006-12-19 18:02:03 -0700708}
709
710
Brian Paulffbc66b2008-07-21 13:58:50 -0600711static GLint
712sizeof_glsl_type(GLenum type)
713{
714 switch (type) {
715 case GL_FLOAT:
716 case GL_INT:
717 case GL_BOOL:
718 return 1;
719 case GL_FLOAT_VEC2:
720 case GL_INT_VEC2:
721 case GL_BOOL_VEC2:
722 return 2;
723 case GL_FLOAT_VEC3:
724 case GL_INT_VEC3:
725 case GL_BOOL_VEC3:
726 return 3;
727 case GL_FLOAT_VEC4:
728 case GL_INT_VEC4:
729 case GL_BOOL_VEC4:
730 return 4;
731 case GL_FLOAT_MAT2:
732 case GL_FLOAT_MAT2x3:
733 case GL_FLOAT_MAT2x4:
734 return 8; /* two float[4] vectors */
735 case GL_FLOAT_MAT3:
736 case GL_FLOAT_MAT3x2:
737 case GL_FLOAT_MAT3x4:
738 return 12; /* three float[4] vectors */
739 case GL_FLOAT_MAT4:
740 case GL_FLOAT_MAT4x2:
741 case GL_FLOAT_MAT4x3:
742 return 16; /* four float[4] vectors */
743 default:
744 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
745 return 1;
746 }
747}
748
749
Brian Paulfd59f192008-05-18 16:04:55 -0600750static void
Brian5b01c5e2006-12-19 18:02:03 -0700751_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
752 GLsizei maxLength, GLsizei *length, GLint *size,
753 GLenum *type, GLchar *nameOut)
754{
Brian Paul530df582008-07-03 16:21:11 -0600755 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700756
Brian Paul530df582008-07-03 16:21:11 -0600757 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
758 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700759 return;
Brian5b01c5e2006-12-19 18:02:03 -0700760
Brian65a18442006-12-19 18:46:56 -0700761 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600762 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700763 return;
764 }
765
766 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700767 shProg->Attributes->Parameters[index].Name);
Brian5b01c5e2006-12-19 18:02:03 -0700768 if (size)
Brian Paulffbc66b2008-07-21 13:58:50 -0600769 *size = shProg->Attributes->Parameters[index].Size
770 / sizeof_glsl_type(shProg->Attributes->Parameters[index].DataType);
Brian Paulade50832008-05-14 16:09:46 -0600771 if (type)
Brian Paulffbc66b2008-07-21 13:58:50 -0600772 *type = shProg->Attributes->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700773}
774
775
776/**
777 * Called via ctx->Driver.GetActiveUniform().
778 */
Brian Paulfd59f192008-05-18 16:04:55 -0600779static void
Brian5b01c5e2006-12-19 18:02:03 -0700780_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
781 GLsizei maxLength, GLsizei *length, GLint *size,
782 GLenum *type, GLchar *nameOut)
783{
Brian Paul530df582008-07-03 16:21:11 -0600784 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600785 const struct gl_program *prog;
786 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700787
Brian Paul530df582008-07-03 16:21:11 -0600788 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
789 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700790 return;
Brian5b01c5e2006-12-19 18:02:03 -0700791
Brian Paulade50832008-05-14 16:09:46 -0600792 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700793 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
794 return;
795 }
796
Brian Paulade50832008-05-14 16:09:46 -0600797 progPos = shProg->Uniforms->Uniforms[index].VertPos;
798 if (progPos >= 0) {
799 prog = &shProg->VertexProgram->Base;
800 }
801 else {
802 progPos = shProg->Uniforms->Uniforms[index].FragPos;
803 if (progPos >= 0) {
804 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600805 }
806 }
807
Brian Paulade50832008-05-14 16:09:46 -0600808 if (!prog || progPos < 0)
809 return; /* should never happen */
810
811 if (nameOut)
812 copy_string(nameOut, maxLength, length,
813 prog->Parameters->Parameters[progPos].Name);
814 if (size)
Brian Paulffbc66b2008-07-21 13:58:50 -0600815 *size = prog->Parameters->Parameters[progPos].Size
816 / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType);
Brian Paulade50832008-05-14 16:09:46 -0600817 if (type)
818 *type = prog->Parameters->Parameters[progPos].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700819}
820
821
822/**
823 * Called via ctx->Driver.GetAttachedShaders().
824 */
Brian Paulfd59f192008-05-18 16:04:55 -0600825static void
Brian5b01c5e2006-12-19 18:02:03 -0700826_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
827 GLsizei *count, GLuint *obj)
828{
Brian Paul530df582008-07-03 16:21:11 -0600829 struct gl_shader_program *shProg =
830 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700831 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600832 GLuint i;
833 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700834 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700835 }
836 if (count)
837 *count = i;
838 }
Brian5b01c5e2006-12-19 18:02:03 -0700839}
840
841
Brian Paulfd59f192008-05-18 16:04:55 -0600842static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700843_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700844{
845#if 0
846 GET_CURRENT_CONTEXT(ctx);
847
848 switch (pname) {
849 case GL_PROGRAM_OBJECT_ARB:
850 {
Brian5b01c5e2006-12-19 18:02:03 -0700851 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700852
853 if (pro != NULL)
854 return (**pro)._container._generic.
855 GetName((struct gl2_generic_intf **) (pro));
856 }
857 break;
858 default:
859 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
860 }
861#endif
862 return 0;
863}
864
865
Brian Paulfd59f192008-05-18 16:04:55 -0600866static void
Brian5b01c5e2006-12-19 18:02:03 -0700867_mesa_get_programiv(GLcontext *ctx, GLuint program,
868 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700869{
Brian65a18442006-12-19 18:46:56 -0700870 struct gl_shader_program *shProg
871 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700872
Brian65a18442006-12-19 18:46:56 -0700873 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700874 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700875 return;
876 }
877
Brian5b01c5e2006-12-19 18:02:03 -0700878 switch (pname) {
879 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700880 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700881 break;
882 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700883 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700884 break;
Brian5b01c5e2006-12-19 18:02:03 -0700885 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700886 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700887 break;
888 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600889 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700890 break;
891 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700892 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700893 break;
894 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700895 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700896 break;
897 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian274ac7a2007-04-18 16:05:53 -0600898 *params = _mesa_longest_parameter_name(shProg->Attributes,
899 PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700900 break;
901 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600902 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700903 break;
904 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600905 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600906 if (*params > 0)
907 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700908 break;
909 default:
Brian5b01c5e2006-12-19 18:02:03 -0700910 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
911 return;
Brian34ae99d2006-12-18 08:28:54 -0700912 }
Brian5b01c5e2006-12-19 18:02:03 -0700913}
Brian34ae99d2006-12-18 08:28:54 -0700914
Brian34ae99d2006-12-18 08:28:54 -0700915
Brian Paulfd59f192008-05-18 16:04:55 -0600916static void
Brian5b01c5e2006-12-19 18:02:03 -0700917_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
918{
Brian Paul530df582008-07-03 16:21:11 -0600919 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700920
921 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700922 return;
923 }
Brian65a18442006-12-19 18:46:56 -0700924
Brian5b01c5e2006-12-19 18:02:03 -0700925 switch (pname) {
926 case GL_SHADER_TYPE:
927 *params = shader->Type;
928 break;
929 case GL_DELETE_STATUS:
930 *params = shader->DeletePending;
931 break;
932 case GL_COMPILE_STATUS:
933 *params = shader->CompileStatus;
934 break;
935 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600936 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700937 break;
938 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600939 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700940 break;
941 default:
942 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
943 return;
944 }
945}
946
947
Brian Paulfd59f192008-05-18 16:04:55 -0600948static void
Brian5b01c5e2006-12-19 18:02:03 -0700949_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
950 GLsizei *length, GLchar *infoLog)
951{
Brian65a18442006-12-19 18:46:56 -0700952 struct gl_shader_program *shProg
953 = _mesa_lookup_shader_program(ctx, program);
954 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700955 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
956 return;
957 }
Brian65a18442006-12-19 18:46:56 -0700958 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700959}
960
961
Brian Paulfd59f192008-05-18 16:04:55 -0600962static void
Brian5b01c5e2006-12-19 18:02:03 -0700963_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
964 GLsizei *length, GLchar *infoLog)
965{
Brian65a18442006-12-19 18:46:56 -0700966 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
967 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700968 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
969 return;
970 }
Brian65a18442006-12-19 18:46:56 -0700971 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700972}
973
974
975/**
976 * Called via ctx->Driver.GetShaderSource().
977 */
Brian Paulfd59f192008-05-18 16:04:55 -0600978static void
Brian5b01c5e2006-12-19 18:02:03 -0700979_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
980 GLsizei *length, GLchar *sourceOut)
981{
Brian Paul530df582008-07-03 16:21:11 -0600982 struct gl_shader *sh;
983 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -0700984 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700985 return;
986 }
Brian65a18442006-12-19 18:46:56 -0700987 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700988}
989
990
Brian Paul2be54a82008-07-08 16:17:04 -0600991#define MAX_UNIFORM_ELEMENTS 16
992
Brian5b01c5e2006-12-19 18:02:03 -0700993/**
Brian Paul2be54a82008-07-08 16:17:04 -0600994 * Helper for GetUniformfv(), GetUniformiv()
995 * Returns number of elements written to 'params' output.
Brian5b01c5e2006-12-19 18:02:03 -0700996 */
Brian Paul2be54a82008-07-08 16:17:04 -0600997static GLuint
998get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
999 GLfloat *params)
Brian5b01c5e2006-12-19 18:02:03 -07001000{
Brian65a18442006-12-19 18:46:56 -07001001 struct gl_shader_program *shProg
1002 = _mesa_lookup_shader_program(ctx, program);
1003 if (shProg) {
Brian Paul6cb12702008-06-28 16:48:31 -06001004 if (shProg->Uniforms &&
1005 location >= 0 && location < shProg->Uniforms->NumUniforms) {
1006 GLint progPos;
1007 GLuint i;
Brian Paulf2632212008-05-16 10:49:44 -06001008 const struct gl_program *prog = NULL;
Brian Paulade50832008-05-14 16:09:46 -06001009
1010 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1011 if (progPos >= 0) {
1012 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001013 }
Brian Paulade50832008-05-14 16:09:46 -06001014 else {
1015 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1016 if (progPos >= 0) {
1017 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001018 }
Brian Paulade50832008-05-14 16:09:46 -06001019 }
1020
Brian Paulf2632212008-05-16 10:49:44 -06001021 ASSERT(prog);
1022 if (prog) {
Brian Paul2be54a82008-07-08 16:17:04 -06001023 /* See uniformiv() below */
1024 assert(prog->Parameters->Parameters[progPos].Size <= MAX_UNIFORM_ELEMENTS);
1025
Brian Paulf2632212008-05-16 10:49:44 -06001026 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
1027 params[i] = prog->Parameters->ParameterValues[progPos][i];
1028 }
Brian Paul2be54a82008-07-08 16:17:04 -06001029 return prog->Parameters->Parameters[progPos].Size;
Brian Paulade50832008-05-14 16:09:46 -06001030 }
Brian5b01c5e2006-12-19 18:02:03 -07001031 }
1032 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001033 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
Brian5b01c5e2006-12-19 18:02:03 -07001034 }
1035 }
1036 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001037 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -07001038 }
Brian Paul2be54a82008-07-08 16:17:04 -06001039 return 0;
1040}
1041
1042
1043/**
1044 * Called via ctx->Driver.GetUniformfv().
1045 */
1046static void
1047_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1048 GLfloat *params)
1049{
1050 (void) get_uniformfv(ctx, program, location, params);
1051}
1052
1053
1054/**
1055 * Called via ctx->Driver.GetUniformiv().
1056 */
1057static void
1058_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1059 GLint *params)
1060{
1061 GLfloat fparams[MAX_UNIFORM_ELEMENTS];
1062 GLuint n = get_uniformfv(ctx, program, location, fparams);
1063 GLuint i;
1064 assert(n <= MAX_UNIFORM_ELEMENTS);
1065 for (i = 0; i < n; i++) {
1066 params[i] = (GLint) fparams[i];
1067 }
Brian5b01c5e2006-12-19 18:02:03 -07001068}
1069
1070
1071/**
1072 * Called via ctx->Driver.GetUniformLocation().
1073 */
Brian Paulfd59f192008-05-18 16:04:55 -06001074static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001075_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1076{
Brian Paul530df582008-07-03 16:21:11 -06001077 struct gl_shader_program *shProg =
1078 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1079
Brian Paulade50832008-05-14 16:09:46 -06001080 if (!shProg)
1081 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001082
Brian Paule06565b2008-07-04 09:58:55 -06001083 if (shProg->LinkStatus == GL_FALSE) {
1084 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1085 return -1;
1086 }
1087
Brian Paul530df582008-07-03 16:21:11 -06001088 /* XXX we should return -1 if the uniform was declared, but not
1089 * actually used.
1090 */
1091
Brian Paulade50832008-05-14 16:09:46 -06001092 return _mesa_lookup_uniform(shProg->Uniforms, name);
Brian5b01c5e2006-12-19 18:02:03 -07001093}
1094
1095
Brian34ae99d2006-12-18 08:28:54 -07001096
Brian5b01c5e2006-12-19 18:02:03 -07001097/**
1098 * Called via ctx->Driver.ShaderSource()
1099 */
Brian Paulfd59f192008-05-18 16:04:55 -06001100static void
Brian5b01c5e2006-12-19 18:02:03 -07001101_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001102{
Brian Paul530df582008-07-03 16:21:11 -06001103 struct gl_shader *sh;
1104
1105 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1106 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001107 return;
Brian34ae99d2006-12-18 08:28:54 -07001108
Brian34ae99d2006-12-18 08:28:54 -07001109 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001110 if (sh->Source) {
1111 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001112 }
Brian65a18442006-12-19 18:46:56 -07001113 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001114 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001115}
1116
1117
Brian5b01c5e2006-12-19 18:02:03 -07001118/**
1119 * Called via ctx->Driver.CompileShader()
1120 */
Brian Paulfd59f192008-05-18 16:04:55 -06001121static void
Brian5b01c5e2006-12-19 18:02:03 -07001122_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001123{
Brian Paul530df582008-07-03 16:21:11 -06001124 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001125
Brian Paul530df582008-07-03 16:21:11 -06001126 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1127 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001128 return;
Brian34ae99d2006-12-18 08:28:54 -07001129
Brian43975832007-01-04 08:21:09 -07001130 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001131}
1132
1133
Brian5b01c5e2006-12-19 18:02:03 -07001134/**
1135 * Called via ctx->Driver.LinkProgram()
1136 */
Brian Paulfd59f192008-05-18 16:04:55 -06001137static void
Brian5b01c5e2006-12-19 18:02:03 -07001138_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001139{
Brian65a18442006-12-19 18:46:56 -07001140 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001141
Brian Paul530df582008-07-03 16:21:11 -06001142 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1143 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001144 return;
Brian34ae99d2006-12-18 08:28:54 -07001145
Briandf43fb62008-05-06 23:08:51 -06001146 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1147
Brianc1771912007-02-16 09:56:19 -07001148 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001149}
1150
1151
1152/**
Brian5b01c5e2006-12-19 18:02:03 -07001153 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001154 */
Brian5b01c5e2006-12-19 18:02:03 -07001155void
1156_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001157{
Brian3c008a02007-04-12 15:22:32 -06001158 struct gl_shader_program *shProg;
1159
Brian00d63aa2007-02-03 11:35:02 -07001160 if (ctx->Shader.CurrentProgram &&
1161 ctx->Shader.CurrentProgram->Name == program) {
1162 /* no-op */
1163 return;
1164 }
1165
1166 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1167
Brian5b01c5e2006-12-19 18:02:03 -07001168 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001169 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001170 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001171 return;
1172 }
1173 if (!shProg->LinkStatus) {
1174 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
Brian5b01c5e2006-12-19 18:02:03 -07001175 return;
1176 }
Brian5b01c5e2006-12-19 18:02:03 -07001177 }
1178 else {
Brian3c008a02007-04-12 15:22:32 -06001179 shProg = NULL;
1180 }
1181
1182 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001183}
Brian34ae99d2006-12-18 08:28:54 -07001184
Brian5b01c5e2006-12-19 18:02:03 -07001185
Brian Paulade50832008-05-14 16:09:46 -06001186
1187/**
1188 * Update the vertex and fragment program's TexturesUsed arrays.
1189 */
1190static void
1191update_textures_used(struct gl_program *prog)
1192{
1193 GLuint s;
1194
1195 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1196
1197 for (s = 0; s < MAX_SAMPLERS; s++) {
1198 if (prog->SamplersUsed & (1 << s)) {
1199 GLuint u = prog->SamplerUnits[s];
1200 GLuint t = prog->SamplerTargets[s];
1201 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1202 prog->TexturesUsed[u] |= (1 << t);
1203 }
1204 }
1205}
1206
1207
Brianb36749d2008-07-21 20:42:05 -06001208static GLboolean
1209is_sampler_type(GLenum type)
1210{
1211 switch (type) {
1212 case GL_SAMPLER_1D:
1213 case GL_SAMPLER_2D:
1214 case GL_SAMPLER_3D:
1215 case GL_SAMPLER_CUBE:
1216 case GL_SAMPLER_1D_SHADOW:
1217 case GL_SAMPLER_2D_SHADOW:
1218 case GL_SAMPLER_2D_RECT_ARB:
1219 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1220 case GL_SAMPLER_1D_ARRAY_EXT:
1221 case GL_SAMPLER_2D_ARRAY_EXT:
1222 return GL_TRUE;
1223 default:
1224 return GL_FALSE;
1225 }
1226}
1227
1228
Brian Paulade50832008-05-14 16:09:46 -06001229/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001230 * Check if the type given by userType is allowed to set a uniform of the
1231 * target type. Generally, equivalence is required, but setting Boolean
1232 * uniforms can be done with glUniformiv or glUniformfv.
1233 */
1234static GLboolean
1235compatible_types(GLenum userType, GLenum targetType)
1236{
1237 if (userType == targetType)
1238 return GL_TRUE;
1239
1240 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1241 return GL_TRUE;
1242
1243 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1244 userType == GL_INT_VEC2))
1245 return GL_TRUE;
1246
1247 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1248 userType == GL_INT_VEC3))
1249 return GL_TRUE;
1250
1251 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1252 userType == GL_INT_VEC4))
1253 return GL_TRUE;
1254
Brianb36749d2008-07-21 20:42:05 -06001255 if (is_sampler_type(targetType) && userType == GL_INT)
1256 return GL_TRUE;
1257
Brian Paulffbc66b2008-07-21 13:58:50 -06001258 return GL_FALSE;
1259}
1260
1261
1262/**
Brian Paulade50832008-05-14 16:09:46 -06001263 * Set the value of a program's uniform variable.
1264 * \param program the program whose uniform to update
1265 * \param location the location/index of the uniform
1266 * \param type the datatype of the uniform
1267 * \param count the number of uniforms to set
1268 * \param elems number of elements per uniform
1269 * \param values the new values
1270 */
1271static void
1272set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
Brian Paul530df582008-07-03 16:21:11 -06001273 GLenum type, GLsizei count, GLint elems, const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001274{
Brian Paulffbc66b2008-07-21 13:58:50 -06001275 if (!compatible_types(type,
1276 program->Parameters->Parameters[location].DataType)) {
1277 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1278 return;
1279 }
1280
Brian Paulade50832008-05-14 16:09:46 -06001281 if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
1282 /* This controls which texture unit which is used by a sampler */
1283 GLuint texUnit, sampler;
1284
1285 /* data type for setting samplers must be int */
1286 if (type != GL_INT || count != 1) {
1287 _mesa_error(ctx, GL_INVALID_OPERATION,
1288 "glUniform(only glUniform1i can be used "
1289 "to set sampler uniforms)");
1290 return;
1291 }
1292
1293 sampler = (GLuint) program->Parameters->ParameterValues[location][0];
1294 texUnit = ((GLuint *) values)[0];
1295
1296 /* check that the sampler (tex unit index) is legal */
1297 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1298 _mesa_error(ctx, GL_INVALID_VALUE,
1299 "glUniform1(invalid sampler/tex unit index)");
1300 return;
1301 }
1302
1303 /* This maps a sampler to a texture unit: */
1304 program->SamplerUnits[sampler] = texUnit;
1305 update_textures_used(program);
1306
1307 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1308 }
1309 else {
1310 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001311 GLsizei k, i;
Brian Paulade50832008-05-14 16:09:46 -06001312
1313 if (count * elems > program->Parameters->Parameters[location].Size) {
1314 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1315 return;
1316 }
1317
1318 for (k = 0; k < count; k++) {
1319 GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
1320 if (type == GL_INT ||
1321 type == GL_INT_VEC2 ||
1322 type == GL_INT_VEC3 ||
1323 type == GL_INT_VEC4) {
1324 const GLint *iValues = ((const GLint *) values) + k * elems;
1325 for (i = 0; i < elems; i++) {
1326 uniformVal[i] = (GLfloat) iValues[i];
1327 }
1328 }
1329 else {
1330 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1331 for (i = 0; i < elems; i++) {
1332 uniformVal[i] = fValues[i];
1333 }
1334 }
1335 }
1336 }
1337}
1338
1339
Brian5b01c5e2006-12-19 18:02:03 -07001340/**
1341 * Called via ctx->Driver.Uniform().
1342 */
Brian Paulfd59f192008-05-18 16:04:55 -06001343static void
Brian5b01c5e2006-12-19 18:02:03 -07001344_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1345 const GLvoid *values, GLenum type)
1346{
Brian3a8e2772006-12-20 17:19:16 -07001347 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001348 GLint elems;
Brian3a8e2772006-12-20 17:19:16 -07001349
1350 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001351 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001352 return;
1353 }
1354
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001355 if (location == -1)
1356 return; /* The standard specifies this as a no-op */
1357
Brian Paulade50832008-05-14 16:09:46 -06001358 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1359 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001360 return;
1361 }
1362
Brian52363952007-03-13 16:50:24 -06001363 if (count < 0) {
1364 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1365 return;
1366 }
1367
Brian98650bd2007-03-13 16:32:48 -06001368 switch (type) {
1369 case GL_FLOAT:
1370 case GL_INT:
1371 elems = 1;
1372 break;
1373 case GL_FLOAT_VEC2:
1374 case GL_INT_VEC2:
1375 elems = 2;
1376 break;
1377 case GL_FLOAT_VEC3:
1378 case GL_INT_VEC3:
1379 elems = 3;
1380 break;
1381 case GL_FLOAT_VEC4:
1382 case GL_INT_VEC4:
1383 elems = 4;
1384 break;
1385 default:
1386 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1387 return;
Brian89dc4852007-01-04 14:35:44 -07001388 }
Brian98650bd2007-03-13 16:32:48 -06001389
Brian Paulade50832008-05-14 16:09:46 -06001390 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001391
Brian Paulade50832008-05-14 16:09:46 -06001392 /* A uniform var may be used by both a vertex shader and a fragment
1393 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001394 */
Brian Paulade50832008-05-14 16:09:46 -06001395 if (shProg->VertexProgram) {
1396 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1397 if (loc >= 0) {
1398 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1399 loc, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001400 }
Brian5b01c5e2006-12-19 18:02:03 -07001401 }
Brian5cf73262007-01-05 16:02:45 -07001402
Brian Paulade50832008-05-14 16:09:46 -06001403 if (shProg->FragmentProgram) {
1404 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1405 if (loc >= 0) {
1406 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1407 loc, type, count, elems, values);
1408 }
1409 }
1410}
1411
1412
1413static void
Brian Paulffbc66b2008-07-21 13:58:50 -06001414get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1415{
1416 switch (type) {
1417 case GL_FLOAT_MAT2:
1418 *rows = *cols = 2;
1419 break;
1420 case GL_FLOAT_MAT2x3:
1421 *rows = 3;
1422 *cols = 2;
1423 break;
1424 case GL_FLOAT_MAT2x4:
1425 *rows = 4;
1426 *cols = 2;
1427 break;
1428 case GL_FLOAT_MAT3:
1429 *rows = 3;
1430 *cols = 3;
1431 break;
1432 case GL_FLOAT_MAT3x2:
1433 *rows = 2;
1434 *cols = 3;
1435 break;
1436 case GL_FLOAT_MAT3x4:
1437 *rows = 4;
1438 *cols = 3;
1439 break;
1440 case GL_FLOAT_MAT4:
1441 *rows = 4;
1442 *cols = 4;
1443 break;
1444 case GL_FLOAT_MAT4x2:
1445 *rows = 2;
1446 *cols = 4;
1447 break;
1448 case GL_FLOAT_MAT4x3:
1449 *rows = 3;
1450 *cols = 4;
1451 break;
1452 default:
1453 *rows = *cols = 0;
1454 }
1455}
1456
1457
1458static void
Brian Paulade50832008-05-14 16:09:46 -06001459set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001460 GLuint location, GLuint count,
1461 GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001462 GLboolean transpose, const GLfloat *values)
1463{
Brian Paulffbc66b2008-07-21 13:58:50 -06001464 GLuint mat, row, col;
1465 GLuint dst = location, src = 0;
1466 GLint nr, nc;
1467
1468 /* check that the number of rows, columns is correct */
1469 get_matrix_dims(program->Parameters->Parameters[location].DataType, &nr, &nc);
1470 if (rows != nr || cols != nc) {
1471 _mesa_error(ctx, GL_INVALID_OPERATION,
1472 "glUniformMatrix(matrix size mismatch");
1473 return;
1474 }
1475
Brian Paulade50832008-05-14 16:09:46 -06001476 /*
1477 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001478 * the rows. So, the loops below look a little funny.
1479 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001480 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001481
1482 /* loop over matrices */
1483 for (mat = 0; mat < count; mat++) {
1484
1485 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001486 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001487 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001488 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001489 if (transpose) {
1490 v[row] = values[src + row * cols + col];
1491 }
1492 else {
1493 v[row] = values[src + col * rows + row];
1494 }
Brian Paulade50832008-05-14 16:09:46 -06001495 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001496 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001497 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001498
1499 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001500 }
Brian34ae99d2006-12-18 08:28:54 -07001501}
1502
1503
1504/**
Brian5b01c5e2006-12-19 18:02:03 -07001505 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001506 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001507 */
Brian Paulfd59f192008-05-18 16:04:55 -06001508static void
Brian5b01c5e2006-12-19 18:02:03 -07001509_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1510 GLenum matrixType, GLint location, GLsizei count,
1511 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001512{
Brian3a8e2772006-12-20 17:19:16 -07001513 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001514
Brian3a8e2772006-12-20 17:19:16 -07001515 if (!shProg || !shProg->LinkStatus) {
1516 _mesa_error(ctx, GL_INVALID_OPERATION,
1517 "glUniformMatrix(program not linked)");
1518 return;
1519 }
Brian Paulade50832008-05-14 16:09:46 -06001520
Bruce Merry89b80322007-12-21 15:20:17 +02001521 if (location == -1)
1522 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001523
1524 if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
1525 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001526 return;
1527 }
Brian34ae99d2006-12-18 08:28:54 -07001528 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001529 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001530 return;
1531 }
1532
1533 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1534
Brian Paulade50832008-05-14 16:09:46 -06001535 if (shProg->VertexProgram) {
1536 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1537 if (loc >= 0) {
1538 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001539 loc, count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001540 }
Brian Paulade50832008-05-14 16:09:46 -06001541 }
1542
1543 if (shProg->FragmentProgram) {
1544 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1545 if (loc >= 0) {
1546 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001547 loc, count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001548 }
Brian34ae99d2006-12-18 08:28:54 -07001549 }
1550}
1551
1552
Brian Paulfd59f192008-05-18 16:04:55 -06001553static void
Brian5b01c5e2006-12-19 18:02:03 -07001554_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001555{
Brian65a18442006-12-19 18:46:56 -07001556 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001557
1558 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001559 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001560 return;
1561 }
1562
Brian Paulbc985b52008-07-21 14:16:07 -06001563 if (!shProg->LinkStatus) {
1564 shProg->Validated = GL_FALSE;
1565 return;
1566 }
1567
1568 /* From the GL spec, a program is invalid if any of these are true:
1569
Brian5b01c5e2006-12-19 18:02:03 -07001570 any two active samplers in the current program object are of
1571 different types, but refer to the same texture image unit,
1572
1573 any active sampler in the current program object refers to a texture
1574 image unit where fixed-function fragment processing accesses a
1575 texture target that does not match the sampler type, or
1576
1577 the sum of the number of active samplers in the program and the
1578 number of texture image units enabled for fixed-function fragment
1579 processing exceeds the combined limit on the total number of texture
1580 image units allowed.
1581 */
Brian Paulbc985b52008-07-21 14:16:07 -06001582
1583 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001584}
Brian Paulfd59f192008-05-18 16:04:55 -06001585
1586
1587/**
1588 * Plug in Mesa's GLSL functions into the device driver function table.
1589 */
1590void
1591_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1592{
1593 driver->AttachShader = _mesa_attach_shader;
1594 driver->BindAttribLocation = _mesa_bind_attrib_location;
1595 driver->CompileShader = _mesa_compile_shader;
1596 driver->CreateProgram = _mesa_create_program;
1597 driver->CreateShader = _mesa_create_shader;
1598 driver->DeleteProgram2 = _mesa_delete_program2;
1599 driver->DeleteShader = _mesa_delete_shader;
1600 driver->DetachShader = _mesa_detach_shader;
1601 driver->GetActiveAttrib = _mesa_get_active_attrib;
1602 driver->GetActiveUniform = _mesa_get_active_uniform;
1603 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1604 driver->GetAttribLocation = _mesa_get_attrib_location;
1605 driver->GetHandle = _mesa_get_handle;
1606 driver->GetProgramiv = _mesa_get_programiv;
1607 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1608 driver->GetShaderiv = _mesa_get_shaderiv;
1609 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1610 driver->GetShaderSource = _mesa_get_shader_source;
1611 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06001612 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06001613 driver->GetUniformLocation = _mesa_get_uniform_location;
1614 driver->IsProgram = _mesa_is_program;
1615 driver->IsShader = _mesa_is_shader;
1616 driver->LinkProgram = _mesa_link_program;
1617 driver->ShaderSource = _mesa_shader_source;
1618 driver->Uniform = _mesa_uniform;
1619 driver->UniformMatrix = _mesa_uniform_matrix;
1620 driver->UseProgram = _mesa_use_program;
1621 driver->ValidateProgram = _mesa_validate_program;
1622}