blob: d1b0e21b9494ffeb9fad60fc73efb494c9824edd [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"
Brian3209c3e2007-01-09 17:49:24 -070043#include "prog_print.h"
44#include "prog_statevars.h"
Brian34ae99d2006-12-18 08:28:54 -070045#include "shader_api.h"
46
47#include "slang_compile.h"
48#include "slang_link.h"
49
50
51
Brianf2923612006-12-20 09:56:44 -070052/**
53 * Allocate a new gl_shader_program object, initialize it.
54 */
55struct gl_shader_program *
56_mesa_new_shader_program(GLcontext *ctx, GLuint name)
57{
58 struct gl_shader_program *shProg;
59 shProg = CALLOC_STRUCT(gl_shader_program);
60 if (shProg) {
61 shProg->Type = GL_SHADER_PROGRAM;
62 shProg->Name = name;
63 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070064 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070065 }
66 return shProg;
67}
68
69
70void
71_mesa_free_shader_program_data(GLcontext *ctx,
72 struct gl_shader_program *shProg)
73{
74 assert(shProg->Type == GL_SHADER_PROGRAM);
75
76 if (shProg->VertexProgram) {
77 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
78 /* to prevent a double-free in the next call */
79 shProg->VertexProgram->Base.Parameters = NULL;
80 }
81 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
82 shProg->VertexProgram = NULL;
83 }
84
85 if (shProg->FragmentProgram) {
86 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
87 /* to prevent a double-free in the next call */
88 shProg->FragmentProgram->Base.Parameters = NULL;
89 }
90 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
91 shProg->FragmentProgram = NULL;
92 }
93
94
95 if (shProg->Uniforms) {
96 _mesa_free_parameter_list(shProg->Uniforms);
97 shProg->Uniforms = NULL;
98 }
99
100 if (shProg->Varying) {
101 _mesa_free_parameter_list(shProg->Varying);
102 shProg->Varying = NULL;
103 }
104}
105
106
107
108void
109_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
110{
111 _mesa_free_shader_program_data(ctx, shProg);
112 _mesa_free(shProg);
113}
114
115
116/**
117 * Lookup a GLSL program object.
118 */
119struct gl_shader_program *
120_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
121{
122 struct gl_shader_program *shProg;
123 if (name) {
124 shProg = (struct gl_shader_program *)
125 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
126 /* Note that both gl_shader and gl_shader_program objects are kept
127 * in the same hash table. Check the object's type to be sure it's
128 * what we're expecting.
129 */
130 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
131 return NULL;
132 }
133 return shProg;
134 }
135 return NULL;
136}
137
138
139/**
140 * Allocate a new gl_shader object, initialize it.
141 */
142struct gl_shader *
143_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
144{
145 struct gl_shader *shader;
146 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
147 shader = CALLOC_STRUCT(gl_shader);
148 if (shader) {
149 shader->Type = type;
150 shader->Name = name;
151 shader->RefCount = 1;
152 }
153 return shader;
154}
155
156
157void
158_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
159{
160 GLuint i;
161 if (sh->Source)
162 _mesa_free((void *) sh->Source);
163 if (sh->InfoLog)
164 _mesa_free(sh->InfoLog);
165 for (i = 0; i < sh->NumPrograms; i++) {
166 assert(sh->Programs[i]);
167 _mesa_delete_program(ctx, sh->Programs[i]);
168 }
169 if (sh->Programs)
170 _mesa_free(sh->Programs);
171 _mesa_free(sh);
172}
173
174
175/**
176 * Lookup a GLSL shader object.
177 */
178struct gl_shader *
179_mesa_lookup_shader(GLcontext *ctx, GLuint name)
180{
181 if (name) {
182 struct gl_shader *sh = (struct gl_shader *)
183 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
184 /* Note that both gl_shader and gl_shader_program objects are kept
185 * in the same hash table. Check the object's type to be sure it's
186 * what we're expecting.
187 */
188 if (sh && sh->Type == GL_SHADER_PROGRAM) {
189 assert(sh->Type == GL_VERTEX_SHADER ||
190 sh->Type == GL_FRAGMENT_SHADER);
191 return NULL;
192 }
193 return sh;
194 }
195 return NULL;
196}
197
198
199void
200_mesa_init_shader_state(GLcontext * ctx)
201{
202 ctx->Shader._FragmentShaderPresent = GL_FALSE;
203 ctx->Shader._VertexShaderPresent = GL_FALSE;
204}
205
206
207
Brian34ae99d2006-12-18 08:28:54 -0700208
Brian5b01c5e2006-12-19 18:02:03 -0700209
210/**
211 * Copy string from <src> to <dst>, up to maxLength characters, returning
212 * length of <dst> in <length>.
213 * \param src the strings source
214 * \param maxLength max chars to copy
215 * \param length returns number of chars copied
216 * \param dst the string destination
217 */
218static void
219copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
220{
221 GLsizei len;
222 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
223 dst[len] = src[len];
224 if (maxLength > 0)
225 dst[len] = 0;
226 if (length)
227 *length = len;
228}
229
230
231
232
233/**
234 * Called via ctx->Driver.AttachShader()
235 */
236void
237_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
238{
Brian65a18442006-12-19 18:46:56 -0700239 struct gl_shader_program *shProg
240 = _mesa_lookup_shader_program(ctx, program);
241 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
242 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700243 GLuint i;
244
Brian65a18442006-12-19 18:46:56 -0700245 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700246 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700247 "glAttachShader(bad program or shader name)");
248 return;
249 }
250
251 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700252 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700253 /* already attached */
254 return;
Brian34ae99d2006-12-18 08:28:54 -0700255 }
256 }
Brian5b01c5e2006-12-19 18:02:03 -0700257
258 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700259 shProg->Shaders = (struct gl_shader **)
260 _mesa_realloc(shProg->Shaders,
261 n * sizeof(struct gl_shader *),
262 (n + 1) * sizeof(struct gl_shader *));
263 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700264 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
265 return;
266 }
267
268 /* append */
Brian65a18442006-12-19 18:46:56 -0700269 shProg->Shaders[n] = sh;
270 sh->RefCount++;
271 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700272}
273
274
275void
276_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
277 const GLchar *name)
278{
Brian65a18442006-12-19 18:46:56 -0700279 struct gl_shader_program *shProg
280 = _mesa_lookup_shader_program(ctx, program);
Brian3209c3e2007-01-09 17:49:24 -0700281 GLint i;
282 GLint oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700283
Brian65a18442006-12-19 18:46:56 -0700284 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700285 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700286 return;
287 }
288
Brian9e4bae92006-12-20 09:27:42 -0700289 if (!name)
290 return;
291
292 if (strncmp(name, "gl_", 3) == 0) {
293 _mesa_error(ctx, GL_INVALID_OPERATION,
294 "glBindAttribLocation(illegal name)");
295 return;
296 }
297
Brian3209c3e2007-01-09 17:49:24 -0700298 oldIndex = _mesa_get_attrib_location(ctx, program, name);
299
300 /* this will replace the current value if it's already in the list */
301 i = _mesa_add_attribute(shProg->Attributes, name, index);
302 if (i < 0) {
303 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
304 }
305
306 if (shProg->VertexProgram && oldIndex >= 0) {
307 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
308 }
309
310 printf("===== post BindAttrib:\n");
311 _mesa_print_program(&shProg->VertexProgram->Base);
312
Brian34ae99d2006-12-18 08:28:54 -0700313}
314
315
Brian5b01c5e2006-12-19 18:02:03 -0700316GLuint
317_mesa_create_shader(GLcontext *ctx, GLenum type)
318{
Brian65a18442006-12-19 18:46:56 -0700319 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700320 GLuint name;
321
322 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
323
324 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700325 case GL_FRAGMENT_SHADER:
326 case GL_VERTEX_SHADER:
327 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700328 break;
329 default:
330 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
331 return 0;
332 }
333
Brian65a18442006-12-19 18:46:56 -0700334 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700335
336 return name;
337}
338
339
340GLuint
341_mesa_create_program(GLcontext *ctx)
342{
343 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700344 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700345
Brian65a18442006-12-19 18:46:56 -0700346 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
347 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700348
Brian65a18442006-12-19 18:46:56 -0700349 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700350
351 return name;
352}
353
354
355void
356_mesa_delete_program2(GLcontext *ctx, GLuint name)
357{
Brian65a18442006-12-19 18:46:56 -0700358 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700359
Brian65a18442006-12-19 18:46:56 -0700360 shProg = _mesa_lookup_shader_program(ctx, name);
361 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700362 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700363 return;
364 }
365
Brian9e4bae92006-12-20 09:27:42 -0700366 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700367 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700368
369 shProg->DeletePending = GL_TRUE;
370
371 /* decrement refcount, delete if zero */
372 shProg->RefCount--;
373 if (shProg->RefCount <= 0) {
374 _mesa_free_shader_program(ctx, shProg);
375 }
Brian5b01c5e2006-12-19 18:02:03 -0700376}
377
378
379void
380_mesa_delete_shader(GLcontext *ctx, GLuint shader)
381{
Brian9e4bae92006-12-20 09:27:42 -0700382 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
383 if (!sh) {
384 return;
385 }
Brian5b01c5e2006-12-19 18:02:03 -0700386
Brian9e4bae92006-12-20 09:27:42 -0700387 sh->DeletePending = GL_TRUE;
388 sh->RefCount--;
389 if (sh->RefCount <= 0) {
390 _mesa_free_shader(ctx, sh);
391 }
Brian5b01c5e2006-12-19 18:02:03 -0700392}
393
394
395void
396_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
397{
Brian65a18442006-12-19 18:46:56 -0700398 struct gl_shader_program *shProg
399 = _mesa_lookup_shader_program(ctx, program);
400 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700401 GLuint i, j;
402
Brian65a18442006-12-19 18:46:56 -0700403 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700404 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700405 "glDetachShader(bad program or shader name)");
406 return;
407 }
408
409 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700410 if (shProg->Shaders[i]->Name == shader) {
411 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700412 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700413
414 shProg->Shaders[i]->RefCount--;
415
Brian5b01c5e2006-12-19 18:02:03 -0700416 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700417 newList = (struct gl_shader **)
418 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700419 if (!newList) {
420 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
421 return;
422 }
423 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700424 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700425 }
426 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700427 newList[j++] = shProg->Shaders[i];
428 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700429
430 /* XXX refcounting! */
431
Brian65a18442006-12-19 18:46:56 -0700432 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700433 return;
434 }
435 }
436
437 /* not found */
Brian43975832007-01-04 08:21:09 -0700438 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700439 "glDetachShader(shader not found)");
440}
441
442
443void
444_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
445 GLsizei maxLength, GLsizei *length, GLint *size,
446 GLenum *type, GLchar *nameOut)
447{
448 static const GLenum vec_types[] = {
449 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
450 };
Brian65a18442006-12-19 18:46:56 -0700451 struct gl_shader_program *shProg
452 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700453 GLint sz;
454
Brian65a18442006-12-19 18:46:56 -0700455 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700456 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700457 return;
458 }
459
Brian65a18442006-12-19 18:46:56 -0700460 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700461 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
462 return;
463 }
464
465 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700466 shProg->Attributes->Parameters[index].Name);
467 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700468 if (size)
469 *size = sz;
470 if (type)
471 *type = vec_types[sz]; /* XXX this is a temporary hack */
472}
473
474
475/**
476 * Called via ctx->Driver.GetActiveUniform().
477 */
478void
479_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
480 GLsizei maxLength, GLsizei *length, GLint *size,
481 GLenum *type, GLchar *nameOut)
482{
483 static const GLenum vec_types[] = {
484 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
485 };
Brian65a18442006-12-19 18:46:56 -0700486 struct gl_shader_program *shProg
487 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700488 GLint sz;
489
Brian65a18442006-12-19 18:46:56 -0700490 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700491 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700492 return;
493 }
494
Brian65a18442006-12-19 18:46:56 -0700495 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700496 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
497 return;
498 }
499
500 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700501 shProg->Uniforms->Parameters[index].Name);
502 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700503 if (size)
504 *size = sz;
505 if (type)
506 *type = vec_types[sz]; /* XXX this is a temporary hack */
507}
508
509
510/**
511 * Called via ctx->Driver.GetAttachedShaders().
512 */
513void
514_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
515 GLsizei *count, GLuint *obj)
516{
Brian65a18442006-12-19 18:46:56 -0700517 struct gl_shader_program *shProg
518 = _mesa_lookup_shader_program(ctx, program);
519 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700520 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700521 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
522 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700523 }
524 if (count)
525 *count = i;
526 }
527 else {
Brian43975832007-01-04 08:21:09 -0700528 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700529 }
530}
531
532
533GLint
534_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
535 const GLchar *name)
536{
Brian65a18442006-12-19 18:46:56 -0700537 struct gl_shader_program *shProg
538 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700539
Brian65a18442006-12-19 18:46:56 -0700540 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700541 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700542 return -1;
543 }
544
Brian65a18442006-12-19 18:46:56 -0700545 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700546 _mesa_error(ctx, GL_INVALID_OPERATION,
547 "glGetAttribLocation(program not linked)");
548 return -1;
549 }
550
551 if (!name)
552 return -1;
553
Brian65a18442006-12-19 18:46:56 -0700554 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700555 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
556 if (i >= 0) {
557 return shProg->Attributes->Parameters[i].StateIndexes[1];
Brian5b01c5e2006-12-19 18:02:03 -0700558 }
559 }
560 return -1;
561}
562
563
564GLuint
565_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700566{
567#if 0
568 GET_CURRENT_CONTEXT(ctx);
569
570 switch (pname) {
571 case GL_PROGRAM_OBJECT_ARB:
572 {
Brian5b01c5e2006-12-19 18:02:03 -0700573 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700574
575 if (pro != NULL)
576 return (**pro)._container._generic.
577 GetName((struct gl2_generic_intf **) (pro));
578 }
579 break;
580 default:
581 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
582 }
583#endif
584 return 0;
585}
586
587
Brian5b01c5e2006-12-19 18:02:03 -0700588void
589_mesa_get_programiv(GLcontext *ctx, GLuint program,
590 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700591{
Brian65a18442006-12-19 18:46:56 -0700592 struct gl_shader_program *shProg
593 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700594
Brian65a18442006-12-19 18:46:56 -0700595 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700596 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700597 return;
598 }
599
Brian5b01c5e2006-12-19 18:02:03 -0700600 switch (pname) {
601 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700602 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700603 break;
604 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700605 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700606 break;
Brian5b01c5e2006-12-19 18:02:03 -0700607 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700608 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700609 break;
610 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700611 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700612 break;
613 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700614 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700615 break;
616 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700617 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700618 break;
619 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700620 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700621 break;
622 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700623 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700624 break;
625 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700626 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700627 break;
628 default:
Brian5b01c5e2006-12-19 18:02:03 -0700629 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
630 return;
Brian34ae99d2006-12-18 08:28:54 -0700631 }
Brian5b01c5e2006-12-19 18:02:03 -0700632}
Brian34ae99d2006-12-18 08:28:54 -0700633
Brian34ae99d2006-12-18 08:28:54 -0700634
Brian5b01c5e2006-12-19 18:02:03 -0700635void
636_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
637{
Brian65a18442006-12-19 18:46:56 -0700638 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700639
640 if (!shader) {
641 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
642 return;
643 }
Brian65a18442006-12-19 18:46:56 -0700644
Brian5b01c5e2006-12-19 18:02:03 -0700645 switch (pname) {
646 case GL_SHADER_TYPE:
647 *params = shader->Type;
648 break;
649 case GL_DELETE_STATUS:
650 *params = shader->DeletePending;
651 break;
652 case GL_COMPILE_STATUS:
653 *params = shader->CompileStatus;
654 break;
655 case GL_INFO_LOG_LENGTH:
656 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
657 break;
658 case GL_SHADER_SOURCE_LENGTH:
659 *params = shader->Source ? strlen((char *) shader->Source) : 0;
660 break;
661 default:
662 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
663 return;
664 }
665}
666
667
668void
669_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
670 GLsizei *length, GLchar *infoLog)
671{
Brian65a18442006-12-19 18:46:56 -0700672 struct gl_shader_program *shProg
673 = _mesa_lookup_shader_program(ctx, program);
674 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700675 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
676 return;
677 }
Brian65a18442006-12-19 18:46:56 -0700678 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700679}
680
681
682void
683_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
684 GLsizei *length, GLchar *infoLog)
685{
Brian65a18442006-12-19 18:46:56 -0700686 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
687 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700688 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
689 return;
690 }
Brian65a18442006-12-19 18:46:56 -0700691 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700692}
693
694
695/**
696 * Called via ctx->Driver.GetShaderSource().
697 */
698void
699_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
700 GLsizei *length, GLchar *sourceOut)
701{
Brian65a18442006-12-19 18:46:56 -0700702 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
703 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700704 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
705 return;
706 }
Brian65a18442006-12-19 18:46:56 -0700707 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700708}
709
710
711/**
712 * Called via ctx->Driver.GetUniformfv().
713 */
714void
715_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
716 GLfloat *params)
717{
Brian65a18442006-12-19 18:46:56 -0700718 struct gl_shader_program *shProg
719 = _mesa_lookup_shader_program(ctx, program);
720 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700721 GLuint i;
Brian65a18442006-12-19 18:46:56 -0700722 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
723 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
724 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700725 }
726 }
727 else {
728 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
729 }
730 }
731 else {
Brian43975832007-01-04 08:21:09 -0700732 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700733 }
734}
735
736
737/**
738 * Called via ctx->Driver.GetUniformLocation().
739 */
740GLint
741_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
742{
743 if (ctx->Shader.CurrentProgram) {
Brian65a18442006-12-19 18:46:56 -0700744 const struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian5b01c5e2006-12-19 18:02:03 -0700745 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700746 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700747 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700748 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700749 /* XXX this is a temporary simplification / short-cut.
750 * We need to handle things like "e.c[0].b" as seen in the
751 * GLSL orange book, page 189.
752 */
Brian5cf73262007-01-05 16:02:45 -0700753 if ((u->Type == PROGRAM_UNIFORM ||
754 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700755 return loc;
756 }
757 }
758 }
759 return -1;
760
761}
762
763
764GLboolean
765_mesa_is_program(GLcontext *ctx, GLuint name)
766{
Brian65a18442006-12-19 18:46:56 -0700767 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
768 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700769}
770
771
772GLboolean
773_mesa_is_shader(GLcontext *ctx, GLuint name)
774{
Brian65a18442006-12-19 18:46:56 -0700775 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700776 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700777}
778
779
780
Brian5b01c5e2006-12-19 18:02:03 -0700781/**
782 * Called via ctx->Driver.ShaderSource()
783 */
784void
785_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700786{
Brian65a18442006-12-19 18:46:56 -0700787 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
788 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700789 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700790 return;
791 }
792
Brian34ae99d2006-12-18 08:28:54 -0700793 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700794 if (sh->Source) {
795 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700796 }
Brian65a18442006-12-19 18:46:56 -0700797 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700798 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700799}
800
801
Brian5b01c5e2006-12-19 18:02:03 -0700802/**
803 * Called via ctx->Driver.CompileShader()
804 */
805void
806_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700807{
Brian65a18442006-12-19 18:46:56 -0700808 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700809
Brian65a18442006-12-19 18:46:56 -0700810 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700811 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
812 return;
813 }
814
Brian43975832007-01-04 08:21:09 -0700815 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700816}
817
818
Brian5b01c5e2006-12-19 18:02:03 -0700819/**
820 * Called via ctx->Driver.LinkProgram()
821 */
822void
823_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700824{
Brian65a18442006-12-19 18:46:56 -0700825 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700826
Brian65a18442006-12-19 18:46:56 -0700827 shProg = _mesa_lookup_shader_program(ctx, program);
828 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700829 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700830 return;
831 }
832
Brian65a18442006-12-19 18:46:56 -0700833 _slang_link2(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700834}
835
836
837/**
Brian5b01c5e2006-12-19 18:02:03 -0700838 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700839 */
Brian5b01c5e2006-12-19 18:02:03 -0700840void
841_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700842{
Brian9e4bae92006-12-20 09:27:42 -0700843 /* unbind old */
844 if (ctx->Shader.CurrentProgram) {
845 ctx->Shader.CurrentProgram->RefCount--;
846 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
847 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
848 }
849 ctx->Shader.CurrentProgram = NULL;
850 }
851
Brian5b01c5e2006-12-19 18:02:03 -0700852 /* XXXX need to handle reference counting here! */
853 if (program) {
Brian65a18442006-12-19 18:46:56 -0700854 struct gl_shader_program *shProg;
855 shProg = _mesa_lookup_shader_program(ctx, program);
856 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700857 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700858 "glUseProgramObjectARB(programObj)");
859 return;
860 }
Brian65a18442006-12-19 18:46:56 -0700861 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700862 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700863 }
864 else {
865 /* don't use a shader program */
866 ctx->Shader.CurrentProgram = NULL;
867 }
868}
Brian34ae99d2006-12-18 08:28:54 -0700869
Brian5b01c5e2006-12-19 18:02:03 -0700870
871/**
872 * Called via ctx->Driver.Uniform().
873 */
874void
875_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
876 const GLvoid *values, GLenum type)
877{
Brian3a8e2772006-12-20 17:19:16 -0700878 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian89dc4852007-01-04 14:35:44 -0700879 GLfloat *uniformVal;
Brian3a8e2772006-12-20 17:19:16 -0700880
881 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700882 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700883 return;
884 }
885
886 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
887 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
888 return;
889 }
890
891 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
892
Brian89dc4852007-01-04 14:35:44 -0700893 uniformVal = shProg->Uniforms->ParameterValues[location];
Brian3a8e2772006-12-20 17:19:16 -0700894
Brian89dc4852007-01-04 14:35:44 -0700895 if (type == GL_INT ||
896 type == GL_INT_VEC2 ||
897 type == GL_INT_VEC3 ||
898 type == GL_INT_VEC4) {
899 const GLint *iValues = (const GLint *) values;
900 switch (type) {
901 case GL_INT_VEC4:
902 uniformVal[3] = (GLfloat) iValues[3];
903 /* fall-through */
904 case GL_INT_VEC3:
905 uniformVal[2] = (GLfloat) iValues[2];
906 /* fall-through */
907 case GL_INT_VEC2:
908 uniformVal[1] = (GLfloat) iValues[1];
909 /* fall-through */
910 case GL_INT:
911 uniformVal[0] = (GLfloat) iValues[0];
912 break;
913 default:
914 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
915 return;
916 }
917 }
918 else {
919 const GLfloat *fValues = (const GLfloat *) values; /* XXX */
920 switch (type) {
921 case GL_FLOAT_VEC4:
922 uniformVal[3] = fValues[3];
923 /* fall-through */
924 case GL_FLOAT_VEC3:
925 uniformVal[2] = fValues[2];
926 /* fall-through */
927 case GL_FLOAT_VEC2:
928 uniformVal[1] = fValues[1];
929 /* fall-through */
930 case GL_FLOAT:
931 uniformVal[0] = fValues[0];
932 break;
933 default:
934 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
935 return;
936 }
Brian5b01c5e2006-12-19 18:02:03 -0700937 }
Brian5cf73262007-01-05 16:02:45 -0700938
939 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
940 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
941 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
942 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
943 }
Brian34ae99d2006-12-18 08:28:54 -0700944}
945
946
947/**
Brian5b01c5e2006-12-19 18:02:03 -0700948 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -0700949 */
Brian5b01c5e2006-12-19 18:02:03 -0700950void
951_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
952 GLenum matrixType, GLint location, GLsizei count,
953 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -0700954{
Brian3a8e2772006-12-20 17:19:16 -0700955 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
956 if (!shProg || !shProg->LinkStatus) {
957 _mesa_error(ctx, GL_INVALID_OPERATION,
958 "glUniformMatrix(program not linked)");
959 return;
960 }
961 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
962 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
963 return;
964 }
Brian34ae99d2006-12-18 08:28:54 -0700965 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -0700966 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -0700967 return;
968 }
969
970 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
971
Brian3a8e2772006-12-20 17:19:16 -0700972 /*
973 * Note: the _columns_ of a matrix are stored in program registers, not
974 * the rows.
975 */
976 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -0700977 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -0700978 GLuint row, col;
979 for (col = 0; col < cols; col++) {
980 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
981 for (row = 0; row < rows; row++) {
982 v[row] = values[col * rows + row];
Brian34ae99d2006-12-18 08:28:54 -0700983 }
Brian34ae99d2006-12-18 08:28:54 -0700984 }
Brian34ae99d2006-12-18 08:28:54 -0700985 }
986 else {
Brian3a8e2772006-12-20 17:19:16 -0700987 GLuint row, col;
988 for (col = 0; col < cols; col++) {
989 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
990 for (row = 0; row < rows; row++) {
991 v[row] = values[row * cols + col];
992 }
993 }
Brian34ae99d2006-12-18 08:28:54 -0700994 }
995}
996
997
Brian5b01c5e2006-12-19 18:02:03 -0700998void
999_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001000{
Brian65a18442006-12-19 18:46:56 -07001001 struct gl_shader_program *shProg;
1002 shProg = _mesa_lookup_shader_program(ctx, program);
1003 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001004 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001005 return;
1006 }
Brian5b01c5e2006-12-19 18:02:03 -07001007 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001008 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001009
Brian5b01c5e2006-12-19 18:02:03 -07001010 /* From the GL spec:
1011 any two active samplers in the current program object are of
1012 different types, but refer to the same texture image unit,
1013
1014 any active sampler in the current program object refers to a texture
1015 image unit where fixed-function fragment processing accesses a
1016 texture target that does not match the sampler type, or
1017
1018 the sum of the number of active samplers in the program and the
1019 number of texture image units enabled for fixed-function fragment
1020 processing exceeds the combined limit on the total number of texture
1021 image units allowed.
1022 */
Brian34ae99d2006-12-18 08:28:54 -07001023}