blob: d6dacdd6793d30df5f50af6a37e4b20c8ee98483 [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) {
Brian43975832007-01-04 08:21:09 -0700243 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700244 "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) {
Brian43975832007-01-04 08:21:09 -0700280 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700281 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) {
Brian43975832007-01-04 08:21:09 -0700351 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700352 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) {
Brian43975832007-01-04 08:21:09 -0700393 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700394 "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 */
Brian43975832007-01-04 08:21:09 -0700427 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700428 "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) {
Brian43975832007-01-04 08:21:09 -0700445 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700446 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) {
Brian43975832007-01-04 08:21:09 -0700480 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700481 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 {
Brian43975832007-01-04 08:21:09 -0700517 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700518 }
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) {
Brian43975832007-01-04 08:21:09 -0700530 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700531 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 {
Brian43975832007-01-04 08:21:09 -0700723 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700724 }
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;
Brian29053852006-12-21 11:21:26 -0700740 /* XXX this is a temporary simplification / short-cut.
741 * We need to handle things like "e.c[0].b" as seen in the
742 * GLSL orange book, page 189.
743 */
Brian5b01c5e2006-12-19 18:02:03 -0700744 if (u->Type == PROGRAM_UNIFORM && !strcmp(u->Name, name)) {
745 return loc;
746 }
747 }
748 }
749 return -1;
750
751}
752
753
754GLboolean
755_mesa_is_program(GLcontext *ctx, GLuint name)
756{
Brian65a18442006-12-19 18:46:56 -0700757 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
758 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700759}
760
761
762GLboolean
763_mesa_is_shader(GLcontext *ctx, GLuint name)
764{
Brian65a18442006-12-19 18:46:56 -0700765 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700766 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700767}
768
769
770
Brian5b01c5e2006-12-19 18:02:03 -0700771/**
772 * Called via ctx->Driver.ShaderSource()
773 */
774void
775_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700776{
Brian65a18442006-12-19 18:46:56 -0700777 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
778 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700779 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700780 return;
781 }
782
Brian34ae99d2006-12-18 08:28:54 -0700783 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700784 if (sh->Source) {
785 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700786 }
Brian65a18442006-12-19 18:46:56 -0700787 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700788 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700789}
790
791
Brian5b01c5e2006-12-19 18:02:03 -0700792/**
793 * Called via ctx->Driver.CompileShader()
794 */
795void
796_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700797{
Brian65a18442006-12-19 18:46:56 -0700798 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700799
Brian65a18442006-12-19 18:46:56 -0700800 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700801 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
802 return;
803 }
804
Brian43975832007-01-04 08:21:09 -0700805 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700806}
807
808
Brian5b01c5e2006-12-19 18:02:03 -0700809/**
810 * Called via ctx->Driver.LinkProgram()
811 */
812void
813_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700814{
Brian65a18442006-12-19 18:46:56 -0700815 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700816
Brian65a18442006-12-19 18:46:56 -0700817 shProg = _mesa_lookup_shader_program(ctx, program);
818 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700819 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700820 return;
821 }
822
Brian65a18442006-12-19 18:46:56 -0700823 _slang_link2(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700824}
825
826
827/**
Brian5b01c5e2006-12-19 18:02:03 -0700828 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700829 */
Brian5b01c5e2006-12-19 18:02:03 -0700830void
831_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700832{
Brian9e4bae92006-12-20 09:27:42 -0700833 /* unbind old */
834 if (ctx->Shader.CurrentProgram) {
835 ctx->Shader.CurrentProgram->RefCount--;
836 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
837 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
838 }
839 ctx->Shader.CurrentProgram = NULL;
840 }
841
Brian5b01c5e2006-12-19 18:02:03 -0700842 /* XXXX need to handle reference counting here! */
843 if (program) {
Brian65a18442006-12-19 18:46:56 -0700844 struct gl_shader_program *shProg;
845 shProg = _mesa_lookup_shader_program(ctx, program);
846 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700847 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700848 "glUseProgramObjectARB(programObj)");
849 return;
850 }
Brian65a18442006-12-19 18:46:56 -0700851 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700852 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700853 }
854 else {
855 /* don't use a shader program */
856 ctx->Shader.CurrentProgram = NULL;
857 }
858}
Brian34ae99d2006-12-18 08:28:54 -0700859
Brian5b01c5e2006-12-19 18:02:03 -0700860
861/**
862 * Called via ctx->Driver.Uniform().
863 */
864void
865_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
866 const GLvoid *values, GLenum type)
867{
Brian3a8e2772006-12-20 17:19:16 -0700868 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian89dc4852007-01-04 14:35:44 -0700869 GLfloat *uniformVal;
Brian3a8e2772006-12-20 17:19:16 -0700870
871 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700872 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700873 return;
874 }
875
876 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
877 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
878 return;
879 }
880
881 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
882
Brian89dc4852007-01-04 14:35:44 -0700883 uniformVal = shProg->Uniforms->ParameterValues[location];
Brian3a8e2772006-12-20 17:19:16 -0700884
Brian89dc4852007-01-04 14:35:44 -0700885 if (type == GL_INT ||
886 type == GL_INT_VEC2 ||
887 type == GL_INT_VEC3 ||
888 type == GL_INT_VEC4) {
889 const GLint *iValues = (const GLint *) values;
890 switch (type) {
891 case GL_INT_VEC4:
892 uniformVal[3] = (GLfloat) iValues[3];
893 /* fall-through */
894 case GL_INT_VEC3:
895 uniformVal[2] = (GLfloat) iValues[2];
896 /* fall-through */
897 case GL_INT_VEC2:
898 uniformVal[1] = (GLfloat) iValues[1];
899 /* fall-through */
900 case GL_INT:
901 uniformVal[0] = (GLfloat) iValues[0];
902 break;
903 default:
904 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
905 return;
906 }
907 }
908 else {
909 const GLfloat *fValues = (const GLfloat *) values; /* XXX */
910 switch (type) {
911 case GL_FLOAT_VEC4:
912 uniformVal[3] = fValues[3];
913 /* fall-through */
914 case GL_FLOAT_VEC3:
915 uniformVal[2] = fValues[2];
916 /* fall-through */
917 case GL_FLOAT_VEC2:
918 uniformVal[1] = fValues[1];
919 /* fall-through */
920 case GL_FLOAT:
921 uniformVal[0] = fValues[0];
922 break;
923 default:
924 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
925 return;
926 }
Brian5b01c5e2006-12-19 18:02:03 -0700927 }
Brian34ae99d2006-12-18 08:28:54 -0700928}
929
930
931/**
Brian5b01c5e2006-12-19 18:02:03 -0700932 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700933 */
Brian5b01c5e2006-12-19 18:02:03 -0700934void
935_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
936 GLenum matrixType, GLint location, GLsizei count,
937 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700938{
Brian3a8e2772006-12-20 17:19:16 -0700939 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
940 if (!shProg || !shProg->LinkStatus) {
941 _mesa_error(ctx, GL_INVALID_OPERATION,
942 "glUniformMatrix(program not linked)");
943 return;
944 }
945 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
946 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
947 return;
948 }
Brian34ae99d2006-12-18 08:28:54 -0700949 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -0700950 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -0700951 return;
952 }
953
954 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
955
Brian3a8e2772006-12-20 17:19:16 -0700956 /*
957 * Note: the _columns_ of a matrix are stored in program registers, not
958 * the rows.
959 */
960 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -0700961 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -0700962 GLuint row, col;
963 for (col = 0; col < cols; col++) {
964 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
965 for (row = 0; row < rows; row++) {
966 v[row] = values[col * rows + row];
Brian34ae99d2006-12-18 08:28:54 -0700967 }
Brian34ae99d2006-12-18 08:28:54 -0700968 }
Brian34ae99d2006-12-18 08:28:54 -0700969 }
970 else {
Brian3a8e2772006-12-20 17:19:16 -0700971 GLuint row, col;
972 for (col = 0; col < cols; col++) {
973 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
974 for (row = 0; row < rows; row++) {
975 v[row] = values[row * cols + col];
976 }
977 }
Brian34ae99d2006-12-18 08:28:54 -0700978 }
979}
980
981
Brian5b01c5e2006-12-19 18:02:03 -0700982void
983_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700984{
Brian65a18442006-12-19 18:46:56 -0700985 struct gl_shader_program *shProg;
986 shProg = _mesa_lookup_shader_program(ctx, program);
987 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700988 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700989 return;
990 }
Brian5b01c5e2006-12-19 18:02:03 -0700991 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -0700992 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700993
Brian5b01c5e2006-12-19 18:02:03 -0700994 /* From the GL spec:
995 any two active samplers in the current program object are of
996 different types, but refer to the same texture image unit,
997
998 any active sampler in the current program object refers to a texture
999 image unit where fixed-function fragment processing accesses a
1000 texture target that does not match the sampler type, or
1001
1002 the sum of the number of active samplers in the program and the
1003 number of texture image units enabled for fixed-function fragment
1004 processing exceeds the combined limit on the total number of texture
1005 image units allowed.
1006 */
Brian34ae99d2006-12-18 08:28:54 -07001007}