blob: 7fb4a8ac43947a9003e6483f734421351ea612a3 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian5b01c5e2006-12-19 18:02:03 -07003 * Version: 6.5.3
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"
Brian34ae99d2006-12-18 08:28:54 -070041#include "program.h"
42#include "prog_parameter.h"
Brian34ae99d2006-12-18 08:28:54 -070043#include "shader_api.h"
44
45#include "slang_compile.h"
46#include "slang_link.h"
47
48
49
Brianf2923612006-12-20 09:56:44 -070050/**
51 * Allocate a new gl_shader_program object, initialize it.
52 */
53struct gl_shader_program *
54_mesa_new_shader_program(GLcontext *ctx, GLuint name)
55{
56 struct gl_shader_program *shProg;
57 shProg = CALLOC_STRUCT(gl_shader_program);
58 if (shProg) {
59 shProg->Type = GL_SHADER_PROGRAM;
60 shProg->Name = name;
61 shProg->RefCount = 1;
62 }
63 return shProg;
64}
65
66
67void
68_mesa_free_shader_program_data(GLcontext *ctx,
69 struct gl_shader_program *shProg)
70{
71 assert(shProg->Type == GL_SHADER_PROGRAM);
72
73 if (shProg->VertexProgram) {
74 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
75 /* to prevent a double-free in the next call */
76 shProg->VertexProgram->Base.Parameters = NULL;
77 }
78 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
79 shProg->VertexProgram = NULL;
80 }
81
82 if (shProg->FragmentProgram) {
83 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
84 /* to prevent a double-free in the next call */
85 shProg->FragmentProgram->Base.Parameters = NULL;
86 }
87 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
88 shProg->FragmentProgram = NULL;
89 }
90
91
92 if (shProg->Uniforms) {
93 _mesa_free_parameter_list(shProg->Uniforms);
94 shProg->Uniforms = NULL;
95 }
96
97 if (shProg->Varying) {
98 _mesa_free_parameter_list(shProg->Varying);
99 shProg->Varying = NULL;
100 }
101}
102
103
104
105void
106_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
107{
108 _mesa_free_shader_program_data(ctx, shProg);
109 _mesa_free(shProg);
110}
111
112
113/**
114 * Lookup a GLSL program object.
115 */
116struct gl_shader_program *
117_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
118{
119 struct gl_shader_program *shProg;
120 if (name) {
121 shProg = (struct gl_shader_program *)
122 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
123 /* Note that both gl_shader and gl_shader_program objects are kept
124 * in the same hash table. Check the object's type to be sure it's
125 * what we're expecting.
126 */
127 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
128 return NULL;
129 }
130 return shProg;
131 }
132 return NULL;
133}
134
135
136/**
137 * Allocate a new gl_shader object, initialize it.
138 */
139struct gl_shader *
140_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
141{
142 struct gl_shader *shader;
143 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
144 shader = CALLOC_STRUCT(gl_shader);
145 if (shader) {
146 shader->Type = type;
147 shader->Name = name;
148 shader->RefCount = 1;
149 }
150 return shader;
151}
152
153
154void
155_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
156{
157 GLuint i;
158 if (sh->Source)
159 _mesa_free((void *) sh->Source);
160 if (sh->InfoLog)
161 _mesa_free(sh->InfoLog);
162 for (i = 0; i < sh->NumPrograms; i++) {
163 assert(sh->Programs[i]);
164 _mesa_delete_program(ctx, sh->Programs[i]);
165 }
166 if (sh->Programs)
167 _mesa_free(sh->Programs);
168 _mesa_free(sh);
169}
170
171
172/**
173 * Lookup a GLSL shader object.
174 */
175struct gl_shader *
176_mesa_lookup_shader(GLcontext *ctx, GLuint name)
177{
178 if (name) {
179 struct gl_shader *sh = (struct gl_shader *)
180 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
181 /* Note that both gl_shader and gl_shader_program objects are kept
182 * in the same hash table. Check the object's type to be sure it's
183 * what we're expecting.
184 */
185 if (sh && sh->Type == GL_SHADER_PROGRAM) {
186 assert(sh->Type == GL_VERTEX_SHADER ||
187 sh->Type == GL_FRAGMENT_SHADER);
188 return NULL;
189 }
190 return sh;
191 }
192 return NULL;
193}
194
195
196void
197_mesa_init_shader_state(GLcontext * ctx)
198{
199 ctx->Shader._FragmentShaderPresent = GL_FALSE;
200 ctx->Shader._VertexShaderPresent = GL_FALSE;
201}
202
203
204
Brian34ae99d2006-12-18 08:28:54 -0700205
Brian5b01c5e2006-12-19 18:02:03 -0700206
207/**
208 * Copy string from <src> to <dst>, up to maxLength characters, returning
209 * length of <dst> in <length>.
210 * \param src the strings source
211 * \param maxLength max chars to copy
212 * \param length returns number of chars copied
213 * \param dst the string destination
214 */
215static void
216copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
217{
218 GLsizei len;
219 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
220 dst[len] = src[len];
221 if (maxLength > 0)
222 dst[len] = 0;
223 if (length)
224 *length = len;
225}
226
227
228
229
230/**
231 * Called via ctx->Driver.AttachShader()
232 */
233void
234_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
235{
Brian65a18442006-12-19 18:46:56 -0700236 struct gl_shader_program *shProg
237 = _mesa_lookup_shader_program(ctx, program);
238 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
239 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700240 GLuint i;
241
Brian65a18442006-12-19 18:46:56 -0700242 if (!shProg || !sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700243 _mesa_error(ctx, GL_INVALID_OPERATION,
244 "glAttachShader(bad program or shader name)");
245 return;
246 }
247
248 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700249 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700250 /* already attached */
251 return;
Brian34ae99d2006-12-18 08:28:54 -0700252 }
253 }
Brian5b01c5e2006-12-19 18:02:03 -0700254
255 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700256 shProg->Shaders = (struct gl_shader **)
257 _mesa_realloc(shProg->Shaders,
258 n * sizeof(struct gl_shader *),
259 (n + 1) * sizeof(struct gl_shader *));
260 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700261 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
262 return;
263 }
264
265 /* append */
Brian65a18442006-12-19 18:46:56 -0700266 shProg->Shaders[n] = sh;
267 sh->RefCount++;
268 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700269}
270
271
272void
273_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
274 const GLchar *name)
275{
Brian65a18442006-12-19 18:46:56 -0700276 struct gl_shader_program *shProg
277 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700278
Brian65a18442006-12-19 18:46:56 -0700279 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700280 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocation(program)");
281 return;
282 }
283
Brian9e4bae92006-12-20 09:27:42 -0700284 if (!name)
285 return;
286
287 if (strncmp(name, "gl_", 3) == 0) {
288 _mesa_error(ctx, GL_INVALID_OPERATION,
289 "glBindAttribLocation(illegal name)");
290 return;
291 }
292
Brian5b01c5e2006-12-19 18:02:03 -0700293#if 0 /* XXXX */
294 if (name == NULL || index >= MAX_VERTEX_ATTRIBS)
295 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocationARB");
296 else if (IS_NAME_WITH_GL_PREFIX(name))
297 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocationARB");
298 else
299 (**pro).OverrideAttribBinding(pro, index, name);
300 RELEASE_PROGRAM(pro);
Brian34ae99d2006-12-18 08:28:54 -0700301#endif
302}
303
304
Brian5b01c5e2006-12-19 18:02:03 -0700305GLuint
306_mesa_create_shader(GLcontext *ctx, GLenum type)
307{
Brian65a18442006-12-19 18:46:56 -0700308 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700309 GLuint name;
310
311 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
312
313 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700314 case GL_FRAGMENT_SHADER:
315 case GL_VERTEX_SHADER:
316 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700317 break;
318 default:
319 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
320 return 0;
321 }
322
Brian65a18442006-12-19 18:46:56 -0700323 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700324
325 return name;
326}
327
328
329GLuint
330_mesa_create_program(GLcontext *ctx)
331{
332 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700333 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700334
Brian65a18442006-12-19 18:46:56 -0700335 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
336 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700337
Brian65a18442006-12-19 18:46:56 -0700338 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700339
340 return name;
341}
342
343
344void
345_mesa_delete_program2(GLcontext *ctx, GLuint name)
346{
Brian65a18442006-12-19 18:46:56 -0700347 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700348
Brian65a18442006-12-19 18:46:56 -0700349 shProg = _mesa_lookup_shader_program(ctx, name);
350 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700351 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteProgram(name)");
352 return;
353 }
354
Brian9e4bae92006-12-20 09:27:42 -0700355 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700356 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700357
358 shProg->DeletePending = GL_TRUE;
359
360 /* decrement refcount, delete if zero */
361 shProg->RefCount--;
362 if (shProg->RefCount <= 0) {
363 _mesa_free_shader_program(ctx, shProg);
364 }
Brian5b01c5e2006-12-19 18:02:03 -0700365}
366
367
368void
369_mesa_delete_shader(GLcontext *ctx, GLuint shader)
370{
Brian9e4bae92006-12-20 09:27:42 -0700371 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
372 if (!sh) {
373 return;
374 }
Brian5b01c5e2006-12-19 18:02:03 -0700375
Brian9e4bae92006-12-20 09:27:42 -0700376 sh->DeletePending = GL_TRUE;
377 sh->RefCount--;
378 if (sh->RefCount <= 0) {
379 _mesa_free_shader(ctx, sh);
380 }
Brian5b01c5e2006-12-19 18:02:03 -0700381}
382
383
384void
385_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
386{
Brian65a18442006-12-19 18:46:56 -0700387 struct gl_shader_program *shProg
388 = _mesa_lookup_shader_program(ctx, program);
389 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700390 GLuint i, j;
391
Brian65a18442006-12-19 18:46:56 -0700392 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700393 _mesa_error(ctx, GL_INVALID_OPERATION,
394 "glDetachShader(bad program or shader name)");
395 return;
396 }
397
398 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700399 if (shProg->Shaders[i]->Name == shader) {
400 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700401 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700402
403 shProg->Shaders[i]->RefCount--;
404
Brian5b01c5e2006-12-19 18:02:03 -0700405 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700406 newList = (struct gl_shader **)
407 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700408 if (!newList) {
409 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
410 return;
411 }
412 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700413 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700414 }
415 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700416 newList[j++] = shProg->Shaders[i];
417 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700418
419 /* XXX refcounting! */
420
Brian65a18442006-12-19 18:46:56 -0700421 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700422 return;
423 }
424 }
425
426 /* not found */
427 _mesa_error(ctx, GL_INVALID_OPERATION,
428 "glDetachShader(shader not found)");
429}
430
431
432void
433_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
434 GLsizei maxLength, GLsizei *length, GLint *size,
435 GLenum *type, GLchar *nameOut)
436{
437 static const GLenum vec_types[] = {
438 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
439 };
Brian65a18442006-12-19 18:46:56 -0700440 struct gl_shader_program *shProg
441 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700442 GLint sz;
443
Brian65a18442006-12-19 18:46:56 -0700444 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700445 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
446 return;
447 }
448
Brian65a18442006-12-19 18:46:56 -0700449 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700450 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
451 return;
452 }
453
454 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700455 shProg->Attributes->Parameters[index].Name);
456 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700457 if (size)
458 *size = sz;
459 if (type)
460 *type = vec_types[sz]; /* XXX this is a temporary hack */
461}
462
463
464/**
465 * Called via ctx->Driver.GetActiveUniform().
466 */
467void
468_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
469 GLsizei maxLength, GLsizei *length, GLint *size,
470 GLenum *type, GLchar *nameOut)
471{
472 static const GLenum vec_types[] = {
473 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
474 };
Brian65a18442006-12-19 18:46:56 -0700475 struct gl_shader_program *shProg
476 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700477 GLint sz;
478
Brian65a18442006-12-19 18:46:56 -0700479 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700480 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
481 return;
482 }
483
Brian65a18442006-12-19 18:46:56 -0700484 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700485 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
486 return;
487 }
488
489 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700490 shProg->Uniforms->Parameters[index].Name);
491 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700492 if (size)
493 *size = sz;
494 if (type)
495 *type = vec_types[sz]; /* XXX this is a temporary hack */
496}
497
498
499/**
500 * Called via ctx->Driver.GetAttachedShaders().
501 */
502void
503_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
504 GLsizei *count, GLuint *obj)
505{
Brian65a18442006-12-19 18:46:56 -0700506 struct gl_shader_program *shProg
507 = _mesa_lookup_shader_program(ctx, program);
508 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700509 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700510 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
511 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700512 }
513 if (count)
514 *count = i;
515 }
516 else {
517 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttachedShaders");
518 }
519}
520
521
522GLint
523_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
524 const GLchar *name)
525{
Brian65a18442006-12-19 18:46:56 -0700526 struct gl_shader_program *shProg
527 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700528
Brian65a18442006-12-19 18:46:56 -0700529 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700530 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttribLocation");
531 return -1;
532 }
533
Brian65a18442006-12-19 18:46:56 -0700534 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700535 _mesa_error(ctx, GL_INVALID_OPERATION,
536 "glGetAttribLocation(program not linked)");
537 return -1;
538 }
539
540 if (!name)
541 return -1;
542
Brian65a18442006-12-19 18:46:56 -0700543 if (shProg->Attributes) {
Brian5b01c5e2006-12-19 18:02:03 -0700544 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700545 for (i = 0; i < shProg->Attributes->NumParameters; i++) {
546 if (!strcmp(shProg->Attributes->Parameters[i].Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700547 return i;
548 }
549 }
550 }
551 return -1;
552}
553
554
555GLuint
556_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700557{
558#if 0
559 GET_CURRENT_CONTEXT(ctx);
560
561 switch (pname) {
562 case GL_PROGRAM_OBJECT_ARB:
563 {
Brian5b01c5e2006-12-19 18:02:03 -0700564 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700565
566 if (pro != NULL)
567 return (**pro)._container._generic.
568 GetName((struct gl2_generic_intf **) (pro));
569 }
570 break;
571 default:
572 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
573 }
574#endif
575 return 0;
576}
577
578
Brian5b01c5e2006-12-19 18:02:03 -0700579void
580_mesa_get_programiv(GLcontext *ctx, GLuint program,
581 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700582{
Brian65a18442006-12-19 18:46:56 -0700583 struct gl_shader_program *shProg
584 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700585
Brian65a18442006-12-19 18:46:56 -0700586 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700587 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700588 return;
589 }
590
Brian5b01c5e2006-12-19 18:02:03 -0700591 switch (pname) {
592 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700593 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700594 break;
595 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700596 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700597 break;
Brian5b01c5e2006-12-19 18:02:03 -0700598 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700599 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700600 break;
601 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700602 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700603 break;
604 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700605 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700606 break;
607 case GL_ACTIVE_ATTRIBUTES:
Brian65a18442006-12-19 18:46:56 -0700608 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700609 break;
610 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700611 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700612 break;
613 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700614 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700615 break;
616 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700617 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700618 break;
619 default:
Brian5b01c5e2006-12-19 18:02:03 -0700620 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
621 return;
Brian34ae99d2006-12-18 08:28:54 -0700622 }
Brian5b01c5e2006-12-19 18:02:03 -0700623}
Brian34ae99d2006-12-18 08:28:54 -0700624
Brian34ae99d2006-12-18 08:28:54 -0700625
Brian5b01c5e2006-12-19 18:02:03 -0700626void
627_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
628{
Brian65a18442006-12-19 18:46:56 -0700629 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700630
631 if (!shader) {
632 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
633 return;
634 }
Brian65a18442006-12-19 18:46:56 -0700635
Brian5b01c5e2006-12-19 18:02:03 -0700636 switch (pname) {
637 case GL_SHADER_TYPE:
638 *params = shader->Type;
639 break;
640 case GL_DELETE_STATUS:
641 *params = shader->DeletePending;
642 break;
643 case GL_COMPILE_STATUS:
644 *params = shader->CompileStatus;
645 break;
646 case GL_INFO_LOG_LENGTH:
647 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
648 break;
649 case GL_SHADER_SOURCE_LENGTH:
650 *params = shader->Source ? strlen((char *) shader->Source) : 0;
651 break;
652 default:
653 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
654 return;
655 }
656}
657
658
659void
660_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
661 GLsizei *length, GLchar *infoLog)
662{
Brian65a18442006-12-19 18:46:56 -0700663 struct gl_shader_program *shProg
664 = _mesa_lookup_shader_program(ctx, program);
665 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700666 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
667 return;
668 }
Brian65a18442006-12-19 18:46:56 -0700669 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700670}
671
672
673void
674_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
675 GLsizei *length, GLchar *infoLog)
676{
Brian65a18442006-12-19 18:46:56 -0700677 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
678 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700679 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
680 return;
681 }
Brian65a18442006-12-19 18:46:56 -0700682 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700683}
684
685
686/**
687 * Called via ctx->Driver.GetShaderSource().
688 */
689void
690_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
691 GLsizei *length, GLchar *sourceOut)
692{
Brian65a18442006-12-19 18:46:56 -0700693 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
694 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700695 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
696 return;
697 }
Brian65a18442006-12-19 18:46:56 -0700698 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700699}
700
701
702/**
703 * Called via ctx->Driver.GetUniformfv().
704 */
705void
706_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
707 GLfloat *params)
708{
Brian65a18442006-12-19 18:46:56 -0700709 struct gl_shader_program *shProg
710 = _mesa_lookup_shader_program(ctx, program);
711 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700712 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700713 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
714 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
715 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700716 }
717 }
718 else {
719 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
720 }
721 }
722 else {
723 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
724 }
725}
726
727
728/**
729 * Called via ctx->Driver.GetUniformLocation().
730 */
731GLint
732_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
733{
734 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700735 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian5b01c5e2006-12-19 18:02:03 -0700736 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700737 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700738 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700739 = shProg->Uniforms->Parameters + loc;
Brian5b01c5e2006-12-19 18:02:03 -0700740 if (u->Type == PROGRAM_UNIFORM && !strcmp(u->Name, name)) {
741 return loc;
742 }
743 }
744 }
745 return -1;
746
747}
748
749
750GLboolean
751_mesa_is_program(GLcontext *ctx, GLuint name)
752{
Brian65a18442006-12-19 18:46:56 -0700753 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
754 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700755}
756
757
758GLboolean
759_mesa_is_shader(GLcontext *ctx, GLuint name)
760{
Brian65a18442006-12-19 18:46:56 -0700761 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700762 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700763}
764
765
766
Brian5b01c5e2006-12-19 18:02:03 -0700767/**
768 * Called via ctx->Driver.ShaderSource()
769 */
770void
771_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700772{
Brian65a18442006-12-19 18:46:56 -0700773 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
774 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700775 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700776 return;
777 }
778
Brian34ae99d2006-12-18 08:28:54 -0700779 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700780 if (sh->Source) {
781 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700782 }
Brian65a18442006-12-19 18:46:56 -0700783 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700784 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700785}
786
787
Brian5b01c5e2006-12-19 18:02:03 -0700788/**
789 * Called via ctx->Driver.CompileShader()
790 */
791void
792_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700793{
Brian65a18442006-12-19 18:46:56 -0700794 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700795 slang_info_log info_log;
796 slang_code_object obj;
797 slang_unit_type type;
798
Brian65a18442006-12-19 18:46:56 -0700799 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700800 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
801 return;
802 }
803
804 slang_info_log_construct(&info_log);
805 _slang_code_object_ctr(&obj);
806
Brian65a18442006-12-19 18:46:56 -0700807 if (sh->Type == GL_VERTEX_SHADER) {
Brian34ae99d2006-12-18 08:28:54 -0700808 type = slang_unit_vertex_shader;
809 }
810 else {
Brian65a18442006-12-19 18:46:56 -0700811 assert(sh->Type == GL_FRAGMENT_SHADER);
Brian34ae99d2006-12-18 08:28:54 -0700812 type = slang_unit_fragment_shader;
813 }
814
Brian65a18442006-12-19 18:46:56 -0700815 if (_slang_compile(sh->Source, &obj, type, &info_log, sh)) {
816 sh->CompileStatus = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700817 }
818 else {
Brian65a18442006-12-19 18:46:56 -0700819 sh->CompileStatus = GL_FALSE;
820 /* XXX temporary */
Brian34ae99d2006-12-18 08:28:54 -0700821 _mesa_problem(ctx, "Program did not compile!");
822 }
823}
824
825
Brian5b01c5e2006-12-19 18:02:03 -0700826/**
827 * Called via ctx->Driver.LinkProgram()
828 */
829void
830_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700831{
Brian65a18442006-12-19 18:46:56 -0700832 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700833
Brian65a18442006-12-19 18:46:56 -0700834 shProg = _mesa_lookup_shader_program(ctx, program);
835 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700836 _mesa_error(ctx, GL_INVALID_OPERATION, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700837 return;
838 }
839
Brian65a18442006-12-19 18:46:56 -0700840 _slang_link2(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700841}
842
843
844/**
Brian5b01c5e2006-12-19 18:02:03 -0700845 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700846 */
Brian5b01c5e2006-12-19 18:02:03 -0700847void
848_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700849{
Brian9e4bae92006-12-20 09:27:42 -0700850 /* unbind old */
851 if (ctx->Shader.CurrentProgram) {
852 ctx->Shader.CurrentProgram->RefCount--;
853 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
854 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
855 }
856 ctx->Shader.CurrentProgram = NULL;
857 }
858
Brian5b01c5e2006-12-19 18:02:03 -0700859 /* XXXX need to handle reference counting here! */
860 if (program) {
Brian65a18442006-12-19 18:46:56 -0700861 struct gl_shader_program *shProg;
862 shProg = _mesa_lookup_shader_program(ctx, program);
863 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700864 _mesa_error(ctx, GL_INVALID_OPERATION,
865 "glUseProgramObjectARB(programObj)");
866 return;
867 }
Brian65a18442006-12-19 18:46:56 -0700868 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700869 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700870 }
871 else {
872 /* don't use a shader program */
873 ctx->Shader.CurrentProgram = NULL;
874 }
875}
Brian34ae99d2006-12-18 08:28:54 -0700876
Brian5b01c5e2006-12-19 18:02:03 -0700877
878/**
879 * Called via ctx->Driver.Uniform().
880 */
881void
882_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
883 const GLvoid *values, GLenum type)
884{
885 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700886 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
887 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
888 GLfloat *v = shProg->Uniforms->ParameterValues[location];
Brian34ae99d2006-12-18 08:28:54 -0700889 const GLfloat *fValues = (const GLfloat *) values; /* XXX */
890 GLint i;
891 if (type == GL_FLOAT_VEC4)
892 count *= 4;
893 else if (type == GL_FLOAT_VEC3)
894 count *= 3;
895 else
896 abort();
897
898 for (i = 0; i < count; i++)
899 v[i] = fValues[i];
900 return;
901 }
902 }
Brian5b01c5e2006-12-19 18:02:03 -0700903 else {
904 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
905 }
Brian34ae99d2006-12-18 08:28:54 -0700906}
907
908
909/**
Brian5b01c5e2006-12-19 18:02:03 -0700910 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700911 */
Brian5b01c5e2006-12-19 18:02:03 -0700912void
913_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
914 GLenum matrixType, GLint location, GLsizei count,
915 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700916{
Brian5b01c5e2006-12-19 18:02:03 -0700917 const char *caller = "glUniformMatrix";
Brian34ae99d2006-12-18 08:28:54 -0700918 const GLint matElements = rows * cols;
Brian34ae99d2006-12-18 08:28:54 -0700919
920 if (values == NULL) {
921 _mesa_error(ctx, GL_INVALID_VALUE, caller);
922 return;
923 }
924
925 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
926
927 if (transpose) {
928 GLfloat *trans, *pt;
929 const GLfloat *pv;
930 GLint i, j, k;
931
932 trans = (GLfloat *) _mesa_malloc(count * matElements * sizeof(GLfloat));
933 if (!trans) {
934 _mesa_error(ctx, GL_OUT_OF_MEMORY, caller);
935 return;
936 }
937
938 pt = trans;
939 pv = values;
940 for (i = 0; i < count; i++) {
941 /* transpose from pv matrix into pt matrix */
942 for (j = 0; j < cols; j++) {
943 for (k = 0; k < rows; k++) {
944 /* XXX verify this */
945 pt[j * rows + k] = pv[k * cols + j];
946 }
947 }
948 pt += matElements;
949 pv += matElements;
950 }
951
952#ifdef OLD
953 if (!(**pro).WriteUniform(pro, location, count, trans, matrixType))
954 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
955#endif
956 _mesa_free(trans);
957 }
958 else {
959#ifdef OLD
960 if (!(**pro).WriteUniform(pro, location, count, values, matrixType))
961 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
962#endif
963 }
964}
965
966
Brian5b01c5e2006-12-19 18:02:03 -0700967void
968_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700969{
Brian65a18442006-12-19 18:46:56 -0700970 struct gl_shader_program *shProg;
971 shProg = _mesa_lookup_shader_program(ctx, program);
972 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700973 _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700974 return;
975 }
Brian5b01c5e2006-12-19 18:02:03 -0700976 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -0700977 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700978
Brian5b01c5e2006-12-19 18:02:03 -0700979 /* From the GL spec:
980 any two active samplers in the current program object are of
981 different types, but refer to the same texture image unit,
982
983 any active sampler in the current program object refers to a texture
984 image unit where fixed-function fragment processing accesses a
985 texture target that does not match the sampler type, or
986
987 the sum of the number of active samplers in the program and the
988 number of texture image units enabled for fixed-function fragment
989 processing exceeds the combined limit on the total number of texture
990 image units allowed.
991 */
Brian34ae99d2006-12-18 08:28:54 -0700992}