blob: e49feea3d86eb5338cfe99020c4b1911ade6651a [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
129#if 0 /* XXXX */
130 if (name == NULL || index >= MAX_VERTEX_ATTRIBS)
131 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocationARB");
132 else if (IS_NAME_WITH_GL_PREFIX(name))
133 _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocationARB");
134 else
135 (**pro).OverrideAttribBinding(pro, index, name);
136 RELEASE_PROGRAM(pro);
Brian34ae99d2006-12-18 08:28:54 -0700137#endif
138}
139
140
Brian5b01c5e2006-12-19 18:02:03 -0700141GLuint
142_mesa_create_shader(GLcontext *ctx, GLenum type)
143{
Brian65a18442006-12-19 18:46:56 -0700144 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700145 GLuint name;
146
147 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
148
149 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700150 case GL_FRAGMENT_SHADER:
151 case GL_VERTEX_SHADER:
152 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700153 break;
154 default:
155 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
156 return 0;
157 }
158
Brian65a18442006-12-19 18:46:56 -0700159 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700160
161 return name;
162}
163
164
165GLuint
166_mesa_create_program(GLcontext *ctx)
167{
168 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700169 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700170
Brian65a18442006-12-19 18:46:56 -0700171 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
172 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700173
Brian65a18442006-12-19 18:46:56 -0700174 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700175
176 return name;
177}
178
179
180void
181_mesa_delete_program2(GLcontext *ctx, GLuint name)
182{
Brian65a18442006-12-19 18:46:56 -0700183 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700184
Brian65a18442006-12-19 18:46:56 -0700185 shProg = _mesa_lookup_shader_program(ctx, name);
186 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700187 _mesa_error(ctx, GL_INVALID_OPERATION, "glDeleteProgram(name)");
188 return;
189 }
190
191 /* XXX refcounting! */
Brian65a18442006-12-19 18:46:56 -0700192 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
193 _mesa_delete_shader_program(ctx, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700194}
195
196
197void
198_mesa_delete_shader(GLcontext *ctx, GLuint shader)
199{
200 /* XXX refcounting! */
201
202 /*
203 _mesa_DeleteObjectARB(shader);
204 */
205}
206
207
208void
209_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
210{
Brian65a18442006-12-19 18:46:56 -0700211 struct gl_shader_program *shProg
212 = _mesa_lookup_shader_program(ctx, program);
213 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700214 GLuint i, j;
215
Brian65a18442006-12-19 18:46:56 -0700216 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700217 _mesa_error(ctx, GL_INVALID_OPERATION,
218 "glDetachShader(bad program or shader name)");
219 return;
220 }
221
222 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700223 if (shProg->Shaders[i]->Name == shader) {
224 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700225 /* found it */
226 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700227 newList = (struct gl_shader **)
228 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700229 if (!newList) {
230 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
231 return;
232 }
233 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700234 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700235 }
236 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700237 newList[j++] = shProg->Shaders[i];
238 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700239
240 /* XXX refcounting! */
241
Brian65a18442006-12-19 18:46:56 -0700242 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700243 return;
244 }
245 }
246
247 /* not found */
248 _mesa_error(ctx, GL_INVALID_OPERATION,
249 "glDetachShader(shader not found)");
250}
251
252
253void
254_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
255 GLsizei maxLength, GLsizei *length, GLint *size,
256 GLenum *type, GLchar *nameOut)
257{
258 static const GLenum vec_types[] = {
259 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
260 };
Brian65a18442006-12-19 18:46:56 -0700261 struct gl_shader_program *shProg
262 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700263 GLint sz;
264
Brian65a18442006-12-19 18:46:56 -0700265 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700266 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
267 return;
268 }
269
Brian65a18442006-12-19 18:46:56 -0700270 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700271 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
272 return;
273 }
274
275 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700276 shProg->Attributes->Parameters[index].Name);
277 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700278 if (size)
279 *size = sz;
280 if (type)
281 *type = vec_types[sz]; /* XXX this is a temporary hack */
282}
283
284
285/**
286 * Called via ctx->Driver.GetActiveUniform().
287 */
288void
289_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
290 GLsizei maxLength, GLsizei *length, GLint *size,
291 GLenum *type, GLchar *nameOut)
292{
293 static const GLenum vec_types[] = {
294 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
295 };
Brian65a18442006-12-19 18:46:56 -0700296 struct gl_shader_program *shProg
297 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700298 GLint sz;
299
Brian65a18442006-12-19 18:46:56 -0700300 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700301 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniform");
302 return;
303 }
304
Brian65a18442006-12-19 18:46:56 -0700305 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700306 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
307 return;
308 }
309
310 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700311 shProg->Uniforms->Parameters[index].Name);
312 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700313 if (size)
314 *size = sz;
315 if (type)
316 *type = vec_types[sz]; /* XXX this is a temporary hack */
317}
318
319
320/**
321 * Called via ctx->Driver.GetAttachedShaders().
322 */
323void
324_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
325 GLsizei *count, GLuint *obj)
326{
Brian65a18442006-12-19 18:46:56 -0700327 struct gl_shader_program *shProg
328 = _mesa_lookup_shader_program(ctx, program);
329 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700330 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700331 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
332 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700333 }
334 if (count)
335 *count = i;
336 }
337 else {
338 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttachedShaders");
339 }
340}
341
342
343GLint
344_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
345 const GLchar *name)
346{
Brian65a18442006-12-19 18:46:56 -0700347 struct gl_shader_program *shProg
348 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700349
Brian65a18442006-12-19 18:46:56 -0700350 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700351 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetAttribLocation");
352 return -1;
353 }
354
Brian65a18442006-12-19 18:46:56 -0700355 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700356 _mesa_error(ctx, GL_INVALID_OPERATION,
357 "glGetAttribLocation(program not linked)");
358 return -1;
359 }
360
361 if (!name)
362 return -1;
363
Brian65a18442006-12-19 18:46:56 -0700364 if (shProg->Attributes) {
Brian5b01c5e2006-12-19 18:02:03 -0700365 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700366 for (i = 0; i < shProg->Attributes->NumParameters; i++) {
367 if (!strcmp(shProg->Attributes->Parameters[i].Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700368 return i;
369 }
370 }
371 }
372 return -1;
373}
374
375
376GLuint
377_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700378{
379#if 0
380 GET_CURRENT_CONTEXT(ctx);
381
382 switch (pname) {
383 case GL_PROGRAM_OBJECT_ARB:
384 {
Brian5b01c5e2006-12-19 18:02:03 -0700385 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700386
387 if (pro != NULL)
388 return (**pro)._container._generic.
389 GetName((struct gl2_generic_intf **) (pro));
390 }
391 break;
392 default:
393 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
394 }
395#endif
396 return 0;
397}
398
399
Brian5b01c5e2006-12-19 18:02:03 -0700400void
401_mesa_get_programiv(GLcontext *ctx, GLuint program,
402 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700403{
Brian65a18442006-12-19 18:46:56 -0700404 struct gl_shader_program *shProg
405 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700406
Brian65a18442006-12-19 18:46:56 -0700407 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700408 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700409 return;
410 }
411
Brian5b01c5e2006-12-19 18:02:03 -0700412 switch (pname) {
413 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700414 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700415 break;
416 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700417 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700418 break;
Brian5b01c5e2006-12-19 18:02:03 -0700419 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700420 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700421 break;
422 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700423 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700424 break;
425 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700426 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700427 break;
428 case GL_ACTIVE_ATTRIBUTES:
Brian65a18442006-12-19 18:46:56 -0700429 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700430 break;
431 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700432 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700433 break;
434 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700435 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700436 break;
437 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700438 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700439 break;
440 default:
Brian5b01c5e2006-12-19 18:02:03 -0700441 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
442 return;
Brian34ae99d2006-12-18 08:28:54 -0700443 }
Brian5b01c5e2006-12-19 18:02:03 -0700444}
Brian34ae99d2006-12-18 08:28:54 -0700445
Brian34ae99d2006-12-18 08:28:54 -0700446
Brian5b01c5e2006-12-19 18:02:03 -0700447void
448_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
449{
Brian65a18442006-12-19 18:46:56 -0700450 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700451
452 if (!shader) {
453 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
454 return;
455 }
Brian65a18442006-12-19 18:46:56 -0700456
Brian5b01c5e2006-12-19 18:02:03 -0700457 switch (pname) {
458 case GL_SHADER_TYPE:
459 *params = shader->Type;
460 break;
461 case GL_DELETE_STATUS:
462 *params = shader->DeletePending;
463 break;
464 case GL_COMPILE_STATUS:
465 *params = shader->CompileStatus;
466 break;
467 case GL_INFO_LOG_LENGTH:
468 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
469 break;
470 case GL_SHADER_SOURCE_LENGTH:
471 *params = shader->Source ? strlen((char *) shader->Source) : 0;
472 break;
473 default:
474 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
475 return;
476 }
477}
478
479
480void
481_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
482 GLsizei *length, GLchar *infoLog)
483{
Brian65a18442006-12-19 18:46:56 -0700484 struct gl_shader_program *shProg
485 = _mesa_lookup_shader_program(ctx, program);
486 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700487 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
488 return;
489 }
Brian65a18442006-12-19 18:46:56 -0700490 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700491}
492
493
494void
495_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
496 GLsizei *length, GLchar *infoLog)
497{
Brian65a18442006-12-19 18:46:56 -0700498 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
499 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700500 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
501 return;
502 }
Brian65a18442006-12-19 18:46:56 -0700503 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700504}
505
506
507/**
508 * Called via ctx->Driver.GetShaderSource().
509 */
510void
511_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
512 GLsizei *length, GLchar *sourceOut)
513{
Brian65a18442006-12-19 18:46:56 -0700514 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
515 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700516 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
517 return;
518 }
Brian65a18442006-12-19 18:46:56 -0700519 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700520}
521
522
523/**
524 * Called via ctx->Driver.GetUniformfv().
525 */
526void
527_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
528 GLfloat *params)
529{
Brian65a18442006-12-19 18:46:56 -0700530 struct gl_shader_program *shProg
531 = _mesa_lookup_shader_program(ctx, program);
532 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700533 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700534 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
535 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
536 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700537 }
538 }
539 else {
540 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
541 }
542 }
543 else {
544 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
545 }
546}
547
548
549/**
550 * Called via ctx->Driver.GetUniformLocation().
551 */
552GLint
553_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
554{
555 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700556 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian5b01c5e2006-12-19 18:02:03 -0700557 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700558 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700559 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700560 = shProg->Uniforms->Parameters + loc;
Brian5b01c5e2006-12-19 18:02:03 -0700561 if (u->Type == PROGRAM_UNIFORM && !strcmp(u->Name, name)) {
562 return loc;
563 }
564 }
565 }
566 return -1;
567
568}
569
570
571GLboolean
572_mesa_is_program(GLcontext *ctx, GLuint name)
573{
Brian65a18442006-12-19 18:46:56 -0700574 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
575 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700576}
577
578
579GLboolean
580_mesa_is_shader(GLcontext *ctx, GLuint name)
581{
Brian65a18442006-12-19 18:46:56 -0700582 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700583 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700584}
585
586
587
Brian5b01c5e2006-12-19 18:02:03 -0700588/**
589 * Called via ctx->Driver.ShaderSource()
590 */
591void
592_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700593{
Brian65a18442006-12-19 18:46:56 -0700594 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
595 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700596 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700597 return;
598 }
599
Brian34ae99d2006-12-18 08:28:54 -0700600 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700601 if (sh->Source) {
602 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700603 }
Brian65a18442006-12-19 18:46:56 -0700604 sh->Source = source;
Brian34ae99d2006-12-18 08:28:54 -0700605}
606
607
Brian5b01c5e2006-12-19 18:02:03 -0700608/**
609 * Called via ctx->Driver.CompileShader()
610 */
611void
612_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700613{
Brian65a18442006-12-19 18:46:56 -0700614 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700615 slang_info_log info_log;
616 slang_code_object obj;
617 slang_unit_type type;
618
Brian65a18442006-12-19 18:46:56 -0700619 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700620 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
621 return;
622 }
623
624 slang_info_log_construct(&info_log);
625 _slang_code_object_ctr(&obj);
626
Brian65a18442006-12-19 18:46:56 -0700627 if (sh->Type == GL_VERTEX_SHADER) {
Brian34ae99d2006-12-18 08:28:54 -0700628 type = slang_unit_vertex_shader;
629 }
630 else {
Brian65a18442006-12-19 18:46:56 -0700631 assert(sh->Type == GL_FRAGMENT_SHADER);
Brian34ae99d2006-12-18 08:28:54 -0700632 type = slang_unit_fragment_shader;
633 }
634
Brian65a18442006-12-19 18:46:56 -0700635 if (_slang_compile(sh->Source, &obj, type, &info_log, sh)) {
636 sh->CompileStatus = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700637 }
638 else {
Brian65a18442006-12-19 18:46:56 -0700639 sh->CompileStatus = GL_FALSE;
640 /* XXX temporary */
Brian34ae99d2006-12-18 08:28:54 -0700641 _mesa_problem(ctx, "Program did not compile!");
642 }
643}
644
645
Brian5b01c5e2006-12-19 18:02:03 -0700646/**
647 * Called via ctx->Driver.LinkProgram()
648 */
649void
650_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700651{
Brian65a18442006-12-19 18:46:56 -0700652 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700653
Brian65a18442006-12-19 18:46:56 -0700654 shProg = _mesa_lookup_shader_program(ctx, program);
655 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700656 _mesa_error(ctx, GL_INVALID_OPERATION, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700657 return;
658 }
659
Brian65a18442006-12-19 18:46:56 -0700660 _slang_link2(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700661}
662
663
664/**
Brian5b01c5e2006-12-19 18:02:03 -0700665 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700666 */
Brian5b01c5e2006-12-19 18:02:03 -0700667void
668_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700669{
Brian5b01c5e2006-12-19 18:02:03 -0700670 /* XXXX need to handle reference counting here! */
671 if (program) {
Brian65a18442006-12-19 18:46:56 -0700672 struct gl_shader_program *shProg;
673 shProg = _mesa_lookup_shader_program(ctx, program);
674 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700675 _mesa_error(ctx, GL_INVALID_OPERATION,
676 "glUseProgramObjectARB(programObj)");
677 return;
678 }
Brian65a18442006-12-19 18:46:56 -0700679 ctx->Shader.CurrentProgram = shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700680 }
681 else {
682 /* don't use a shader program */
683 ctx->Shader.CurrentProgram = NULL;
684 }
685}
Brian34ae99d2006-12-18 08:28:54 -0700686
Brian5b01c5e2006-12-19 18:02:03 -0700687
688/**
689 * Called via ctx->Driver.Uniform().
690 */
691void
692_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
693 const GLvoid *values, GLenum type)
694{
695 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700696 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
697 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
698 GLfloat *v = shProg->Uniforms->ParameterValues[location];
Brian34ae99d2006-12-18 08:28:54 -0700699 const GLfloat *fValues = (const GLfloat *) values; /* XXX */
700 GLint i;
701 if (type == GL_FLOAT_VEC4)
702 count *= 4;
703 else if (type == GL_FLOAT_VEC3)
704 count *= 3;
705 else
706 abort();
707
708 for (i = 0; i < count; i++)
709 v[i] = fValues[i];
710 return;
711 }
712 }
Brian5b01c5e2006-12-19 18:02:03 -0700713 else {
714 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
715 }
Brian34ae99d2006-12-18 08:28:54 -0700716}
717
718
719/**
Brian5b01c5e2006-12-19 18:02:03 -0700720 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700721 */
Brian5b01c5e2006-12-19 18:02:03 -0700722void
723_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
724 GLenum matrixType, GLint location, GLsizei count,
725 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700726{
Brian5b01c5e2006-12-19 18:02:03 -0700727 const char *caller = "glUniformMatrix";
Brian34ae99d2006-12-18 08:28:54 -0700728 const GLint matElements = rows * cols;
Brian34ae99d2006-12-18 08:28:54 -0700729
730 if (values == NULL) {
731 _mesa_error(ctx, GL_INVALID_VALUE, caller);
732 return;
733 }
734
735 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
736
737 if (transpose) {
738 GLfloat *trans, *pt;
739 const GLfloat *pv;
740 GLint i, j, k;
741
742 trans = (GLfloat *) _mesa_malloc(count * matElements * sizeof(GLfloat));
743 if (!trans) {
744 _mesa_error(ctx, GL_OUT_OF_MEMORY, caller);
745 return;
746 }
747
748 pt = trans;
749 pv = values;
750 for (i = 0; i < count; i++) {
751 /* transpose from pv matrix into pt matrix */
752 for (j = 0; j < cols; j++) {
753 for (k = 0; k < rows; k++) {
754 /* XXX verify this */
755 pt[j * rows + k] = pv[k * cols + j];
756 }
757 }
758 pt += matElements;
759 pv += matElements;
760 }
761
762#ifdef OLD
763 if (!(**pro).WriteUniform(pro, location, count, trans, matrixType))
764 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
765#endif
766 _mesa_free(trans);
767 }
768 else {
769#ifdef OLD
770 if (!(**pro).WriteUniform(pro, location, count, values, matrixType))
771 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
772#endif
773 }
774}
775
776
Brian5b01c5e2006-12-19 18:02:03 -0700777void
778_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700779{
Brian65a18442006-12-19 18:46:56 -0700780 struct gl_shader_program *shProg;
781 shProg = _mesa_lookup_shader_program(ctx, program);
782 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700783 _mesa_error(ctx, GL_INVALID_OPERATION, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700784 return;
785 }
Brian5b01c5e2006-12-19 18:02:03 -0700786 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -0700787 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -0700788
Brian5b01c5e2006-12-19 18:02:03 -0700789 /* From the GL spec:
790 any two active samplers in the current program object are of
791 different types, but refer to the same texture image unit,
792
793 any active sampler in the current program object refers to a texture
794 image unit where fixed-function fragment processing accesses a
795 texture target that does not match the sampler type, or
796
797 the sum of the number of active samplers in the program and the
798 number of texture image units enabled for fixed-function fragment
799 processing exceeds the combined limit on the total number of texture
800 image units allowed.
801 */
Brian34ae99d2006-12-18 08:28:54 -0700802}
803
804
Brian34ae99d2006-12-18 08:28:54 -0700805
Brian5b01c5e2006-12-19 18:02:03 -0700806/**********************************************************************/
Brian34ae99d2006-12-18 08:28:54 -0700807
808
809/**
Brian65a18442006-12-19 18:46:56 -0700810 * Allocate a new gl_shader_program object, initialize it.
Brian34ae99d2006-12-18 08:28:54 -0700811 */
Brian65a18442006-12-19 18:46:56 -0700812struct gl_shader_program *
813_mesa_new_shader_program(GLcontext *ctx, GLuint name)
Brian34ae99d2006-12-18 08:28:54 -0700814{
Brian65a18442006-12-19 18:46:56 -0700815 struct gl_shader_program *shProg;
816 shProg = CALLOC_STRUCT(gl_shader_program);
817 if (shProg) {
818 shProg->Type = GL_SHADER_PROGRAM;
819 shProg->Name = name;
Brian34ae99d2006-12-18 08:28:54 -0700820 }
Brian65a18442006-12-19 18:46:56 -0700821 return shProg;
Brian34ae99d2006-12-18 08:28:54 -0700822}
823
824
825void
Brian65a18442006-12-19 18:46:56 -0700826_mesa_free_shader_program_data(GLcontext *ctx,
827 struct gl_shader_program *shProg)
Brian34ae99d2006-12-18 08:28:54 -0700828{
Brian65a18442006-12-19 18:46:56 -0700829 assert(shProg->Type == GL_SHADER_PROGRAM);
830
831 if (shProg->VertexProgram) {
832 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
Brian34ae99d2006-12-18 08:28:54 -0700833 /* to prevent a double-free in the next call */
Brian65a18442006-12-19 18:46:56 -0700834 shProg->VertexProgram->Base.Parameters = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700835 }
Brian65a18442006-12-19 18:46:56 -0700836 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
837 shProg->VertexProgram = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700838 }
839
Brian65a18442006-12-19 18:46:56 -0700840 if (shProg->FragmentProgram) {
841 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
Brian34ae99d2006-12-18 08:28:54 -0700842 /* to prevent a double-free in the next call */
Brian65a18442006-12-19 18:46:56 -0700843 shProg->FragmentProgram->Base.Parameters = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700844 }
Brian65a18442006-12-19 18:46:56 -0700845 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
846 shProg->FragmentProgram = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700847 }
848
849
Brian65a18442006-12-19 18:46:56 -0700850 if (shProg->Uniforms) {
851 _mesa_free_parameter_list(shProg->Uniforms);
852 shProg->Uniforms = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700853 }
854
Brian65a18442006-12-19 18:46:56 -0700855 if (shProg->Varying) {
856 _mesa_free_parameter_list(shProg->Varying);
857 shProg->Varying = NULL;
Brian34ae99d2006-12-18 08:28:54 -0700858 }
859}
860
861
862
863void
Brian65a18442006-12-19 18:46:56 -0700864_mesa_delete_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
Brian34ae99d2006-12-18 08:28:54 -0700865{
Brian65a18442006-12-19 18:46:56 -0700866 _mesa_free_shader_program_data(ctx, shProg);
867 _mesa_free(shProg);
Brian34ae99d2006-12-18 08:28:54 -0700868}
869
870
871/**
872 * Lookup a GLSL program object.
873 */
Brian65a18442006-12-19 18:46:56 -0700874struct gl_shader_program *
875_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
Brian34ae99d2006-12-18 08:28:54 -0700876{
Brian65a18442006-12-19 18:46:56 -0700877 struct gl_shader_program *shProg;
878 if (name) {
879 shProg = (struct gl_shader_program *)
880 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
881 /* Note that both gl_shader and gl_shader_program objects are kept
882 * in the same hash table. Check the object's type to be sure it's
883 * what we're expecting.
884 */
885 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
886 return NULL;
887 }
888 return shProg;
889 }
890 return NULL;
Brian34ae99d2006-12-18 08:28:54 -0700891}
892
893
Brian65a18442006-12-19 18:46:56 -0700894/**
895 * Allocate a new gl_shader object, initialize it.
896 */
Brian34ae99d2006-12-18 08:28:54 -0700897struct gl_shader *
898_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
899{
900 struct gl_shader *shader;
901 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
902 shader = CALLOC_STRUCT(gl_shader);
903 if (shader) {
Brian34ae99d2006-12-18 08:28:54 -0700904 shader->Type = type;
Brian65a18442006-12-19 18:46:56 -0700905 shader->Name = name;
Brian34ae99d2006-12-18 08:28:54 -0700906 }
907 return shader;
908}
909
910
911/**
912 * Lookup a GLSL shader object.
913 */
Brian65a18442006-12-19 18:46:56 -0700914struct gl_shader *
Brian34ae99d2006-12-18 08:28:54 -0700915_mesa_lookup_shader(GLcontext *ctx, GLuint name)
916{
Brian65a18442006-12-19 18:46:56 -0700917 if (name) {
918 struct gl_shader *sh = (struct gl_shader *)
Brian34ae99d2006-12-18 08:28:54 -0700919 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brian65a18442006-12-19 18:46:56 -0700920 /* Note that both gl_shader and gl_shader_program objects are kept
921 * in the same hash table. Check the object's type to be sure it's
922 * what we're expecting.
923 */
924 if (sh && sh->Type == GL_SHADER_PROGRAM) {
925 assert(sh->Type == GL_VERTEX_SHADER ||
926 sh->Type == GL_FRAGMENT_SHADER);
927 return NULL;
928 }
929 return sh;
930 }
931 return NULL;
Brian34ae99d2006-12-18 08:28:54 -0700932}
933
934
Brian5b01c5e2006-12-19 18:02:03 -0700935void
936_mesa_init_shader_state(GLcontext * ctx)
Brian34ae99d2006-12-18 08:28:54 -0700937{
Brian5b01c5e2006-12-19 18:02:03 -0700938 ctx->Shader._FragmentShaderPresent = GL_FALSE;
939 ctx->Shader._VertexShaderPresent = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700940}