blob: a401803c3e9d09e7b688a6b558f8f3c500b077a9 [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 Paulffbc66b2008-07-21 13:58:50 -0600512 GLenum datatype;
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");
546 }
547
Brian9f660252007-04-11 09:00:56 -0600548 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
549 /* If the index changed, need to search/replace references to that attribute
550 * in the vertex program.
551 */
Brian3209c3e2007-01-09 17:49:24 -0700552 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
553 }
Brian34ae99d2006-12-18 08:28:54 -0700554}
555
556
Brian Paulfd59f192008-05-18 16:04:55 -0600557static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700558_mesa_create_shader(GLcontext *ctx, GLenum type)
559{
Brian65a18442006-12-19 18:46:56 -0700560 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700561 GLuint name;
562
563 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
564
565 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700566 case GL_FRAGMENT_SHADER:
567 case GL_VERTEX_SHADER:
568 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700569 break;
570 default:
571 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
572 return 0;
573 }
574
Brian65a18442006-12-19 18:46:56 -0700575 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700576
577 return name;
578}
579
580
Brian Paulfd59f192008-05-18 16:04:55 -0600581static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700582_mesa_create_program(GLcontext *ctx)
583{
584 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700585 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700586
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800587 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700588 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700589
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800590 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700591
Brian3c008a02007-04-12 15:22:32 -0600592 assert(shProg->RefCount == 1);
593
Brian5b01c5e2006-12-19 18:02:03 -0700594 return name;
595}
596
597
Brian3c008a02007-04-12 15:22:32 -0600598/**
599 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
600 * DeleteProgramARB.
601 */
Brian Paulfd59f192008-05-18 16:04:55 -0600602static void
Brian5b01c5e2006-12-19 18:02:03 -0700603_mesa_delete_program2(GLcontext *ctx, GLuint name)
604{
Brian3c008a02007-04-12 15:22:32 -0600605 /*
606 * NOTE: deleting shaders/programs works a bit differently than
607 * texture objects (and buffer objects, etc). Shader/program
608 * handles/IDs exist in the hash table until the object is really
609 * deleted (refcount==0). With texture objects, the handle/ID is
610 * removed from the hash table in glDeleteTextures() while the tex
611 * object itself might linger until its refcount goes to zero.
612 */
Brian65a18442006-12-19 18:46:56 -0700613 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700614
Brian Paul530df582008-07-03 16:21:11 -0600615 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
616 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700617 return;
Brian5b01c5e2006-12-19 18:02:03 -0700618
Brian9e4bae92006-12-20 09:27:42 -0700619 shProg->DeletePending = GL_TRUE;
620
Brian3c008a02007-04-12 15:22:32 -0600621 /* effectively, decr shProg's refcount */
622 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700623}
624
625
Brian Paulfd59f192008-05-18 16:04:55 -0600626static void
Brian5b01c5e2006-12-19 18:02:03 -0700627_mesa_delete_shader(GLcontext *ctx, GLuint shader)
628{
Brian Paul530df582008-07-03 16:21:11 -0600629 struct gl_shader *sh;
630
631 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
632 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700633 return;
Brian5b01c5e2006-12-19 18:02:03 -0700634
Brian9e4bae92006-12-20 09:27:42 -0700635 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600636
637 /* effectively, decr sh's refcount */
638 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700639}
640
641
Brian Paulfd59f192008-05-18 16:04:55 -0600642static void
Brian5b01c5e2006-12-19 18:02:03 -0700643_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
644{
Brian Paul530df582008-07-03 16:21:11 -0600645 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100646 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700647 GLuint i, j;
648
Brian Paul530df582008-07-03 16:21:11 -0600649 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
650 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700651 return;
Brian5b01c5e2006-12-19 18:02:03 -0700652
Brian237b9852007-08-07 21:48:31 +0100653 n = shProg->NumShaders;
654
Brian5b01c5e2006-12-19 18:02:03 -0700655 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700656 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700657 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600658 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700659
Brian Paul530df582008-07-03 16:21:11 -0600660 /* release */
Brian3c008a02007-04-12 15:22:32 -0600661 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700662
Brian5b01c5e2006-12-19 18:02:03 -0700663 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700664 newList = (struct gl_shader **)
665 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700666 if (!newList) {
667 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
668 return;
669 }
670 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700671 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700672 }
673 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700674 newList[j++] = shProg->Shaders[i];
675 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700676
Brian65a18442006-12-19 18:46:56 -0700677 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600678 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600679
680#ifdef DEBUG
681 /* sanity check */
682 {
683 for (j = 0; j < shProg->NumShaders; j++) {
684 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
685 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
686 assert(shProg->Shaders[j]->RefCount > 0);
687 }
688 }
689#endif
690
Brian5b01c5e2006-12-19 18:02:03 -0700691 return;
692 }
693 }
694
695 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600696 {
697 GLenum err;
698 if (_mesa_is_shader(ctx, shader))
699 err = GL_INVALID_OPERATION;
700 else if (_mesa_is_program(ctx, shader))
701 err = GL_INVALID_OPERATION;
702 else
703 err = GL_INVALID_VALUE;
704 _mesa_error(ctx, err, "glDetachProgram(shader)");
705 return;
706 }
Brian5b01c5e2006-12-19 18:02:03 -0700707}
708
709
Brian Paulffbc66b2008-07-21 13:58:50 -0600710static GLint
711sizeof_glsl_type(GLenum type)
712{
713 switch (type) {
714 case GL_FLOAT:
715 case GL_INT:
716 case GL_BOOL:
717 return 1;
718 case GL_FLOAT_VEC2:
719 case GL_INT_VEC2:
720 case GL_BOOL_VEC2:
721 return 2;
722 case GL_FLOAT_VEC3:
723 case GL_INT_VEC3:
724 case GL_BOOL_VEC3:
725 return 3;
726 case GL_FLOAT_VEC4:
727 case GL_INT_VEC4:
728 case GL_BOOL_VEC4:
729 return 4;
730 case GL_FLOAT_MAT2:
731 case GL_FLOAT_MAT2x3:
732 case GL_FLOAT_MAT2x4:
733 return 8; /* two float[4] vectors */
734 case GL_FLOAT_MAT3:
735 case GL_FLOAT_MAT3x2:
736 case GL_FLOAT_MAT3x4:
737 return 12; /* three float[4] vectors */
738 case GL_FLOAT_MAT4:
739 case GL_FLOAT_MAT4x2:
740 case GL_FLOAT_MAT4x3:
741 return 16; /* four float[4] vectors */
742 default:
743 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
744 return 1;
745 }
746}
747
748
Brian Paulfd59f192008-05-18 16:04:55 -0600749static void
Brian5b01c5e2006-12-19 18:02:03 -0700750_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
751 GLsizei maxLength, GLsizei *length, GLint *size,
752 GLenum *type, GLchar *nameOut)
753{
Brian Paul530df582008-07-03 16:21:11 -0600754 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700755
Brian Paul530df582008-07-03 16:21:11 -0600756 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
757 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700758 return;
Brian5b01c5e2006-12-19 18:02:03 -0700759
Brian65a18442006-12-19 18:46:56 -0700760 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600761 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700762 return;
763 }
764
765 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700766 shProg->Attributes->Parameters[index].Name);
Brian5b01c5e2006-12-19 18:02:03 -0700767 if (size)
Brian Paulffbc66b2008-07-21 13:58:50 -0600768 *size = shProg->Attributes->Parameters[index].Size
769 / sizeof_glsl_type(shProg->Attributes->Parameters[index].DataType);
Brian Paulade50832008-05-14 16:09:46 -0600770 if (type)
Brian Paulffbc66b2008-07-21 13:58:50 -0600771 *type = shProg->Attributes->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700772}
773
774
775/**
776 * Called via ctx->Driver.GetActiveUniform().
777 */
Brian Paulfd59f192008-05-18 16:04:55 -0600778static void
Brian5b01c5e2006-12-19 18:02:03 -0700779_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
780 GLsizei maxLength, GLsizei *length, GLint *size,
781 GLenum *type, GLchar *nameOut)
782{
Brian Paul530df582008-07-03 16:21:11 -0600783 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600784 const struct gl_program *prog;
785 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700786
Brian Paul530df582008-07-03 16:21:11 -0600787 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
788 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700789 return;
Brian5b01c5e2006-12-19 18:02:03 -0700790
Brian Paulade50832008-05-14 16:09:46 -0600791 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700792 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
793 return;
794 }
795
Brian Paulade50832008-05-14 16:09:46 -0600796 progPos = shProg->Uniforms->Uniforms[index].VertPos;
797 if (progPos >= 0) {
798 prog = &shProg->VertexProgram->Base;
799 }
800 else {
801 progPos = shProg->Uniforms->Uniforms[index].FragPos;
802 if (progPos >= 0) {
803 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600804 }
805 }
806
Brian Paulade50832008-05-14 16:09:46 -0600807 if (!prog || progPos < 0)
808 return; /* should never happen */
809
810 if (nameOut)
811 copy_string(nameOut, maxLength, length,
812 prog->Parameters->Parameters[progPos].Name);
813 if (size)
Brian Paulffbc66b2008-07-21 13:58:50 -0600814 *size = prog->Parameters->Parameters[progPos].Size
815 / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType);
Brian Paulade50832008-05-14 16:09:46 -0600816 if (type)
817 *type = prog->Parameters->Parameters[progPos].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700818}
819
820
821/**
822 * Called via ctx->Driver.GetAttachedShaders().
823 */
Brian Paulfd59f192008-05-18 16:04:55 -0600824static void
Brian5b01c5e2006-12-19 18:02:03 -0700825_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
826 GLsizei *count, GLuint *obj)
827{
Brian Paul530df582008-07-03 16:21:11 -0600828 struct gl_shader_program *shProg =
829 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700830 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600831 GLuint i;
832 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700833 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700834 }
835 if (count)
836 *count = i;
837 }
Brian5b01c5e2006-12-19 18:02:03 -0700838}
839
840
Brian Paulfd59f192008-05-18 16:04:55 -0600841static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700842_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700843{
844#if 0
845 GET_CURRENT_CONTEXT(ctx);
846
847 switch (pname) {
848 case GL_PROGRAM_OBJECT_ARB:
849 {
Brian5b01c5e2006-12-19 18:02:03 -0700850 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700851
852 if (pro != NULL)
853 return (**pro)._container._generic.
854 GetName((struct gl2_generic_intf **) (pro));
855 }
856 break;
857 default:
858 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
859 }
860#endif
861 return 0;
862}
863
864
Brian Paulfd59f192008-05-18 16:04:55 -0600865static void
Brian5b01c5e2006-12-19 18:02:03 -0700866_mesa_get_programiv(GLcontext *ctx, GLuint program,
867 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700868{
Brian65a18442006-12-19 18:46:56 -0700869 struct gl_shader_program *shProg
870 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700871
Brian65a18442006-12-19 18:46:56 -0700872 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700873 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700874 return;
875 }
876
Brian5b01c5e2006-12-19 18:02:03 -0700877 switch (pname) {
878 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700879 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700880 break;
881 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700882 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700883 break;
Brian5b01c5e2006-12-19 18:02:03 -0700884 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700885 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700886 break;
887 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600888 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700889 break;
890 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700891 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700892 break;
893 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700894 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700895 break;
896 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian274ac7a2007-04-18 16:05:53 -0600897 *params = _mesa_longest_parameter_name(shProg->Attributes,
898 PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700899 break;
900 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600901 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700902 break;
903 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600904 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600905 if (*params > 0)
906 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700907 break;
908 default:
Brian5b01c5e2006-12-19 18:02:03 -0700909 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
910 return;
Brian34ae99d2006-12-18 08:28:54 -0700911 }
Brian5b01c5e2006-12-19 18:02:03 -0700912}
Brian34ae99d2006-12-18 08:28:54 -0700913
Brian34ae99d2006-12-18 08:28:54 -0700914
Brian Paulfd59f192008-05-18 16:04:55 -0600915static void
Brian5b01c5e2006-12-19 18:02:03 -0700916_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
917{
Brian Paul530df582008-07-03 16:21:11 -0600918 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700919
920 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700921 return;
922 }
Brian65a18442006-12-19 18:46:56 -0700923
Brian5b01c5e2006-12-19 18:02:03 -0700924 switch (pname) {
925 case GL_SHADER_TYPE:
926 *params = shader->Type;
927 break;
928 case GL_DELETE_STATUS:
929 *params = shader->DeletePending;
930 break;
931 case GL_COMPILE_STATUS:
932 *params = shader->CompileStatus;
933 break;
934 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600935 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700936 break;
937 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600938 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700939 break;
940 default:
941 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
942 return;
943 }
944}
945
946
Brian Paulfd59f192008-05-18 16:04:55 -0600947static void
Brian5b01c5e2006-12-19 18:02:03 -0700948_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
949 GLsizei *length, GLchar *infoLog)
950{
Brian65a18442006-12-19 18:46:56 -0700951 struct gl_shader_program *shProg
952 = _mesa_lookup_shader_program(ctx, program);
953 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700954 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
955 return;
956 }
Brian65a18442006-12-19 18:46:56 -0700957 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700958}
959
960
Brian Paulfd59f192008-05-18 16:04:55 -0600961static void
Brian5b01c5e2006-12-19 18:02:03 -0700962_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
963 GLsizei *length, GLchar *infoLog)
964{
Brian65a18442006-12-19 18:46:56 -0700965 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
966 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700967 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
968 return;
969 }
Brian65a18442006-12-19 18:46:56 -0700970 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700971}
972
973
974/**
975 * Called via ctx->Driver.GetShaderSource().
976 */
Brian Paulfd59f192008-05-18 16:04:55 -0600977static void
Brian5b01c5e2006-12-19 18:02:03 -0700978_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
979 GLsizei *length, GLchar *sourceOut)
980{
Brian Paul530df582008-07-03 16:21:11 -0600981 struct gl_shader *sh;
982 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -0700983 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700984 return;
985 }
Brian65a18442006-12-19 18:46:56 -0700986 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700987}
988
989
Brian Paul2be54a82008-07-08 16:17:04 -0600990#define MAX_UNIFORM_ELEMENTS 16
991
Brian5b01c5e2006-12-19 18:02:03 -0700992/**
Brian Paul2be54a82008-07-08 16:17:04 -0600993 * Helper for GetUniformfv(), GetUniformiv()
994 * Returns number of elements written to 'params' output.
Brian5b01c5e2006-12-19 18:02:03 -0700995 */
Brian Paul2be54a82008-07-08 16:17:04 -0600996static GLuint
997get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
998 GLfloat *params)
Brian5b01c5e2006-12-19 18:02:03 -0700999{
Brian65a18442006-12-19 18:46:56 -07001000 struct gl_shader_program *shProg
1001 = _mesa_lookup_shader_program(ctx, program);
1002 if (shProg) {
Brian Paul6cb12702008-06-28 16:48:31 -06001003 if (shProg->Uniforms &&
1004 location >= 0 && location < shProg->Uniforms->NumUniforms) {
1005 GLint progPos;
1006 GLuint i;
Brian Paulf2632212008-05-16 10:49:44 -06001007 const struct gl_program *prog = NULL;
Brian Paulade50832008-05-14 16:09:46 -06001008
1009 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1010 if (progPos >= 0) {
1011 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001012 }
Brian Paulade50832008-05-14 16:09:46 -06001013 else {
1014 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1015 if (progPos >= 0) {
1016 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001017 }
Brian Paulade50832008-05-14 16:09:46 -06001018 }
1019
Brian Paulf2632212008-05-16 10:49:44 -06001020 ASSERT(prog);
1021 if (prog) {
Brian Paul2be54a82008-07-08 16:17:04 -06001022 /* See uniformiv() below */
1023 assert(prog->Parameters->Parameters[progPos].Size <= MAX_UNIFORM_ELEMENTS);
1024
Brian Paulf2632212008-05-16 10:49:44 -06001025 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
1026 params[i] = prog->Parameters->ParameterValues[progPos][i];
1027 }
Brian Paul2be54a82008-07-08 16:17:04 -06001028 return prog->Parameters->Parameters[progPos].Size;
Brian Paulade50832008-05-14 16:09:46 -06001029 }
Brian5b01c5e2006-12-19 18:02:03 -07001030 }
1031 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001032 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
Brian5b01c5e2006-12-19 18:02:03 -07001033 }
1034 }
1035 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001036 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -07001037 }
Brian Paul2be54a82008-07-08 16:17:04 -06001038 return 0;
1039}
1040
1041
1042/**
1043 * Called via ctx->Driver.GetUniformfv().
1044 */
1045static void
1046_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1047 GLfloat *params)
1048{
1049 (void) get_uniformfv(ctx, program, location, params);
1050}
1051
1052
1053/**
1054 * Called via ctx->Driver.GetUniformiv().
1055 */
1056static void
1057_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1058 GLint *params)
1059{
1060 GLfloat fparams[MAX_UNIFORM_ELEMENTS];
1061 GLuint n = get_uniformfv(ctx, program, location, fparams);
1062 GLuint i;
1063 assert(n <= MAX_UNIFORM_ELEMENTS);
1064 for (i = 0; i < n; i++) {
1065 params[i] = (GLint) fparams[i];
1066 }
Brian5b01c5e2006-12-19 18:02:03 -07001067}
1068
1069
1070/**
1071 * Called via ctx->Driver.GetUniformLocation().
1072 */
Brian Paulfd59f192008-05-18 16:04:55 -06001073static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001074_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1075{
Brian Paul530df582008-07-03 16:21:11 -06001076 struct gl_shader_program *shProg =
1077 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1078
Brian Paulade50832008-05-14 16:09:46 -06001079 if (!shProg)
1080 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001081
Brian Paule06565b2008-07-04 09:58:55 -06001082 if (shProg->LinkStatus == GL_FALSE) {
1083 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1084 return -1;
1085 }
1086
Brian Paul530df582008-07-03 16:21:11 -06001087 /* XXX we should return -1 if the uniform was declared, but not
1088 * actually used.
1089 */
1090
Brian Paulade50832008-05-14 16:09:46 -06001091 return _mesa_lookup_uniform(shProg->Uniforms, name);
Brian5b01c5e2006-12-19 18:02:03 -07001092}
1093
1094
Brian34ae99d2006-12-18 08:28:54 -07001095
Brian5b01c5e2006-12-19 18:02:03 -07001096/**
1097 * Called via ctx->Driver.ShaderSource()
1098 */
Brian Paulfd59f192008-05-18 16:04:55 -06001099static void
Brian5b01c5e2006-12-19 18:02:03 -07001100_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001101{
Brian Paul530df582008-07-03 16:21:11 -06001102 struct gl_shader *sh;
1103
1104 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1105 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001106 return;
Brian34ae99d2006-12-18 08:28:54 -07001107
Brian34ae99d2006-12-18 08:28:54 -07001108 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001109 if (sh->Source) {
1110 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001111 }
Brian65a18442006-12-19 18:46:56 -07001112 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001113 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001114}
1115
1116
Brian5b01c5e2006-12-19 18:02:03 -07001117/**
1118 * Called via ctx->Driver.CompileShader()
1119 */
Brian Paulfd59f192008-05-18 16:04:55 -06001120static void
Brian5b01c5e2006-12-19 18:02:03 -07001121_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001122{
Brian Paul530df582008-07-03 16:21:11 -06001123 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001124
Brian Paul530df582008-07-03 16:21:11 -06001125 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1126 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001127 return;
Brian34ae99d2006-12-18 08:28:54 -07001128
Brian43975832007-01-04 08:21:09 -07001129 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001130}
1131
1132
Brian5b01c5e2006-12-19 18:02:03 -07001133/**
1134 * Called via ctx->Driver.LinkProgram()
1135 */
Brian Paulfd59f192008-05-18 16:04:55 -06001136static void
Brian5b01c5e2006-12-19 18:02:03 -07001137_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001138{
Brian65a18442006-12-19 18:46:56 -07001139 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001140
Brian Paul530df582008-07-03 16:21:11 -06001141 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1142 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001143 return;
Brian34ae99d2006-12-18 08:28:54 -07001144
Briandf43fb62008-05-06 23:08:51 -06001145 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1146
Brianc1771912007-02-16 09:56:19 -07001147 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001148}
1149
1150
1151/**
Brian5b01c5e2006-12-19 18:02:03 -07001152 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001153 */
Brian5b01c5e2006-12-19 18:02:03 -07001154void
1155_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001156{
Brian3c008a02007-04-12 15:22:32 -06001157 struct gl_shader_program *shProg;
1158
Brian00d63aa2007-02-03 11:35:02 -07001159 if (ctx->Shader.CurrentProgram &&
1160 ctx->Shader.CurrentProgram->Name == program) {
1161 /* no-op */
1162 return;
1163 }
1164
1165 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1166
Brian5b01c5e2006-12-19 18:02:03 -07001167 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001168 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001169 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001170 return;
1171 }
1172 if (!shProg->LinkStatus) {
1173 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
Brian5b01c5e2006-12-19 18:02:03 -07001174 return;
1175 }
Brian5b01c5e2006-12-19 18:02:03 -07001176 }
1177 else {
Brian3c008a02007-04-12 15:22:32 -06001178 shProg = NULL;
1179 }
1180
1181 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001182}
Brian34ae99d2006-12-18 08:28:54 -07001183
Brian5b01c5e2006-12-19 18:02:03 -07001184
Brian Paulade50832008-05-14 16:09:46 -06001185
1186/**
1187 * Update the vertex and fragment program's TexturesUsed arrays.
1188 */
1189static void
1190update_textures_used(struct gl_program *prog)
1191{
1192 GLuint s;
1193
1194 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1195
1196 for (s = 0; s < MAX_SAMPLERS; s++) {
1197 if (prog->SamplersUsed & (1 << s)) {
1198 GLuint u = prog->SamplerUnits[s];
1199 GLuint t = prog->SamplerTargets[s];
1200 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1201 prog->TexturesUsed[u] |= (1 << t);
1202 }
1203 }
1204}
1205
1206
Brianb36749d2008-07-21 20:42:05 -06001207static GLboolean
1208is_sampler_type(GLenum type)
1209{
1210 switch (type) {
1211 case GL_SAMPLER_1D:
1212 case GL_SAMPLER_2D:
1213 case GL_SAMPLER_3D:
1214 case GL_SAMPLER_CUBE:
1215 case GL_SAMPLER_1D_SHADOW:
1216 case GL_SAMPLER_2D_SHADOW:
1217 case GL_SAMPLER_2D_RECT_ARB:
1218 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1219 case GL_SAMPLER_1D_ARRAY_EXT:
1220 case GL_SAMPLER_2D_ARRAY_EXT:
1221 return GL_TRUE;
1222 default:
1223 return GL_FALSE;
1224 }
1225}
1226
1227
Brian Paulade50832008-05-14 16:09:46 -06001228/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001229 * Check if the type given by userType is allowed to set a uniform of the
1230 * target type. Generally, equivalence is required, but setting Boolean
1231 * uniforms can be done with glUniformiv or glUniformfv.
1232 */
1233static GLboolean
1234compatible_types(GLenum userType, GLenum targetType)
1235{
1236 if (userType == targetType)
1237 return GL_TRUE;
1238
1239 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1240 return GL_TRUE;
1241
1242 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1243 userType == GL_INT_VEC2))
1244 return GL_TRUE;
1245
1246 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1247 userType == GL_INT_VEC3))
1248 return GL_TRUE;
1249
1250 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1251 userType == GL_INT_VEC4))
1252 return GL_TRUE;
1253
Brianb36749d2008-07-21 20:42:05 -06001254 if (is_sampler_type(targetType) && userType == GL_INT)
1255 return GL_TRUE;
1256
Brian Paulffbc66b2008-07-21 13:58:50 -06001257 return GL_FALSE;
1258}
1259
1260
1261/**
Brian Paulade50832008-05-14 16:09:46 -06001262 * Set the value of a program's uniform variable.
1263 * \param program the program whose uniform to update
1264 * \param location the location/index of the uniform
1265 * \param type the datatype of the uniform
1266 * \param count the number of uniforms to set
1267 * \param elems number of elements per uniform
1268 * \param values the new values
1269 */
1270static void
1271set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
Brian Paul530df582008-07-03 16:21:11 -06001272 GLenum type, GLsizei count, GLint elems, const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001273{
Brian Paulffbc66b2008-07-21 13:58:50 -06001274 if (!compatible_types(type,
1275 program->Parameters->Parameters[location].DataType)) {
1276 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1277 return;
1278 }
1279
Brian Paulade50832008-05-14 16:09:46 -06001280 if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
1281 /* This controls which texture unit which is used by a sampler */
1282 GLuint texUnit, sampler;
1283
1284 /* data type for setting samplers must be int */
1285 if (type != GL_INT || count != 1) {
1286 _mesa_error(ctx, GL_INVALID_OPERATION,
1287 "glUniform(only glUniform1i can be used "
1288 "to set sampler uniforms)");
1289 return;
1290 }
1291
1292 sampler = (GLuint) program->Parameters->ParameterValues[location][0];
1293 texUnit = ((GLuint *) values)[0];
1294
1295 /* check that the sampler (tex unit index) is legal */
1296 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1297 _mesa_error(ctx, GL_INVALID_VALUE,
1298 "glUniform1(invalid sampler/tex unit index)");
1299 return;
1300 }
1301
1302 /* This maps a sampler to a texture unit: */
1303 program->SamplerUnits[sampler] = texUnit;
1304 update_textures_used(program);
1305
1306 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1307 }
1308 else {
1309 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001310 GLsizei k, i;
Brian Paulade50832008-05-14 16:09:46 -06001311
1312 if (count * elems > program->Parameters->Parameters[location].Size) {
1313 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1314 return;
1315 }
1316
1317 for (k = 0; k < count; k++) {
1318 GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
1319 if (type == GL_INT ||
1320 type == GL_INT_VEC2 ||
1321 type == GL_INT_VEC3 ||
1322 type == GL_INT_VEC4) {
1323 const GLint *iValues = ((const GLint *) values) + k * elems;
1324 for (i = 0; i < elems; i++) {
1325 uniformVal[i] = (GLfloat) iValues[i];
1326 }
1327 }
1328 else {
1329 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1330 for (i = 0; i < elems; i++) {
1331 uniformVal[i] = fValues[i];
1332 }
1333 }
1334 }
1335 }
1336}
1337
1338
Brian5b01c5e2006-12-19 18:02:03 -07001339/**
1340 * Called via ctx->Driver.Uniform().
1341 */
Brian Paulfd59f192008-05-18 16:04:55 -06001342static void
Brian5b01c5e2006-12-19 18:02:03 -07001343_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1344 const GLvoid *values, GLenum type)
1345{
Brian3a8e2772006-12-20 17:19:16 -07001346 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001347 GLint elems;
Brian3a8e2772006-12-20 17:19:16 -07001348
1349 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001350 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001351 return;
1352 }
1353
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001354 if (location == -1)
1355 return; /* The standard specifies this as a no-op */
1356
Brian Paulade50832008-05-14 16:09:46 -06001357 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1358 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001359 return;
1360 }
1361
Brian52363952007-03-13 16:50:24 -06001362 if (count < 0) {
1363 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1364 return;
1365 }
1366
Brian98650bd2007-03-13 16:32:48 -06001367 switch (type) {
1368 case GL_FLOAT:
1369 case GL_INT:
1370 elems = 1;
1371 break;
1372 case GL_FLOAT_VEC2:
1373 case GL_INT_VEC2:
1374 elems = 2;
1375 break;
1376 case GL_FLOAT_VEC3:
1377 case GL_INT_VEC3:
1378 elems = 3;
1379 break;
1380 case GL_FLOAT_VEC4:
1381 case GL_INT_VEC4:
1382 elems = 4;
1383 break;
1384 default:
1385 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1386 return;
Brian89dc4852007-01-04 14:35:44 -07001387 }
Brian98650bd2007-03-13 16:32:48 -06001388
Brian Paulade50832008-05-14 16:09:46 -06001389 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001390
Brian Paulade50832008-05-14 16:09:46 -06001391 /* A uniform var may be used by both a vertex shader and a fragment
1392 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001393 */
Brian Paulade50832008-05-14 16:09:46 -06001394 if (shProg->VertexProgram) {
1395 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1396 if (loc >= 0) {
1397 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1398 loc, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001399 }
Brian5b01c5e2006-12-19 18:02:03 -07001400 }
Brian5cf73262007-01-05 16:02:45 -07001401
Brian Paulade50832008-05-14 16:09:46 -06001402 if (shProg->FragmentProgram) {
1403 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1404 if (loc >= 0) {
1405 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1406 loc, type, count, elems, values);
1407 }
1408 }
1409}
1410
1411
1412static void
Brian Paulffbc66b2008-07-21 13:58:50 -06001413get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1414{
1415 switch (type) {
1416 case GL_FLOAT_MAT2:
1417 *rows = *cols = 2;
1418 break;
1419 case GL_FLOAT_MAT2x3:
1420 *rows = 3;
1421 *cols = 2;
1422 break;
1423 case GL_FLOAT_MAT2x4:
1424 *rows = 4;
1425 *cols = 2;
1426 break;
1427 case GL_FLOAT_MAT3:
1428 *rows = 3;
1429 *cols = 3;
1430 break;
1431 case GL_FLOAT_MAT3x2:
1432 *rows = 2;
1433 *cols = 3;
1434 break;
1435 case GL_FLOAT_MAT3x4:
1436 *rows = 4;
1437 *cols = 3;
1438 break;
1439 case GL_FLOAT_MAT4:
1440 *rows = 4;
1441 *cols = 4;
1442 break;
1443 case GL_FLOAT_MAT4x2:
1444 *rows = 2;
1445 *cols = 4;
1446 break;
1447 case GL_FLOAT_MAT4x3:
1448 *rows = 3;
1449 *cols = 4;
1450 break;
1451 default:
1452 *rows = *cols = 0;
1453 }
1454}
1455
1456
1457static void
Brian Paulade50832008-05-14 16:09:46 -06001458set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001459 GLuint location, GLuint count,
1460 GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001461 GLboolean transpose, const GLfloat *values)
1462{
Brian Paulffbc66b2008-07-21 13:58:50 -06001463 GLuint mat, row, col;
1464 GLuint dst = location, src = 0;
1465 GLint nr, nc;
1466
1467 /* check that the number of rows, columns is correct */
1468 get_matrix_dims(program->Parameters->Parameters[location].DataType, &nr, &nc);
1469 if (rows != nr || cols != nc) {
1470 _mesa_error(ctx, GL_INVALID_OPERATION,
1471 "glUniformMatrix(matrix size mismatch");
1472 return;
1473 }
1474
Brian Paulade50832008-05-14 16:09:46 -06001475 /*
1476 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001477 * the rows. So, the loops below look a little funny.
1478 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001479 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001480
1481 /* loop over matrices */
1482 for (mat = 0; mat < count; mat++) {
1483
1484 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001485 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001486 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001487 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001488 if (transpose) {
1489 v[row] = values[src + row * cols + col];
1490 }
1491 else {
1492 v[row] = values[src + col * rows + row];
1493 }
Brian Paulade50832008-05-14 16:09:46 -06001494 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001495 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001496 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001497
1498 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001499 }
Brian34ae99d2006-12-18 08:28:54 -07001500}
1501
1502
1503/**
Brian5b01c5e2006-12-19 18:02:03 -07001504 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001505 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001506 */
Brian Paulfd59f192008-05-18 16:04:55 -06001507static void
Brian5b01c5e2006-12-19 18:02:03 -07001508_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1509 GLenum matrixType, GLint location, GLsizei count,
1510 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001511{
Brian3a8e2772006-12-20 17:19:16 -07001512 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001513
Brian3a8e2772006-12-20 17:19:16 -07001514 if (!shProg || !shProg->LinkStatus) {
1515 _mesa_error(ctx, GL_INVALID_OPERATION,
1516 "glUniformMatrix(program not linked)");
1517 return;
1518 }
Brian Paulade50832008-05-14 16:09:46 -06001519
Bruce Merry89b80322007-12-21 15:20:17 +02001520 if (location == -1)
1521 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001522
1523 if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
1524 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001525 return;
1526 }
Brian34ae99d2006-12-18 08:28:54 -07001527 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001528 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001529 return;
1530 }
1531
1532 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1533
Brian Paulade50832008-05-14 16:09:46 -06001534 if (shProg->VertexProgram) {
1535 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1536 if (loc >= 0) {
1537 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001538 loc, count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001539 }
Brian Paulade50832008-05-14 16:09:46 -06001540 }
1541
1542 if (shProg->FragmentProgram) {
1543 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1544 if (loc >= 0) {
1545 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001546 loc, count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001547 }
Brian34ae99d2006-12-18 08:28:54 -07001548 }
1549}
1550
1551
Brian Paulfd59f192008-05-18 16:04:55 -06001552static void
Brian5b01c5e2006-12-19 18:02:03 -07001553_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001554{
Brian65a18442006-12-19 18:46:56 -07001555 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001556
1557 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001558 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001559 return;
1560 }
1561
Brian Paulbc985b52008-07-21 14:16:07 -06001562 if (!shProg->LinkStatus) {
1563 shProg->Validated = GL_FALSE;
1564 return;
1565 }
1566
1567 /* From the GL spec, a program is invalid if any of these are true:
1568
Brian5b01c5e2006-12-19 18:02:03 -07001569 any two active samplers in the current program object are of
1570 different types, but refer to the same texture image unit,
1571
1572 any active sampler in the current program object refers to a texture
1573 image unit where fixed-function fragment processing accesses a
1574 texture target that does not match the sampler type, or
1575
1576 the sum of the number of active samplers in the program and the
1577 number of texture image units enabled for fixed-function fragment
1578 processing exceeds the combined limit on the total number of texture
1579 image units allowed.
1580 */
Brian Paulbc985b52008-07-21 14:16:07 -06001581
1582 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001583}
Brian Paulfd59f192008-05-18 16:04:55 -06001584
1585
1586/**
1587 * Plug in Mesa's GLSL functions into the device driver function table.
1588 */
1589void
1590_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1591{
1592 driver->AttachShader = _mesa_attach_shader;
1593 driver->BindAttribLocation = _mesa_bind_attrib_location;
1594 driver->CompileShader = _mesa_compile_shader;
1595 driver->CreateProgram = _mesa_create_program;
1596 driver->CreateShader = _mesa_create_shader;
1597 driver->DeleteProgram2 = _mesa_delete_program2;
1598 driver->DeleteShader = _mesa_delete_shader;
1599 driver->DetachShader = _mesa_detach_shader;
1600 driver->GetActiveAttrib = _mesa_get_active_attrib;
1601 driver->GetActiveUniform = _mesa_get_active_uniform;
1602 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1603 driver->GetAttribLocation = _mesa_get_attrib_location;
1604 driver->GetHandle = _mesa_get_handle;
1605 driver->GetProgramiv = _mesa_get_programiv;
1606 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1607 driver->GetShaderiv = _mesa_get_shaderiv;
1608 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1609 driver->GetShaderSource = _mesa_get_shader_source;
1610 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06001611 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06001612 driver->GetUniformLocation = _mesa_get_uniform_location;
1613 driver->IsProgram = _mesa_is_program;
1614 driver->IsShader = _mesa_is_shader;
1615 driver->LinkProgram = _mesa_link_program;
1616 driver->ShaderSource = _mesa_shader_source;
1617 driver->Uniform = _mesa_uniform;
1618 driver->UniformMatrix = _mesa_uniform_matrix;
1619 driver->UseProgram = _mesa_use_program;
1620 driver->ValidateProgram = _mesa_validate_program;
1621}