blob: 7c5a20bbbeb9eac5db5599a84dc9d5543b6086ea [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian Paul27341a92008-09-16 16:28:36 -06003 * Version: 7.2
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian Paul8c51e002008-08-11 15:09:47 -06005 * Copyright (C) 2004-2008 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
Brian Paulbbd28712008-09-18 12:26:54 -060038#include "main/glheader.h"
39#include "main/context.h"
40#include "main/hash.h"
41#include "main/macros.h"
42#include "shader/program.h"
43#include "shader/prog_parameter.h"
44#include "shader/prog_print.h"
45#include "shader/prog_statevars.h"
46#include "shader/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
Brian Paul27341a92008-09-16 16:28:36 -0600495 if (shProg->VertexProgram) {
496 const struct gl_program_parameter_list *attribs =
497 shProg->VertexProgram->Base.Attributes;
498 if (attribs) {
499 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
500 if (i >= 0) {
501 return attribs->Parameters[i].StateIndexes[0];
502 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600503 }
504 }
505 return -1;
506}
507
508
Brian Paulfd59f192008-05-18 16:04:55 -0600509static void
Brian5b01c5e2006-12-19 18:02:03 -0700510_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
511 const GLchar *name)
512{
Brian Paul530df582008-07-03 16:21:11 -0600513 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700514 const GLint size = -1; /* unknown size */
Brian Paul27341a92008-09-16 16:28:36 -0600515 GLint i;
Brian Paul6f1abb92008-07-29 17:27:22 -0600516 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700517
Brian Paul530df582008-07-03 16:21:11 -0600518 shProg = _mesa_lookup_shader_program_err(ctx, program,
519 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700520 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700521 return;
522 }
523
Brian9e4bae92006-12-20 09:27:42 -0700524 if (!name)
525 return;
526
527 if (strncmp(name, "gl_", 3) == 0) {
528 _mesa_error(ctx, GL_INVALID_OPERATION,
529 "glBindAttribLocation(illegal name)");
530 return;
531 }
532
Brian Paul7acb7c12008-07-03 13:49:48 -0600533 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
534 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
535 return;
536 }
537
Brian3209c3e2007-01-09 17:49:24 -0700538 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600539 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700540 if (i < 0) {
541 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600542 return;
Brian3209c3e2007-01-09 17:49:24 -0700543 }
544
Brian Paul27341a92008-09-16 16:28:36 -0600545 /*
546 * Note that this attribute binding won't go into effect until
547 * glLinkProgram is called again.
548 */
Brian34ae99d2006-12-18 08:28:54 -0700549}
550
551
Brian Paulfd59f192008-05-18 16:04:55 -0600552static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700553_mesa_create_shader(GLcontext *ctx, GLenum type)
554{
Brian65a18442006-12-19 18:46:56 -0700555 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700556 GLuint name;
557
558 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
559
560 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700561 case GL_FRAGMENT_SHADER:
562 case GL_VERTEX_SHADER:
563 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700564 break;
565 default:
566 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
567 return 0;
568 }
569
Brian65a18442006-12-19 18:46:56 -0700570 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700571
572 return name;
573}
574
575
Brian Paulfd59f192008-05-18 16:04:55 -0600576static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700577_mesa_create_program(GLcontext *ctx)
578{
579 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700580 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700581
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800582 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700583 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700584
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800585 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700586
Brian3c008a02007-04-12 15:22:32 -0600587 assert(shProg->RefCount == 1);
588
Brian5b01c5e2006-12-19 18:02:03 -0700589 return name;
590}
591
592
Brian3c008a02007-04-12 15:22:32 -0600593/**
594 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
595 * DeleteProgramARB.
596 */
Brian Paulfd59f192008-05-18 16:04:55 -0600597static void
Brian5b01c5e2006-12-19 18:02:03 -0700598_mesa_delete_program2(GLcontext *ctx, GLuint name)
599{
Brian3c008a02007-04-12 15:22:32 -0600600 /*
601 * NOTE: deleting shaders/programs works a bit differently than
602 * texture objects (and buffer objects, etc). Shader/program
603 * handles/IDs exist in the hash table until the object is really
604 * deleted (refcount==0). With texture objects, the handle/ID is
605 * removed from the hash table in glDeleteTextures() while the tex
606 * object itself might linger until its refcount goes to zero.
607 */
Brian65a18442006-12-19 18:46:56 -0700608 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700609
Brian Paul530df582008-07-03 16:21:11 -0600610 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
611 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700612 return;
Brian5b01c5e2006-12-19 18:02:03 -0700613
Brian9e4bae92006-12-20 09:27:42 -0700614 shProg->DeletePending = GL_TRUE;
615
Brian3c008a02007-04-12 15:22:32 -0600616 /* effectively, decr shProg's refcount */
617 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700618}
619
620
Brian Paulfd59f192008-05-18 16:04:55 -0600621static void
Brian5b01c5e2006-12-19 18:02:03 -0700622_mesa_delete_shader(GLcontext *ctx, GLuint shader)
623{
Brian Paul530df582008-07-03 16:21:11 -0600624 struct gl_shader *sh;
625
626 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
627 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700628 return;
Brian5b01c5e2006-12-19 18:02:03 -0700629
Brian9e4bae92006-12-20 09:27:42 -0700630 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600631
632 /* effectively, decr sh's refcount */
633 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700634}
635
636
Brian Paulfd59f192008-05-18 16:04:55 -0600637static void
Brian5b01c5e2006-12-19 18:02:03 -0700638_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
639{
Brian Paul530df582008-07-03 16:21:11 -0600640 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100641 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700642 GLuint i, j;
643
Brian Paul530df582008-07-03 16:21:11 -0600644 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
645 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700646 return;
Brian5b01c5e2006-12-19 18:02:03 -0700647
Brian237b9852007-08-07 21:48:31 +0100648 n = shProg->NumShaders;
649
Brian5b01c5e2006-12-19 18:02:03 -0700650 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700651 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700652 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600653 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700654
Brian Paul530df582008-07-03 16:21:11 -0600655 /* release */
Brian3c008a02007-04-12 15:22:32 -0600656 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700657
Brian5b01c5e2006-12-19 18:02:03 -0700658 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700659 newList = (struct gl_shader **)
660 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700661 if (!newList) {
662 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
663 return;
664 }
665 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700666 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700667 }
668 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700669 newList[j++] = shProg->Shaders[i];
670 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700671
Brian65a18442006-12-19 18:46:56 -0700672 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600673 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600674
675#ifdef DEBUG
676 /* sanity check */
677 {
678 for (j = 0; j < shProg->NumShaders; j++) {
679 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
680 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
681 assert(shProg->Shaders[j]->RefCount > 0);
682 }
683 }
684#endif
685
Brian5b01c5e2006-12-19 18:02:03 -0700686 return;
687 }
688 }
689
690 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600691 {
692 GLenum err;
693 if (_mesa_is_shader(ctx, shader))
694 err = GL_INVALID_OPERATION;
695 else if (_mesa_is_program(ctx, shader))
696 err = GL_INVALID_OPERATION;
697 else
698 err = GL_INVALID_VALUE;
699 _mesa_error(ctx, err, "glDetachProgram(shader)");
700 return;
701 }
Brian5b01c5e2006-12-19 18:02:03 -0700702}
703
704
Brian Paulffbc66b2008-07-21 13:58:50 -0600705static GLint
706sizeof_glsl_type(GLenum type)
707{
708 switch (type) {
709 case GL_FLOAT:
710 case GL_INT:
711 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600712 case GL_SAMPLER_1D:
713 case GL_SAMPLER_2D:
714 case GL_SAMPLER_3D:
715 case GL_SAMPLER_CUBE:
716 case GL_SAMPLER_1D_SHADOW:
717 case GL_SAMPLER_2D_SHADOW:
718 case GL_SAMPLER_2D_RECT_ARB:
719 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
720 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
721 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
722 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600723 return 1;
724 case GL_FLOAT_VEC2:
725 case GL_INT_VEC2:
726 case GL_BOOL_VEC2:
727 return 2;
728 case GL_FLOAT_VEC3:
729 case GL_INT_VEC3:
730 case GL_BOOL_VEC3:
731 return 3;
732 case GL_FLOAT_VEC4:
733 case GL_INT_VEC4:
734 case GL_BOOL_VEC4:
735 return 4;
736 case GL_FLOAT_MAT2:
737 case GL_FLOAT_MAT2x3:
738 case GL_FLOAT_MAT2x4:
739 return 8; /* two float[4] vectors */
740 case GL_FLOAT_MAT3:
741 case GL_FLOAT_MAT3x2:
742 case GL_FLOAT_MAT3x4:
743 return 12; /* three float[4] vectors */
744 case GL_FLOAT_MAT4:
745 case GL_FLOAT_MAT4x2:
746 case GL_FLOAT_MAT4x3:
747 return 16; /* four float[4] vectors */
748 default:
749 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
750 return 1;
751 }
752}
753
754
Brian Paulfd59f192008-05-18 16:04:55 -0600755static void
Brian5b01c5e2006-12-19 18:02:03 -0700756_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
757 GLsizei maxLength, GLsizei *length, GLint *size,
758 GLenum *type, GLchar *nameOut)
759{
Brian Paul27341a92008-09-16 16:28:36 -0600760 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600761 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700762
Brian Paul530df582008-07-03 16:21:11 -0600763 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
764 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700765 return;
Brian5b01c5e2006-12-19 18:02:03 -0700766
Brian Paul27341a92008-09-16 16:28:36 -0600767 if (shProg->VertexProgram)
768 attribs = shProg->VertexProgram->Base.Attributes;
769
770 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600771 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700772 return;
773 }
774
Brian Paul27341a92008-09-16 16:28:36 -0600775 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
776
Brian5b01c5e2006-12-19 18:02:03 -0700777 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600778 *size = attribs->Parameters[index].Size
779 / sizeof_glsl_type(attribs->Parameters[index].DataType);
780
Brian Paulade50832008-05-14 16:09:46 -0600781 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600782 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700783}
784
785
786/**
787 * Called via ctx->Driver.GetActiveUniform().
788 */
Brian Paulfd59f192008-05-18 16:04:55 -0600789static void
Brian5b01c5e2006-12-19 18:02:03 -0700790_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
791 GLsizei maxLength, GLsizei *length, GLint *size,
792 GLenum *type, GLchar *nameOut)
793{
Brian Paul530df582008-07-03 16:21:11 -0600794 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600795 const struct gl_program *prog;
796 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700797
Brian Paul530df582008-07-03 16:21:11 -0600798 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
799 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700800 return;
Brian5b01c5e2006-12-19 18:02:03 -0700801
Brian Paulade50832008-05-14 16:09:46 -0600802 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700803 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
804 return;
805 }
806
Brian Paulade50832008-05-14 16:09:46 -0600807 progPos = shProg->Uniforms->Uniforms[index].VertPos;
808 if (progPos >= 0) {
809 prog = &shProg->VertexProgram->Base;
810 }
811 else {
812 progPos = shProg->Uniforms->Uniforms[index].FragPos;
813 if (progPos >= 0) {
814 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600815 }
816 }
817
Brian Paulade50832008-05-14 16:09:46 -0600818 if (!prog || progPos < 0)
819 return; /* should never happen */
820
821 if (nameOut)
822 copy_string(nameOut, maxLength, length,
823 prog->Parameters->Parameters[progPos].Name);
824 if (size)
Brian Paulffbc66b2008-07-21 13:58:50 -0600825 *size = prog->Parameters->Parameters[progPos].Size
826 / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType);
Brian Paulade50832008-05-14 16:09:46 -0600827 if (type)
828 *type = prog->Parameters->Parameters[progPos].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700829}
830
831
832/**
833 * Called via ctx->Driver.GetAttachedShaders().
834 */
Brian Paulfd59f192008-05-18 16:04:55 -0600835static void
Brian5b01c5e2006-12-19 18:02:03 -0700836_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
837 GLsizei *count, GLuint *obj)
838{
Brian Paul530df582008-07-03 16:21:11 -0600839 struct gl_shader_program *shProg =
840 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700841 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600842 GLuint i;
843 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700844 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700845 }
846 if (count)
847 *count = i;
848 }
Brian5b01c5e2006-12-19 18:02:03 -0700849}
850
851
Brian Paulfd59f192008-05-18 16:04:55 -0600852static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700853_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700854{
855#if 0
856 GET_CURRENT_CONTEXT(ctx);
857
858 switch (pname) {
859 case GL_PROGRAM_OBJECT_ARB:
860 {
Brian5b01c5e2006-12-19 18:02:03 -0700861 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700862
863 if (pro != NULL)
864 return (**pro)._container._generic.
865 GetName((struct gl2_generic_intf **) (pro));
866 }
867 break;
868 default:
869 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
870 }
871#endif
872 return 0;
873}
874
875
Brian Paulfd59f192008-05-18 16:04:55 -0600876static void
Brian5b01c5e2006-12-19 18:02:03 -0700877_mesa_get_programiv(GLcontext *ctx, GLuint program,
878 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700879{
Brian Paul27341a92008-09-16 16:28:36 -0600880 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -0700881 struct gl_shader_program *shProg
882 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700883
Brian65a18442006-12-19 18:46:56 -0700884 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700885 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700886 return;
887 }
888
Brian Paul27341a92008-09-16 16:28:36 -0600889 if (shProg->VertexProgram)
890 attribs = shProg->VertexProgram->Base.Attributes;
891 else
892 attribs = NULL;
893
Brian5b01c5e2006-12-19 18:02:03 -0700894 switch (pname) {
895 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700896 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700897 break;
898 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700899 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700900 break;
Brian5b01c5e2006-12-19 18:02:03 -0700901 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700902 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700903 break;
904 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600905 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700906 break;
907 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700908 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700909 break;
910 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -0600911 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700912 break;
913 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -0600914 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700915 break;
916 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600917 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700918 break;
919 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600920 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600921 if (*params > 0)
922 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700923 break;
924 default:
Brian5b01c5e2006-12-19 18:02:03 -0700925 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
926 return;
Brian34ae99d2006-12-18 08:28:54 -0700927 }
Brian5b01c5e2006-12-19 18:02:03 -0700928}
Brian34ae99d2006-12-18 08:28:54 -0700929
Brian34ae99d2006-12-18 08:28:54 -0700930
Brian Paulfd59f192008-05-18 16:04:55 -0600931static void
Brian5b01c5e2006-12-19 18:02:03 -0700932_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
933{
Brian Paul530df582008-07-03 16:21:11 -0600934 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700935
936 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700937 return;
938 }
Brian65a18442006-12-19 18:46:56 -0700939
Brian5b01c5e2006-12-19 18:02:03 -0700940 switch (pname) {
941 case GL_SHADER_TYPE:
942 *params = shader->Type;
943 break;
944 case GL_DELETE_STATUS:
945 *params = shader->DeletePending;
946 break;
947 case GL_COMPILE_STATUS:
948 *params = shader->CompileStatus;
949 break;
950 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600951 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700952 break;
953 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600954 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700955 break;
956 default:
957 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
958 return;
959 }
960}
961
962
Brian Paulfd59f192008-05-18 16:04:55 -0600963static void
Brian5b01c5e2006-12-19 18:02:03 -0700964_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
965 GLsizei *length, GLchar *infoLog)
966{
Brian65a18442006-12-19 18:46:56 -0700967 struct gl_shader_program *shProg
968 = _mesa_lookup_shader_program(ctx, program);
969 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700970 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
971 return;
972 }
Brian65a18442006-12-19 18:46:56 -0700973 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700974}
975
976
Brian Paulfd59f192008-05-18 16:04:55 -0600977static void
Brian5b01c5e2006-12-19 18:02:03 -0700978_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
979 GLsizei *length, GLchar *infoLog)
980{
Brian65a18442006-12-19 18:46:56 -0700981 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
982 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700983 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
984 return;
985 }
Brian65a18442006-12-19 18:46:56 -0700986 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700987}
988
989
990/**
991 * Called via ctx->Driver.GetShaderSource().
992 */
Brian Paulfd59f192008-05-18 16:04:55 -0600993static void
Brian5b01c5e2006-12-19 18:02:03 -0700994_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
995 GLsizei *length, GLchar *sourceOut)
996{
Brian Paul530df582008-07-03 16:21:11 -0600997 struct gl_shader *sh;
998 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -0700999 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001000 return;
1001 }
Brian65a18442006-12-19 18:46:56 -07001002 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001003}
1004
1005
Brian Paul2be54a82008-07-08 16:17:04 -06001006#define MAX_UNIFORM_ELEMENTS 16
1007
Brian5b01c5e2006-12-19 18:02:03 -07001008/**
Brian Paul2be54a82008-07-08 16:17:04 -06001009 * Helper for GetUniformfv(), GetUniformiv()
1010 * Returns number of elements written to 'params' output.
Brian5b01c5e2006-12-19 18:02:03 -07001011 */
Brian Paul2be54a82008-07-08 16:17:04 -06001012static GLuint
1013get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1014 GLfloat *params)
Brian5b01c5e2006-12-19 18:02:03 -07001015{
Brian65a18442006-12-19 18:46:56 -07001016 struct gl_shader_program *shProg
1017 = _mesa_lookup_shader_program(ctx, program);
1018 if (shProg) {
Brian Paul6cb12702008-06-28 16:48:31 -06001019 if (shProg->Uniforms &&
Brian Paul016701f2008-07-29 17:43:35 -06001020 location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) {
Brian Paul6cb12702008-06-28 16:48:31 -06001021 GLint progPos;
1022 GLuint i;
Brian Paulf2632212008-05-16 10:49:44 -06001023 const struct gl_program *prog = NULL;
Brian Paulade50832008-05-14 16:09:46 -06001024
1025 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1026 if (progPos >= 0) {
1027 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001028 }
Brian Paulade50832008-05-14 16:09:46 -06001029 else {
1030 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1031 if (progPos >= 0) {
1032 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001033 }
Brian Paulade50832008-05-14 16:09:46 -06001034 }
1035
Brian Paulf2632212008-05-16 10:49:44 -06001036 ASSERT(prog);
1037 if (prog) {
Brian Paul2be54a82008-07-08 16:17:04 -06001038 /* See uniformiv() below */
1039 assert(prog->Parameters->Parameters[progPos].Size <= MAX_UNIFORM_ELEMENTS);
1040
Brian Paulf2632212008-05-16 10:49:44 -06001041 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
1042 params[i] = prog->Parameters->ParameterValues[progPos][i];
1043 }
Brian Paul2be54a82008-07-08 16:17:04 -06001044 return prog->Parameters->Parameters[progPos].Size;
Brian Paulade50832008-05-14 16:09:46 -06001045 }
Brian5b01c5e2006-12-19 18:02:03 -07001046 }
1047 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001048 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
Brian5b01c5e2006-12-19 18:02:03 -07001049 }
1050 }
1051 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001052 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -07001053 }
Brian Paul2be54a82008-07-08 16:17:04 -06001054 return 0;
1055}
1056
1057
1058/**
1059 * Called via ctx->Driver.GetUniformfv().
1060 */
1061static void
1062_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1063 GLfloat *params)
1064{
1065 (void) get_uniformfv(ctx, program, location, params);
1066}
1067
1068
1069/**
1070 * Called via ctx->Driver.GetUniformiv().
1071 */
1072static void
1073_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1074 GLint *params)
1075{
1076 GLfloat fparams[MAX_UNIFORM_ELEMENTS];
1077 GLuint n = get_uniformfv(ctx, program, location, fparams);
1078 GLuint i;
1079 assert(n <= MAX_UNIFORM_ELEMENTS);
1080 for (i = 0; i < n; i++) {
1081 params[i] = (GLint) fparams[i];
1082 }
Brian5b01c5e2006-12-19 18:02:03 -07001083}
1084
1085
1086/**
1087 * Called via ctx->Driver.GetUniformLocation().
1088 */
Brian Paulfd59f192008-05-18 16:04:55 -06001089static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001090_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1091{
Brian Paul530df582008-07-03 16:21:11 -06001092 struct gl_shader_program *shProg =
1093 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1094
Brian Paulade50832008-05-14 16:09:46 -06001095 if (!shProg)
1096 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001097
Brian Paule06565b2008-07-04 09:58:55 -06001098 if (shProg->LinkStatus == GL_FALSE) {
1099 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1100 return -1;
1101 }
1102
Brian Paul530df582008-07-03 16:21:11 -06001103 /* XXX we should return -1 if the uniform was declared, but not
1104 * actually used.
1105 */
1106
Brian Paulade50832008-05-14 16:09:46 -06001107 return _mesa_lookup_uniform(shProg->Uniforms, name);
Brian5b01c5e2006-12-19 18:02:03 -07001108}
1109
1110
Brian34ae99d2006-12-18 08:28:54 -07001111
Brian5b01c5e2006-12-19 18:02:03 -07001112/**
1113 * Called via ctx->Driver.ShaderSource()
1114 */
Brian Paulfd59f192008-05-18 16:04:55 -06001115static void
Brian5b01c5e2006-12-19 18:02:03 -07001116_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001117{
Brian Paul530df582008-07-03 16:21:11 -06001118 struct gl_shader *sh;
1119
1120 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1121 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001122 return;
Brian34ae99d2006-12-18 08:28:54 -07001123
Brian34ae99d2006-12-18 08:28:54 -07001124 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001125 if (sh->Source) {
1126 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001127 }
Brian65a18442006-12-19 18:46:56 -07001128 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001129 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001130}
1131
1132
Brian5b01c5e2006-12-19 18:02:03 -07001133/**
1134 * Called via ctx->Driver.CompileShader()
1135 */
Brian Paulfd59f192008-05-18 16:04:55 -06001136static void
Brian5b01c5e2006-12-19 18:02:03 -07001137_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001138{
Brian Paul530df582008-07-03 16:21:11 -06001139 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001140
Brian Paul530df582008-07-03 16:21:11 -06001141 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1142 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001143 return;
Brian34ae99d2006-12-18 08:28:54 -07001144
Brian43975832007-01-04 08:21:09 -07001145 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001146}
1147
1148
Brian5b01c5e2006-12-19 18:02:03 -07001149/**
1150 * Called via ctx->Driver.LinkProgram()
1151 */
Brian Paulfd59f192008-05-18 16:04:55 -06001152static void
Brian5b01c5e2006-12-19 18:02:03 -07001153_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001154{
Brian65a18442006-12-19 18:46:56 -07001155 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001156
Brian Paul530df582008-07-03 16:21:11 -06001157 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1158 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001159 return;
Brian34ae99d2006-12-18 08:28:54 -07001160
Briandf43fb62008-05-06 23:08:51 -06001161 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1162
Brianc1771912007-02-16 09:56:19 -07001163 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001164}
1165
1166
1167/**
Brian5b01c5e2006-12-19 18:02:03 -07001168 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001169 */
Brian5b01c5e2006-12-19 18:02:03 -07001170void
1171_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001172{
Brian3c008a02007-04-12 15:22:32 -06001173 struct gl_shader_program *shProg;
1174
Brian00d63aa2007-02-03 11:35:02 -07001175 if (ctx->Shader.CurrentProgram &&
1176 ctx->Shader.CurrentProgram->Name == program) {
1177 /* no-op */
1178 return;
1179 }
1180
1181 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1182
Brian5b01c5e2006-12-19 18:02:03 -07001183 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001184 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001185 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001186 return;
1187 }
1188 if (!shProg->LinkStatus) {
1189 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
Brian5b01c5e2006-12-19 18:02:03 -07001190 return;
1191 }
Brian5b01c5e2006-12-19 18:02:03 -07001192 }
1193 else {
Brian3c008a02007-04-12 15:22:32 -06001194 shProg = NULL;
1195 }
1196
1197 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001198}
Brian34ae99d2006-12-18 08:28:54 -07001199
Brian5b01c5e2006-12-19 18:02:03 -07001200
Brian Paulade50832008-05-14 16:09:46 -06001201
1202/**
1203 * Update the vertex and fragment program's TexturesUsed arrays.
1204 */
1205static void
1206update_textures_used(struct gl_program *prog)
1207{
1208 GLuint s;
1209
1210 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1211
1212 for (s = 0; s < MAX_SAMPLERS; s++) {
1213 if (prog->SamplersUsed & (1 << s)) {
1214 GLuint u = prog->SamplerUnits[s];
1215 GLuint t = prog->SamplerTargets[s];
1216 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1217 prog->TexturesUsed[u] |= (1 << t);
1218 }
1219 }
1220}
1221
1222
Brianb36749d2008-07-21 20:42:05 -06001223static GLboolean
1224is_sampler_type(GLenum type)
1225{
1226 switch (type) {
1227 case GL_SAMPLER_1D:
1228 case GL_SAMPLER_2D:
1229 case GL_SAMPLER_3D:
1230 case GL_SAMPLER_CUBE:
1231 case GL_SAMPLER_1D_SHADOW:
1232 case GL_SAMPLER_2D_SHADOW:
1233 case GL_SAMPLER_2D_RECT_ARB:
1234 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1235 case GL_SAMPLER_1D_ARRAY_EXT:
1236 case GL_SAMPLER_2D_ARRAY_EXT:
1237 return GL_TRUE;
1238 default:
1239 return GL_FALSE;
1240 }
1241}
1242
1243
Brian Paulade50832008-05-14 16:09:46 -06001244/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001245 * Check if the type given by userType is allowed to set a uniform of the
1246 * target type. Generally, equivalence is required, but setting Boolean
1247 * uniforms can be done with glUniformiv or glUniformfv.
1248 */
1249static GLboolean
1250compatible_types(GLenum userType, GLenum targetType)
1251{
1252 if (userType == targetType)
1253 return GL_TRUE;
1254
1255 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1256 return GL_TRUE;
1257
1258 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1259 userType == GL_INT_VEC2))
1260 return GL_TRUE;
1261
1262 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1263 userType == GL_INT_VEC3))
1264 return GL_TRUE;
1265
1266 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1267 userType == GL_INT_VEC4))
1268 return GL_TRUE;
1269
Brianb36749d2008-07-21 20:42:05 -06001270 if (is_sampler_type(targetType) && userType == GL_INT)
1271 return GL_TRUE;
1272
Brian Paulffbc66b2008-07-21 13:58:50 -06001273 return GL_FALSE;
1274}
1275
1276
1277/**
Brian Paulade50832008-05-14 16:09:46 -06001278 * Set the value of a program's uniform variable.
1279 * \param program the program whose uniform to update
1280 * \param location the location/index of the uniform
1281 * \param type the datatype of the uniform
1282 * \param count the number of uniforms to set
1283 * \param elems number of elements per uniform
1284 * \param values the new values
1285 */
1286static void
1287set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
Brian Paul530df582008-07-03 16:21:11 -06001288 GLenum type, GLsizei count, GLint elems, const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001289{
Brian Paulffbc66b2008-07-21 13:58:50 -06001290 if (!compatible_types(type,
1291 program->Parameters->Parameters[location].DataType)) {
1292 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1293 return;
1294 }
1295
Brian Paulade50832008-05-14 16:09:46 -06001296 if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
1297 /* This controls which texture unit which is used by a sampler */
1298 GLuint texUnit, sampler;
1299
1300 /* data type for setting samplers must be int */
1301 if (type != GL_INT || count != 1) {
1302 _mesa_error(ctx, GL_INVALID_OPERATION,
1303 "glUniform(only glUniform1i can be used "
1304 "to set sampler uniforms)");
1305 return;
1306 }
1307
1308 sampler = (GLuint) program->Parameters->ParameterValues[location][0];
1309 texUnit = ((GLuint *) values)[0];
1310
1311 /* check that the sampler (tex unit index) is legal */
1312 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1313 _mesa_error(ctx, GL_INVALID_VALUE,
1314 "glUniform1(invalid sampler/tex unit index)");
1315 return;
1316 }
1317
1318 /* This maps a sampler to a texture unit: */
1319 program->SamplerUnits[sampler] = texUnit;
1320 update_textures_used(program);
1321
1322 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1323 }
1324 else {
1325 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001326 GLsizei k, i;
Brian Paulade50832008-05-14 16:09:46 -06001327
Brian Paul016701f2008-07-29 17:43:35 -06001328 if (count * elems > (GLint) program->Parameters->Parameters[location].Size) {
Brian Paulade50832008-05-14 16:09:46 -06001329 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1330 return;
1331 }
1332
1333 for (k = 0; k < count; k++) {
1334 GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
1335 if (type == GL_INT ||
1336 type == GL_INT_VEC2 ||
1337 type == GL_INT_VEC3 ||
1338 type == GL_INT_VEC4) {
1339 const GLint *iValues = ((const GLint *) values) + k * elems;
1340 for (i = 0; i < elems; i++) {
1341 uniformVal[i] = (GLfloat) iValues[i];
1342 }
1343 }
1344 else {
1345 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1346 for (i = 0; i < elems; i++) {
1347 uniformVal[i] = fValues[i];
1348 }
1349 }
1350 }
1351 }
1352}
1353
1354
Brian5b01c5e2006-12-19 18:02:03 -07001355/**
1356 * Called via ctx->Driver.Uniform().
1357 */
Brian Paulfd59f192008-05-18 16:04:55 -06001358static void
Brian5b01c5e2006-12-19 18:02:03 -07001359_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1360 const GLvoid *values, GLenum type)
1361{
Brian3a8e2772006-12-20 17:19:16 -07001362 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001363 GLint elems;
Brian3a8e2772006-12-20 17:19:16 -07001364
1365 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001366 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001367 return;
1368 }
1369
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001370 if (location == -1)
1371 return; /* The standard specifies this as a no-op */
1372
Brian Paulade50832008-05-14 16:09:46 -06001373 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1374 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001375 return;
1376 }
1377
Brian52363952007-03-13 16:50:24 -06001378 if (count < 0) {
1379 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1380 return;
1381 }
1382
Brian98650bd2007-03-13 16:32:48 -06001383 switch (type) {
1384 case GL_FLOAT:
1385 case GL_INT:
1386 elems = 1;
1387 break;
1388 case GL_FLOAT_VEC2:
1389 case GL_INT_VEC2:
1390 elems = 2;
1391 break;
1392 case GL_FLOAT_VEC3:
1393 case GL_INT_VEC3:
1394 elems = 3;
1395 break;
1396 case GL_FLOAT_VEC4:
1397 case GL_INT_VEC4:
1398 elems = 4;
1399 break;
1400 default:
1401 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1402 return;
Brian89dc4852007-01-04 14:35:44 -07001403 }
Brian98650bd2007-03-13 16:32:48 -06001404
Brian Paulade50832008-05-14 16:09:46 -06001405 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001406
Brian Paulade50832008-05-14 16:09:46 -06001407 /* A uniform var may be used by both a vertex shader and a fragment
1408 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001409 */
Brian Paulade50832008-05-14 16:09:46 -06001410 if (shProg->VertexProgram) {
1411 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1412 if (loc >= 0) {
1413 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1414 loc, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001415 }
Brian5b01c5e2006-12-19 18:02:03 -07001416 }
Brian5cf73262007-01-05 16:02:45 -07001417
Brian Paulade50832008-05-14 16:09:46 -06001418 if (shProg->FragmentProgram) {
1419 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1420 if (loc >= 0) {
1421 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1422 loc, type, count, elems, values);
1423 }
1424 }
1425}
1426
1427
1428static void
Brian Paulffbc66b2008-07-21 13:58:50 -06001429get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1430{
1431 switch (type) {
1432 case GL_FLOAT_MAT2:
1433 *rows = *cols = 2;
1434 break;
1435 case GL_FLOAT_MAT2x3:
1436 *rows = 3;
1437 *cols = 2;
1438 break;
1439 case GL_FLOAT_MAT2x4:
1440 *rows = 4;
1441 *cols = 2;
1442 break;
1443 case GL_FLOAT_MAT3:
1444 *rows = 3;
1445 *cols = 3;
1446 break;
1447 case GL_FLOAT_MAT3x2:
1448 *rows = 2;
1449 *cols = 3;
1450 break;
1451 case GL_FLOAT_MAT3x4:
1452 *rows = 4;
1453 *cols = 3;
1454 break;
1455 case GL_FLOAT_MAT4:
1456 *rows = 4;
1457 *cols = 4;
1458 break;
1459 case GL_FLOAT_MAT4x2:
1460 *rows = 2;
1461 *cols = 4;
1462 break;
1463 case GL_FLOAT_MAT4x3:
1464 *rows = 3;
1465 *cols = 4;
1466 break;
1467 default:
1468 *rows = *cols = 0;
1469 }
1470}
1471
1472
1473static void
Brian Paulade50832008-05-14 16:09:46 -06001474set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001475 GLuint location, GLuint count,
1476 GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001477 GLboolean transpose, const GLfloat *values)
1478{
Brian Paulffbc66b2008-07-21 13:58:50 -06001479 GLuint mat, row, col;
1480 GLuint dst = location, src = 0;
1481 GLint nr, nc;
1482
1483 /* check that the number of rows, columns is correct */
1484 get_matrix_dims(program->Parameters->Parameters[location].DataType, &nr, &nc);
1485 if (rows != nr || cols != nc) {
1486 _mesa_error(ctx, GL_INVALID_OPERATION,
1487 "glUniformMatrix(matrix size mismatch");
1488 return;
1489 }
1490
Brian Paulade50832008-05-14 16:09:46 -06001491 /*
1492 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001493 * the rows. So, the loops below look a little funny.
1494 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001495 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001496
1497 /* loop over matrices */
1498 for (mat = 0; mat < count; mat++) {
1499
1500 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001501 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001502 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001503 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001504 if (transpose) {
1505 v[row] = values[src + row * cols + col];
1506 }
1507 else {
1508 v[row] = values[src + col * rows + row];
1509 }
Brian Paulade50832008-05-14 16:09:46 -06001510 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001511 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001512 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001513
1514 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001515 }
Brian34ae99d2006-12-18 08:28:54 -07001516}
1517
1518
1519/**
Brian5b01c5e2006-12-19 18:02:03 -07001520 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001521 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001522 */
Brian Paulfd59f192008-05-18 16:04:55 -06001523static void
Brian5b01c5e2006-12-19 18:02:03 -07001524_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1525 GLenum matrixType, GLint location, GLsizei count,
1526 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001527{
Brian3a8e2772006-12-20 17:19:16 -07001528 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001529
Brian3a8e2772006-12-20 17:19:16 -07001530 if (!shProg || !shProg->LinkStatus) {
1531 _mesa_error(ctx, GL_INVALID_OPERATION,
1532 "glUniformMatrix(program not linked)");
1533 return;
1534 }
Brian Paulade50832008-05-14 16:09:46 -06001535
Bruce Merry89b80322007-12-21 15:20:17 +02001536 if (location == -1)
1537 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001538
Brian Paul016701f2008-07-29 17:43:35 -06001539 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001540 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001541 return;
1542 }
Brian34ae99d2006-12-18 08:28:54 -07001543 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001544 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001545 return;
1546 }
1547
1548 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1549
Brian Paulade50832008-05-14 16:09:46 -06001550 if (shProg->VertexProgram) {
1551 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1552 if (loc >= 0) {
1553 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001554 loc, count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001555 }
Brian Paulade50832008-05-14 16:09:46 -06001556 }
1557
1558 if (shProg->FragmentProgram) {
1559 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1560 if (loc >= 0) {
1561 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001562 loc, count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001563 }
Brian34ae99d2006-12-18 08:28:54 -07001564 }
1565}
1566
1567
Brian Paulfd59f192008-05-18 16:04:55 -06001568static void
Brian5b01c5e2006-12-19 18:02:03 -07001569_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001570{
Brian65a18442006-12-19 18:46:56 -07001571 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001572
1573 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001574 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001575 return;
1576 }
1577
Brian Paulbc985b52008-07-21 14:16:07 -06001578 if (!shProg->LinkStatus) {
1579 shProg->Validated = GL_FALSE;
1580 return;
1581 }
1582
1583 /* From the GL spec, a program is invalid if any of these are true:
1584
Brian5b01c5e2006-12-19 18:02:03 -07001585 any two active samplers in the current program object are of
1586 different types, but refer to the same texture image unit,
1587
1588 any active sampler in the current program object refers to a texture
1589 image unit where fixed-function fragment processing accesses a
1590 texture target that does not match the sampler type, or
1591
1592 the sum of the number of active samplers in the program and the
1593 number of texture image units enabled for fixed-function fragment
1594 processing exceeds the combined limit on the total number of texture
1595 image units allowed.
1596 */
Brian Paulbc985b52008-07-21 14:16:07 -06001597
1598 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001599}
Brian Paulfd59f192008-05-18 16:04:55 -06001600
1601
1602/**
1603 * Plug in Mesa's GLSL functions into the device driver function table.
1604 */
1605void
1606_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1607{
1608 driver->AttachShader = _mesa_attach_shader;
1609 driver->BindAttribLocation = _mesa_bind_attrib_location;
1610 driver->CompileShader = _mesa_compile_shader;
1611 driver->CreateProgram = _mesa_create_program;
1612 driver->CreateShader = _mesa_create_shader;
1613 driver->DeleteProgram2 = _mesa_delete_program2;
1614 driver->DeleteShader = _mesa_delete_shader;
1615 driver->DetachShader = _mesa_detach_shader;
1616 driver->GetActiveAttrib = _mesa_get_active_attrib;
1617 driver->GetActiveUniform = _mesa_get_active_uniform;
1618 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1619 driver->GetAttribLocation = _mesa_get_attrib_location;
1620 driver->GetHandle = _mesa_get_handle;
1621 driver->GetProgramiv = _mesa_get_programiv;
1622 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1623 driver->GetShaderiv = _mesa_get_shaderiv;
1624 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1625 driver->GetShaderSource = _mesa_get_shader_source;
1626 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06001627 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06001628 driver->GetUniformLocation = _mesa_get_uniform_location;
1629 driver->IsProgram = _mesa_is_program;
1630 driver->IsShader = _mesa_is_shader;
1631 driver->LinkProgram = _mesa_link_program;
1632 driver->ShaderSource = _mesa_shader_source;
1633 driver->Uniform = _mesa_uniform;
1634 driver->UniformMatrix = _mesa_uniform_matrix;
1635 driver->UseProgram = _mesa_use_program;
1636 driver->ValidateProgram = _mesa_validate_program;
1637}