blob: 2d1056e667426101eff446e6ee6ced84d08cdf58 [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
Brian34ae99d2006-12-18 08:28:54 -070050
Brian5b01c5e2006-12-19 18:02:03 -070051
52/**
53 * Copy string from <src> to <dst>, up to maxLength characters, returning
54 * length of <dst> in <length>.
55 * \param src the strings source
56 * \param maxLength max chars to copy
57 * \param length returns number of chars copied
58 * \param dst the string destination
59 */
60static void
61copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
62{
63 GLsizei len;
64 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
65 dst[len] = src[len];
66 if (maxLength > 0)
67 dst[len] = 0;
68 if (length)
69 *length = len;
70}
71
72
73
74
75/**
76 * Called via ctx->Driver.AttachShader()
77 */
78void
79_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
80{
Brian65a18442006-12-19 18:46:56 -070081 struct gl_shader_program *shProg
82 = _mesa_lookup_shader_program(ctx, program);
83 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
84 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -070085 GLuint i;
86
Brian65a18442006-12-19 18:46:56 -070087 if (!shProg || !sh) {
Brian5b01c5e2006-12-19 18:02:03 -070088 _mesa_error(ctx, GL_INVALID_OPERATION,
89 "glAttachShader(bad program or shader name)");
90 return;
91 }
92
93 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -070094 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -070095 /* already attached */
96 return;
Brian34ae99d2006-12-18 08:28:54 -070097 }
98 }
Brian5b01c5e2006-12-19 18:02:03 -070099
100 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700101 shProg->Shaders = (struct gl_shader **)
102 _mesa_realloc(shProg->Shaders,
103 n * sizeof(struct gl_shader *),
104 (n + 1) * sizeof(struct gl_shader *));
105 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700106 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
107 return;
108 }
109
110 /* append */
Brian65a18442006-12-19 18:46:56 -0700111 shProg->Shaders[n] = sh;
112 sh->RefCount++;
113 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700114}
115
116
117void
118_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
119 const GLchar *name)
120{
Brian65a18442006-12-19 18:46:56 -0700121 struct gl_shader_program *shProg
122 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700123
Brian65a18442006-12-19 18:46:56 -0700124 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700125 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocation(program)");
126 return;
127 }
128
Brian9e4bae92006-12-20 09:27:42 -0700129 if (!name)
130 return;
131
132 if (strncmp(name, "gl_", 3) == 0) {
133 _mesa_error(ctx, GL_INVALID_OPERATION,
134 "glBindAttribLocation(illegal name)");
135 return;
136 }
137
Brian5b01c5e2006-12-19 18:02:03 -0700138#if 0 /* XXXX */
139 if (name == NULL || index >= MAX_VERTEX_ATTRIBS)
140 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocationARB");
141 else if (IS_NAME_WITH_GL_PREFIX(name))
142 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocationARB");
143 else
144 (**pro).OverrideAttribBinding(pro, index, name);
145 RELEASE_PROGRAM(pro);
Brian34ae99d2006-12-18 08:28:54 -0700146#endif
147}
148
149
Brian5b01c5e2006-12-19 18:02:03 -0700150GLuint
151_mesa_create_shader(GLcontext *ctx, GLenum type)
152{
Brian65a18442006-12-19 18:46:56 -0700153 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700154 GLuint name;
155
156 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
157
158 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700159 case GL_FRAGMENT_SHADER:
160 case GL_VERTEX_SHADER:
161 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700162 break;
163 default:
164 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
165 return 0;
166 }
167
Brian65a18442006-12-19 18:46:56 -0700168 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700169
170 return name;
171}
172
173
174GLuint
175_mesa_create_program(GLcontext *ctx)
176{
177 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700178 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700179
Brian65a18442006-12-19 18:46:56 -0700180 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
181 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700182
Brian65a18442006-12-19 18:46:56 -0700183 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700184
185 return name;
186}
187
188
189void
190_mesa_delete_program2(GLcontext *ctx, GLuint name)
191{
Brian65a18442006-12-19 18:46:56 -0700192 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700193
Brian65a18442006-12-19 18:46:56 -0700194 shProg = _mesa_lookup_shader_program(ctx, name);
195 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700196 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteProgram(name)");
197 return;
198 }
199
Brian9e4bae92006-12-20 09:27:42 -0700200 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700201 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700202
203 shProg->DeletePending = GL_TRUE;
204
205 /* decrement refcount, delete if zero */
206 shProg->RefCount--;
207 if (shProg->RefCount <= 0) {
208 _mesa_free_shader_program(ctx, shProg);
209 }
Brian5b01c5e2006-12-19 18:02:03 -0700210}
211
212
213void
214_mesa_delete_shader(GLcontext *ctx, GLuint shader)
215{
Brian9e4bae92006-12-20 09:27:42 -0700216 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
217 if (!sh) {
218 return;
219 }
Brian5b01c5e2006-12-19 18:02:03 -0700220
Brian9e4bae92006-12-20 09:27:42 -0700221 sh->DeletePending = GL_TRUE;
222 sh->RefCount--;
223 if (sh->RefCount <= 0) {
224 _mesa_free_shader(ctx, sh);
225 }
Brian5b01c5e2006-12-19 18:02:03 -0700226}
227
228
229void
230_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
231{
Brian65a18442006-12-19 18:46:56 -0700232 struct gl_shader_program *shProg
233 = _mesa_lookup_shader_program(ctx, program);
234 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700235 GLuint i, j;
236
Brian65a18442006-12-19 18:46:56 -0700237 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700238 _mesa_error(ctx, GL_INVALID_OPERATION,
239 "glDetachShader(bad program or shader name)");
240 return;
241 }
242
243 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700244 if (shProg->Shaders[i]->Name == shader) {
245 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700246 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700247
248 shProg->Shaders[i]->RefCount--;
249
Brian5b01c5e2006-12-19 18:02:03 -0700250 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700251 newList = (struct gl_shader **)
252 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700253 if (!newList) {
254 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
255 return;
256 }
257 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700258 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700259 }
260 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700261 newList[j++] = shProg->Shaders[i];
262 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700263
264 /* XXX refcounting! */
265
Brian65a18442006-12-19 18:46:56 -0700266 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700267 return;
268 }
269 }
270
271 /* not found */
272 _mesa_error(ctx, GL_INVALID_OPERATION,
273 "glDetachShader(shader not found)");
274}
275
276
277void
278_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
279 GLsizei maxLength, GLsizei *length, GLint *size,
280 GLenum *type, GLchar *nameOut)
281{
282 static const GLenum vec_types[] = {
283 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
284 };
Brian65a18442006-12-19 18:46:56 -0700285 struct gl_shader_program *shProg
286 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700287 GLint sz;
288
Brian65a18442006-12-19 18:46:56 -0700289 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700290 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
291 return;
292 }
293
Brian65a18442006-12-19 18:46:56 -0700294 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700295 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
296 return;
297 }
298
299 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700300 shProg->Attributes->Parameters[index].Name);
301 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700302 if (size)
303 *size = sz;
304 if (type)
305 *type = vec_types[sz]; /* XXX this is a temporary hack */
306}
307
308
309/**
310 * Called via ctx->Driver.GetActiveUniform().
311 */
312void
313_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
314 GLsizei maxLength, GLsizei *length, GLint *size,
315 GLenum *type, GLchar *nameOut)
316{
317 static const GLenum vec_types[] = {
318 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
319 };
Brian65a18442006-12-19 18:46:56 -0700320 struct gl_shader_program *shProg
321 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700322 GLint sz;
323
Brian65a18442006-12-19 18:46:56 -0700324 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700325 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
326 return;
327 }
328
Brian65a18442006-12-19 18:46:56 -0700329 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700330 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
331 return;
332 }
333
334 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700335 shProg->Uniforms->Parameters[index].Name);
336 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700337 if (size)
338 *size = sz;
339 if (type)
340 *type = vec_types[sz]; /* XXX this is a temporary hack */
341}
342
343
344/**
345 * Called via ctx->Driver.GetAttachedShaders().
346 */
347void
348_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
349 GLsizei *count, GLuint *obj)
350{
Brian65a18442006-12-19 18:46:56 -0700351 struct gl_shader_program *shProg
352 = _mesa_lookup_shader_program(ctx, program);
353 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700354 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700355 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
356 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700357 }
358 if (count)
359 *count = i;
360 }
361 else {
362 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttachedShaders");
363 }
364}
365
366
367GLint
368_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
369 const GLchar *name)
370{
Brian65a18442006-12-19 18:46:56 -0700371 struct gl_shader_program *shProg
372 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700373
Brian65a18442006-12-19 18:46:56 -0700374 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700375 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttribLocation");
376 return -1;
377 }
378
Brian65a18442006-12-19 18:46:56 -0700379 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700380 _mesa_error(ctx, GL_INVALID_OPERATION,
381 "glGetAttribLocation(program not linked)");
382 return -1;
383 }
384
385 if (!name)
386 return -1;
387
Brian65a18442006-12-19 18:46:56 -0700388 if (shProg->Attributes) {
Brian5b01c5e2006-12-19 18:02:03 -0700389 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700390 for (i = 0; i < shProg->Attributes->NumParameters; i++) {
391 if (!strcmp(shProg->Attributes->Parameters[i].Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700392 return i;
393 }
394 }
395 }
396 return -1;
397}
398
399
400GLuint
401_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700402{
403#if 0
404 GET_CURRENT_CONTEXT(ctx);
405
406 switch (pname) {
407 case GL_PROGRAM_OBJECT_ARB:
408 {
Brian5b01c5e2006-12-19 18:02:03 -0700409 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700410
411 if (pro != NULL)
412 return (**pro)._container._generic.
413 GetName((struct gl2_generic_intf **) (pro));
414 }
415 break;
416 default:
417 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
418 }
419#endif
420 return 0;
421}
422
423
Brian5b01c5e2006-12-19 18:02:03 -0700424void
425_mesa_get_programiv(GLcontext *ctx, GLuint program,
426 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700427{
Brian65a18442006-12-19 18:46:56 -0700428 struct gl_shader_program *shProg
429 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700430
Brian65a18442006-12-19 18:46:56 -0700431 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700432 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700433 return;
434 }
435
Brian5b01c5e2006-12-19 18:02:03 -0700436 switch (pname) {
437 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700438 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700439 break;
440 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700441 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700442 break;
Brian5b01c5e2006-12-19 18:02:03 -0700443 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700444 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700445 break;
446 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700447 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700448 break;
449 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700450 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700451 break;
452 case GL_ACTIVE_ATTRIBUTES:
Brian65a18442006-12-19 18:46:56 -0700453 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700454 break;
455 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700456 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700457 break;
458 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700459 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700460 break;
461 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700462 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700463 break;
464 default:
Brian5b01c5e2006-12-19 18:02:03 -0700465 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
466 return;
Brian34ae99d2006-12-18 08:28:54 -0700467 }
Brian5b01c5e2006-12-19 18:02:03 -0700468}
Brian34ae99d2006-12-18 08:28:54 -0700469
Brian34ae99d2006-12-18 08:28:54 -0700470
Brian5b01c5e2006-12-19 18:02:03 -0700471void
472_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
473{
Brian65a18442006-12-19 18:46:56 -0700474 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700475
476 if (!shader) {
477 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
478 return;
479 }
Brian65a18442006-12-19 18:46:56 -0700480
Brian5b01c5e2006-12-19 18:02:03 -0700481 switch (pname) {
482 case GL_SHADER_TYPE:
483 *params = shader->Type;
484 break;
485 case GL_DELETE_STATUS:
486 *params = shader->DeletePending;
487 break;
488 case GL_COMPILE_STATUS:
489 *params = shader->CompileStatus;
490 break;
491 case GL_INFO_LOG_LENGTH:
492 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
493 break;
494 case GL_SHADER_SOURCE_LENGTH:
495 *params = shader->Source ? strlen((char *) shader->Source) : 0;
496 break;
497 default:
498 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
499 return;
500 }
501}
502
503
504void
505_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
506 GLsizei *length, GLchar *infoLog)
507{
Brian65a18442006-12-19 18:46:56 -0700508 struct gl_shader_program *shProg
509 = _mesa_lookup_shader_program(ctx, program);
510 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700511 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
512 return;
513 }
Brian65a18442006-12-19 18:46:56 -0700514 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700515}
516
517
518void
519_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
520 GLsizei *length, GLchar *infoLog)
521{
Brian65a18442006-12-19 18:46:56 -0700522 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
523 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700524 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
525 return;
526 }
Brian65a18442006-12-19 18:46:56 -0700527 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700528}
529
530
531/**
532 * Called via ctx->Driver.GetShaderSource().
533 */
534void
535_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
536 GLsizei *length, GLchar *sourceOut)
537{
Brian65a18442006-12-19 18:46:56 -0700538 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
539 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700540 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
541 return;
542 }
Brian65a18442006-12-19 18:46:56 -0700543 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700544}
545
546
547/**
548 * Called via ctx->Driver.GetUniformfv().
549 */
550void
551_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
552 GLfloat *params)
553{
Brian65a18442006-12-19 18:46:56 -0700554 struct gl_shader_program *shProg
555 = _mesa_lookup_shader_program(ctx, program);
556 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700557 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700558 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
559 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
560 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700561 }
562 }
563 else {
564 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
565 }
566 }
567 else {
568 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
569 }
570}
571
572
573/**
574 * Called via ctx->Driver.GetUniformLocation().
575 */
576GLint
577_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
578{
579 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700580 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian5b01c5e2006-12-19 18:02:03 -0700581 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700582 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700583 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700584 = shProg->Uniforms->Parameters + loc;
Brian5b01c5e2006-12-19 18:02:03 -0700585 if (u->Type == PROGRAM_UNIFORM && !strcmp(u->Name, name)) {
586 return loc;
587 }
588 }
589 }
590 return -1;
591
592}
593
594
595GLboolean
596_mesa_is_program(GLcontext *ctx, GLuint name)
597{
Brian65a18442006-12-19 18:46:56 -0700598 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
599 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700600}
601
602
603GLboolean
604_mesa_is_shader(GLcontext *ctx, GLuint name)
605{
Brian65a18442006-12-19 18:46:56 -0700606 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700607 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700608}
609
610
611
Brian5b01c5e2006-12-19 18:02:03 -0700612/**
613 * Called via ctx->Driver.ShaderSource()
614 */
615void
616_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700617{
Brian65a18442006-12-19 18:46:56 -0700618 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
619 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700620 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700621 return;
622 }
623
Brian34ae99d2006-12-18 08:28:54 -0700624 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700625 if (sh->Source) {
626 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700627 }
Brian65a18442006-12-19 18:46:56 -0700628 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700629 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700630}
631
632
Brian5b01c5e2006-12-19 18:02:03 -0700633/**
634 * Called via ctx->Driver.CompileShader()
635 */
636void
637_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700638{
Brian65a18442006-12-19 18:46:56 -0700639 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700640 slang_info_log info_log;
641 slang_code_object obj;
642 slang_unit_type type;
643
Brian65a18442006-12-19 18:46:56 -0700644 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700645 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
646 return;
647 }
648
649 slang_info_log_construct(&info_log);
650 _slang_code_object_ctr(&obj);
651
Brian65a18442006-12-19 18:46:56 -0700652 if (sh->Type == GL_VERTEX_SHADER) {
Brian34ae99d2006-12-18 08:28:54 -0700653 type = slang_unit_vertex_shader;
654 }
655 else {
Brian65a18442006-12-19 18:46:56 -0700656 assert(sh->Type == GL_FRAGMENT_SHADER);
Brian34ae99d2006-12-18 08:28:54 -0700657 type = slang_unit_fragment_shader;
658 }
659
Brian65a18442006-12-19 18:46:56 -0700660 if (_slang_compile(sh->Source, &obj, type, &info_log, sh)) {
661 sh->CompileStatus = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700662 }
663 else {
Brian65a18442006-12-19 18:46:56 -0700664 sh->CompileStatus = GL_FALSE;
665 /* XXX temporary */
Brian34ae99d2006-12-18 08:28:54 -0700666 _mesa_problem(ctx, "Program did not compile!");
667 }
668}
669
670
Brian5b01c5e2006-12-19 18:02:03 -0700671/**
672 * Called via ctx->Driver.LinkProgram()
673 */
674void
675_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700676{
Brian65a18442006-12-19 18:46:56 -0700677 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700678
Brian65a18442006-12-19 18:46:56 -0700679 shProg = _mesa_lookup_shader_program(ctx, program);
680 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700681 _mesa_error(ctx, GL_INVALID_OPERATION, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700682 return;
683 }
684
Brian65a18442006-12-19 18:46:56 -0700685 _slang_link2(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700686}
687
688
689/**
Brian5b01c5e2006-12-19 18:02:03 -0700690 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700691 */
Brian5b01c5e2006-12-19 18:02:03 -0700692void
693_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700694{
Brian9e4bae92006-12-20 09:27:42 -0700695 /* unbind old */
696 if (ctx->Shader.CurrentProgram) {
697 ctx->Shader.CurrentProgram->RefCount--;
698 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
699 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
700 }
701 ctx->Shader.CurrentProgram = NULL;
702 }
703
Brian5b01c5e2006-12-19 18:02:03 -0700704 /* XXXX need to handle reference counting here! */
705 if (program) {
Brian65a18442006-12-19 18:46:56 -0700706 struct gl_shader_program *shProg;
707 shProg = _mesa_lookup_shader_program(ctx, program);
708 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700709 _mesa_error(ctx, GL_INVALID_OPERATION,
710 "glUseProgramObjectARB(programObj)");
711 return;
712 }
Brian65a18442006-12-19 18:46:56 -0700713 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700714 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700715 }
716 else {
717 /* don't use a shader program */
718 ctx->Shader.CurrentProgram = NULL;
719 }
720}
Brian34ae99d2006-12-18 08:28:54 -0700721
Brian5b01c5e2006-12-19 18:02:03 -0700722
723/**
724 * Called via ctx->Driver.Uniform().
725 */
726void
727_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
728 const GLvoid *values, GLenum type)
729{
730 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700731 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
732 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
733 GLfloat *v = shProg->Uniforms->ParameterValues[location];
Brian34ae99d2006-12-18 08:28:54 -0700734 const GLfloat *fValues = (const GLfloat *) values; /* XXX */
735 GLint i;
736 if (type == GL_FLOAT_VEC4)
737 count *= 4;
738 else if (type == GL_FLOAT_VEC3)
739 count *= 3;
740 else
741 abort();
742
743 for (i = 0; i < count; i++)
744 v[i] = fValues[i];
745 return;
746 }
747 }
Brian5b01c5e2006-12-19 18:02:03 -0700748 else {
749 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
750 }
Brian34ae99d2006-12-18 08:28:54 -0700751}
752
753
754/**
Brian5b01c5e2006-12-19 18:02:03 -0700755 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700756 */
Brian5b01c5e2006-12-19 18:02:03 -0700757void
758_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
759 GLenum matrixType, GLint location, GLsizei count,
760 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700761{
Brian5b01c5e2006-12-19 18:02:03 -0700762 const char *caller = "glUniformMatrix";
Brian34ae99d2006-12-18 08:28:54 -0700763 const GLint matElements = rows * cols;
Brian34ae99d2006-12-18 08:28:54 -0700764
765 if (values == NULL) {
766 _mesa_error(ctx, GL_INVALID_VALUE, caller);
767 return;
768 }
769
770 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
771
772 if (transpose) {
773 GLfloat *trans, *pt;
774 const GLfloat *pv;
775 GLint i, j, k;
776
777 trans = (GLfloat *) _mesa_malloc(count * matElements * sizeof(GLfloat));
778 if (!trans) {
779 _mesa_error(ctx, GL_OUT_OF_MEMORY, caller);
780 return;
781 }
782
783 pt = trans;
784 pv = values;
785 for (i = 0; i < count; i++) {
786 /* transpose from pv matrix into pt matrix */
787 for (j = 0; j < cols; j++) {
788 for (k = 0; k < rows; k++) {
789 /* XXX verify this */
790 pt[j * rows + k] = pv[k * cols + j];
791 }
792 }
793 pt += matElements;
794 pv += matElements;
795 }
796
797#ifdef OLD
798 if (!(**pro).WriteUniform(pro, location, count, trans, matrixType))
799 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
800#endif
801 _mesa_free(trans);
802 }
803 else {
804#ifdef OLD
805 if (!(**pro).WriteUniform(pro, location, count, values, matrixType))
806 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
807#endif
808 }
809}
810
811
Brian5b01c5e2006-12-19 18:02:03 -0700812void
813_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700814{
Brian65a18442006-12-19 18:46:56 -0700815 struct gl_shader_program *shProg;
816 shProg = _mesa_lookup_shader_program(ctx, program);
817 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700818 _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700819 return;
820 }
Brian5b01c5e2006-12-19 18:02:03 -0700821 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -0700822 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700823
Brian5b01c5e2006-12-19 18:02:03 -0700824 /* From the GL spec:
825 any two active samplers in the current program object are of
826 different types, but refer to the same texture image unit,
827
828 any active sampler in the current program object refers to a texture
829 image unit where fixed-function fragment processing accesses a
830 texture target that does not match the sampler type, or
831
832 the sum of the number of active samplers in the program and the
833 number of texture image units enabled for fixed-function fragment
834 processing exceeds the combined limit on the total number of texture
835 image units allowed.
836 */
Brian34ae99d2006-12-18 08:28:54 -0700837}
838
839
Brian34ae99d2006-12-18 08:28:54 -0700840
Brian5b01c5e2006-12-19 18:02:03 -0700841/**********************************************************************/
Brian34ae99d2006-12-18 08:28:54 -0700842
843
844/**
Brian65a18442006-12-19 18:46:56 -0700845 * Allocate a new gl_shader_program object, initialize it.
Brian34ae99d2006-12-18 08:28:54 -0700846 */
Brian65a18442006-12-19 18:46:56 -0700847struct gl_shader_program *
848_mesa_new_shader_program(GLcontext *ctx, GLuint name)
Brian34ae99d2006-12-18 08:28:54 -0700849{
Brian65a18442006-12-19 18:46:56 -0700850 struct gl_shader_program *shProg;
851 shProg = CALLOC_STRUCT(gl_shader_program);
852 if (shProg) {
853 shProg->Type = GL_SHADER_PROGRAM;
854 shProg->Name = name;
Brian9e4bae92006-12-20 09:27:42 -0700855 shProg->RefCount = 1;
Brian34ae99d2006-12-18 08:28:54 -0700856 }
Brian65a18442006-12-19 18:46:56 -0700857 return shProg;
Brian34ae99d2006-12-18 08:28:54 -0700858}
859
860
861void
Brian65a18442006-12-19 18:46:56 -0700862_mesa_free_shader_program_data(GLcontext *ctx,
863 struct gl_shader_program *shProg)
Brian34ae99d2006-12-18 08:28:54 -0700864{
Brian65a18442006-12-19 18:46:56 -0700865 assert(shProg->Type == GL_SHADER_PROGRAM);
866
867 if (shProg->VertexProgram) {
868 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
Brian34ae99d2006-12-18 08:28:54 -0700869 /* to prevent a double-free in the next call */
Brian65a18442006-12-19 18:46:56 -0700870 shProg->VertexProgram->Base.Parameters = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700871 }
Brian65a18442006-12-19 18:46:56 -0700872 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
873 shProg->VertexProgram = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700874 }
875
Brian65a18442006-12-19 18:46:56 -0700876 if (shProg->FragmentProgram) {
877 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
Brian34ae99d2006-12-18 08:28:54 -0700878 /* to prevent a double-free in the next call */
Brian65a18442006-12-19 18:46:56 -0700879 shProg->FragmentProgram->Base.Parameters = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700880 }
Brian65a18442006-12-19 18:46:56 -0700881 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
882 shProg->FragmentProgram = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700883 }
884
885
Brian65a18442006-12-19 18:46:56 -0700886 if (shProg->Uniforms) {
887 _mesa_free_parameter_list(shProg->Uniforms);
888 shProg->Uniforms = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700889 }
890
Brian65a18442006-12-19 18:46:56 -0700891 if (shProg->Varying) {
892 _mesa_free_parameter_list(shProg->Varying);
893 shProg->Varying = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700894 }
895}
896
897
898
899void
Brian9e4bae92006-12-20 09:27:42 -0700900_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
Brian34ae99d2006-12-18 08:28:54 -0700901{
Brian65a18442006-12-19 18:46:56 -0700902 _mesa_free_shader_program_data(ctx, shProg);
903 _mesa_free(shProg);
Brian34ae99d2006-12-18 08:28:54 -0700904}
905
906
907/**
908 * Lookup a GLSL program object.
909 */
Brian65a18442006-12-19 18:46:56 -0700910struct gl_shader_program *
911_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
Brian34ae99d2006-12-18 08:28:54 -0700912{
Brian65a18442006-12-19 18:46:56 -0700913 struct gl_shader_program *shProg;
914 if (name) {
915 shProg = (struct gl_shader_program *)
916 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
917 /* Note that both gl_shader and gl_shader_program objects are kept
918 * in the same hash table. Check the object's type to be sure it's
919 * what we're expecting.
920 */
921 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
922 return NULL;
923 }
924 return shProg;
925 }
926 return NULL;
Brian34ae99d2006-12-18 08:28:54 -0700927}
928
929
Brian65a18442006-12-19 18:46:56 -0700930/**
931 * Allocate a new gl_shader object, initialize it.
932 */
Brian34ae99d2006-12-18 08:28:54 -0700933struct gl_shader *
934_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
935{
936 struct gl_shader *shader;
937 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
938 shader = CALLOC_STRUCT(gl_shader);
939 if (shader) {
Brian34ae99d2006-12-18 08:28:54 -0700940 shader->Type = type;
Brian65a18442006-12-19 18:46:56 -0700941 shader->Name = name;
Brian9e4bae92006-12-20 09:27:42 -0700942 shader->RefCount = 1;
Brian34ae99d2006-12-18 08:28:54 -0700943 }
944 return shader;
945}
946
947
Brian9e4bae92006-12-20 09:27:42 -0700948void
949_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
950{
951 GLuint i;
952 if (sh->Source)
953 _mesa_free((void *) sh->Source);
954 if (sh->InfoLog)
955 _mesa_free(sh->InfoLog);
956 for (i = 0; i < sh->NumPrograms; i++) {
957 assert(sh->Programs[i]);
958 _mesa_delete_program(ctx, sh->Programs[i]);
959 }
960 if (sh->Programs)
961 _mesa_free(sh->Programs);
962 _mesa_free(sh);
963}
964
965
Brian34ae99d2006-12-18 08:28:54 -0700966/**
967 * Lookup a GLSL shader object.
968 */
Brian65a18442006-12-19 18:46:56 -0700969struct gl_shader *
Brian34ae99d2006-12-18 08:28:54 -0700970_mesa_lookup_shader(GLcontext *ctx, GLuint name)
971{
Brian65a18442006-12-19 18:46:56 -0700972 if (name) {
973 struct gl_shader *sh = (struct gl_shader *)
Brian34ae99d2006-12-18 08:28:54 -0700974 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brian65a18442006-12-19 18:46:56 -0700975 /* Note that both gl_shader and gl_shader_program objects are kept
976 * in the same hash table. Check the object's type to be sure it's
977 * what we're expecting.
978 */
979 if (sh && sh->Type == GL_SHADER_PROGRAM) {
980 assert(sh->Type == GL_VERTEX_SHADER ||
981 sh->Type == GL_FRAGMENT_SHADER);
982 return NULL;
983 }
984 return sh;
985 }
986 return NULL;
Brian34ae99d2006-12-18 08:28:54 -0700987}
988
989
Brian5b01c5e2006-12-19 18:02:03 -0700990void
991_mesa_init_shader_state(GLcontext * ctx)
Brian34ae99d2006-12-18 08:28:54 -0700992{
Brian5b01c5e2006-12-19 18:02:03 -0700993 ctx->Shader._FragmentShaderPresent = GL_FALSE;
994 ctx->Shader._VertexShaderPresent = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700995}