blob: 08fa9a7e233e1bf50dc14877d259856ee2892bca [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian3e4302f2007-05-09 08:04:32 -06003 * Version: 7.0
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"
Brian274ac7a2007-04-18 16:05:53 -060041#include "macros.h"
Brian34ae99d2006-12-18 08:28:54 -070042#include "program.h"
43#include "prog_parameter.h"
Brian3209c3e2007-01-09 17:49:24 -070044#include "prog_print.h"
45#include "prog_statevars.h"
Brian Paulade50832008-05-14 16:09:46 -060046#include "prog_uniform.h"
Brianc223c6b2007-07-04 13:15:20 -060047#include "shader/shader_api.h"
48#include "shader/slang/slang_compile.h"
49#include "shader/slang/slang_link.h"
Brian34ae99d2006-12-18 08:28:54 -070050
51
52
Brianf2923612006-12-20 09:56:44 -070053/**
54 * Allocate a new gl_shader_program object, initialize it.
55 */
56struct gl_shader_program *
57_mesa_new_shader_program(GLcontext *ctx, GLuint name)
58{
59 struct gl_shader_program *shProg;
60 shProg = CALLOC_STRUCT(gl_shader_program);
61 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060062 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070063 shProg->Name = name;
64 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070065 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070066 }
67 return shProg;
68}
69
70
Brianb9fbedd2007-03-26 09:23:44 -060071/**
Brian3c008a02007-04-12 15:22:32 -060072 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060073 */
Brianf2923612006-12-20 09:56:44 -070074void
Brian3c008a02007-04-12 15:22:32 -060075_mesa_clear_shader_program_data(GLcontext *ctx,
76 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070077{
Brian Paul8bdf5b62008-05-16 09:56:59 -060078 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
79 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070080
Brianf2923612006-12-20 09:56:44 -070081 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060082 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070083 shProg->Uniforms = NULL;
84 }
85
86 if (shProg->Varying) {
87 _mesa_free_parameter_list(shProg->Varying);
88 shProg->Varying = NULL;
89 }
90}
91
92
Brianb9fbedd2007-03-26 09:23:44 -060093/**
Brian3c008a02007-04-12 15:22:32 -060094 * Free all the data that hangs off a shader program object, but not the
95 * object itself.
96 */
97void
98_mesa_free_shader_program_data(GLcontext *ctx,
99 struct gl_shader_program *shProg)
100{
101 GLuint i;
102
Brianf3e8c322007-04-18 14:53:23 -0600103 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600104
105 _mesa_clear_shader_program_data(ctx, shProg);
106
Brian4b7c6fc2007-04-19 15:23:34 -0600107 if (shProg->Attributes) {
108 _mesa_free_parameter_list(shProg->Attributes);
109 shProg->Attributes = NULL;
110 }
111
Brian3c008a02007-04-12 15:22:32 -0600112 /* detach shaders */
113 for (i = 0; i < shProg->NumShaders; i++) {
114 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
115 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800116 shProg->NumShaders = 0;
117
Brian3c008a02007-04-12 15:22:32 -0600118 if (shProg->Shaders) {
119 _mesa_free(shProg->Shaders);
120 shProg->Shaders = NULL;
121 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100122
123 if (shProg->InfoLog) {
124 _mesa_free(shProg->InfoLog);
125 shProg->InfoLog = NULL;
126 }
Brian3c008a02007-04-12 15:22:32 -0600127}
128
129
130/**
Brianb9fbedd2007-03-26 09:23:44 -0600131 * Free/delete a shader program object.
132 */
Brianf2923612006-12-20 09:56:44 -0700133void
134_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
135{
136 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100137
Brianf2923612006-12-20 09:56:44 -0700138 _mesa_free(shProg);
139}
140
141
142/**
Brian3c008a02007-04-12 15:22:32 -0600143 * Set ptr to point to shProg.
144 * If ptr is pointing to another object, decrement its refcount (and delete
145 * if refcount hits zero).
146 * Then set ptr to point to shProg, incrementing its refcount.
147 */
148/* XXX this could be static */
149void
150_mesa_reference_shader_program(GLcontext *ctx,
151 struct gl_shader_program **ptr,
152 struct gl_shader_program *shProg)
153{
154 assert(ptr);
155 if (*ptr == shProg) {
156 /* no-op */
157 return;
158 }
159 if (*ptr) {
160 /* Unreference the old shader program */
161 GLboolean deleteFlag = GL_FALSE;
162 struct gl_shader_program *old = *ptr;
163
164 ASSERT(old->RefCount > 0);
165 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600166#if 0
167 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
168 (void *) old, old->Name, old->RefCount);
169#endif
Brian3c008a02007-04-12 15:22:32 -0600170 deleteFlag = (old->RefCount == 0);
171
172 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800173 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600174 _mesa_free_shader_program(ctx, old);
175 }
176
177 *ptr = NULL;
178 }
179 assert(!*ptr);
180
181 if (shProg) {
182 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600183#if 0
184 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
185 (void *) shProg, shProg->Name, shProg->RefCount);
186#endif
Brian3c008a02007-04-12 15:22:32 -0600187 *ptr = shProg;
188 }
189}
190
191
192/**
Brianf2923612006-12-20 09:56:44 -0700193 * Lookup a GLSL program object.
194 */
195struct gl_shader_program *
196_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
197{
198 struct gl_shader_program *shProg;
199 if (name) {
200 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800201 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700202 /* Note that both gl_shader and gl_shader_program objects are kept
203 * in the same hash table. Check the object's type to be sure it's
204 * what we're expecting.
205 */
Brianf3e8c322007-04-18 14:53:23 -0600206 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700207 return NULL;
208 }
209 return shProg;
210 }
211 return NULL;
212}
213
214
215/**
216 * Allocate a new gl_shader object, initialize it.
217 */
218struct gl_shader *
219_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
220{
221 struct gl_shader *shader;
222 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
223 shader = CALLOC_STRUCT(gl_shader);
224 if (shader) {
225 shader->Type = type;
226 shader->Name = name;
227 shader->RefCount = 1;
228 }
229 return shader;
230}
231
232
233void
234_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
235{
236 GLuint i;
237 if (sh->Source)
238 _mesa_free((void *) sh->Source);
239 if (sh->InfoLog)
240 _mesa_free(sh->InfoLog);
Brian Paul57e222d2008-05-14 12:10:45 -0600241 for (i = 0; i < sh->NumPrograms; i++)
242 _mesa_reference_program(ctx, &sh->Programs[i], NULL);
Brianf2923612006-12-20 09:56:44 -0700243 if (sh->Programs)
244 _mesa_free(sh->Programs);
245 _mesa_free(sh);
246}
247
248
249/**
Brian3c008a02007-04-12 15:22:32 -0600250 * Set ptr to point to sh.
251 * If ptr is pointing to another shader, decrement its refcount (and delete
252 * if refcount hits zero).
253 * Then set ptr to point to sh, incrementing its refcount.
254 */
255/* XXX this could be static */
256void
257_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
258 struct gl_shader *sh)
259{
260 assert(ptr);
261 if (*ptr == sh) {
262 /* no-op */
263 return;
264 }
265 if (*ptr) {
266 /* Unreference the old shader */
267 GLboolean deleteFlag = GL_FALSE;
268 struct gl_shader *old = *ptr;
269
270 ASSERT(old->RefCount > 0);
271 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600272 /*printf("SHADER DECR %p (%d) to %d\n",
273 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600274 deleteFlag = (old->RefCount == 0);
275
276 if (deleteFlag) {
277 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
278 _mesa_free_shader(ctx, old);
279 }
280
281 *ptr = NULL;
282 }
283 assert(!*ptr);
284
285 if (sh) {
286 /* reference new */
287 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600288 /*printf("SHADER INCR %p (%d) to %d\n",
289 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600290 *ptr = sh;
291 }
292}
293
294
295/**
Brianf2923612006-12-20 09:56:44 -0700296 * Lookup a GLSL shader object.
297 */
298struct gl_shader *
299_mesa_lookup_shader(GLcontext *ctx, GLuint name)
300{
301 if (name) {
302 struct gl_shader *sh = (struct gl_shader *)
303 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
304 /* Note that both gl_shader and gl_shader_program objects are kept
305 * in the same hash table. Check the object's type to be sure it's
306 * what we're expecting.
307 */
Brianf3e8c322007-04-18 14:53:23 -0600308 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700309 return NULL;
310 }
311 return sh;
312 }
313 return NULL;
314}
315
316
Brianfa4d0362007-02-26 18:33:50 -0700317/**
318 * Initialize context's shader state.
319 */
Brianf2923612006-12-20 09:56:44 -0700320void
321_mesa_init_shader_state(GLcontext * ctx)
322{
Brianfa4d0362007-02-26 18:33:50 -0700323 /* Device drivers may override these to control what kind of instructions
324 * are generated by the GLSL compiler.
325 */
326 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600327 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700328 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700329}
330
331
Brian5b01c5e2006-12-19 18:02:03 -0700332/**
Brian935f93f2007-03-24 16:20:02 -0600333 * Free the per-context shader-related state.
334 */
335void
336_mesa_free_shader_state(GLcontext *ctx)
337{
Brian3c008a02007-04-12 15:22:32 -0600338 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600339}
340
341
342/**
Brian5b01c5e2006-12-19 18:02:03 -0700343 * Copy string from <src> to <dst>, up to maxLength characters, returning
344 * length of <dst> in <length>.
345 * \param src the strings source
346 * \param maxLength max chars to copy
347 * \param length returns number of chars copied
348 * \param dst the string destination
349 */
350static void
351copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
352{
353 GLsizei len;
354 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
355 dst[len] = src[len];
356 if (maxLength > 0)
357 dst[len] = 0;
358 if (length)
359 *length = len;
360}
361
362
Brian5b01c5e2006-12-19 18:02:03 -0700363/**
Brian2761cfc2007-12-20 09:05:37 -0700364 * Return size (in floats) of the given GLSL type.
365 * See also _slang_sizeof_type_specifier().
366 */
367static GLint
368sizeof_glsl_type(GLenum type)
369{
370 switch (type) {
371 case GL_BOOL:
372 case GL_FLOAT:
373 case GL_INT:
374 return 1;
375 case GL_BOOL_VEC2:
376 case GL_FLOAT_VEC2:
377 case GL_INT_VEC2:
378 return 2;
379 case GL_BOOL_VEC3:
380 case GL_FLOAT_VEC3:
381 case GL_INT_VEC3:
382 return 3;
383 case GL_BOOL_VEC4:
384 case GL_FLOAT_VEC4:
385 case GL_INT_VEC4:
386 return 4;
387 case GL_FLOAT_MAT2:
388 return 8; /* 2 rows of 4, actually */
389 case GL_FLOAT_MAT3:
390 return 12; /* 3 rows of 4, actually */
391 case GL_FLOAT_MAT4:
392 return 16;
393 case GL_FLOAT_MAT2x3:
Bruce Merryeeb03fa2007-12-21 14:41:45 +0200394 return 8; /* 2 rows of 4, actually */
Brian2761cfc2007-12-20 09:05:37 -0700395 case GL_FLOAT_MAT2x4:
396 return 8;
397 case GL_FLOAT_MAT3x2:
398 return 12; /* 3 rows of 4, actually */
399 case GL_FLOAT_MAT3x4:
400 return 12;
401 case GL_FLOAT_MAT4x2:
402 return 16; /* 4 rows of 4, actually */
403 case GL_FLOAT_MAT4x3:
Bruce Merryeeb03fa2007-12-21 14:41:45 +0200404 return 16; /* 4 rows of 4, actually */
Brian2761cfc2007-12-20 09:05:37 -0700405 default:
406 return 0; /* error */
407 }
408}
409
410
411/**
Brian5b01c5e2006-12-19 18:02:03 -0700412 * Called via ctx->Driver.AttachShader()
413 */
414void
415_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
416{
Brian65a18442006-12-19 18:46:56 -0700417 struct gl_shader_program *shProg
418 = _mesa_lookup_shader_program(ctx, program);
419 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
Brian237b9852007-08-07 21:48:31 +0100420 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700421 GLuint i;
422
Brian65a18442006-12-19 18:46:56 -0700423 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700424 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700425 "glAttachShader(bad program or shader name)");
426 return;
427 }
428
Brian237b9852007-08-07 21:48:31 +0100429 n = shProg->NumShaders;
430
Brian5b01c5e2006-12-19 18:02:03 -0700431 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700432 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700433 /* already attached */
434 return;
Brian34ae99d2006-12-18 08:28:54 -0700435 }
436 }
Brian5b01c5e2006-12-19 18:02:03 -0700437
438 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700439 shProg->Shaders = (struct gl_shader **)
440 _mesa_realloc(shProg->Shaders,
441 n * sizeof(struct gl_shader *),
442 (n + 1) * sizeof(struct gl_shader *));
443 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700444 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
445 return;
446 }
447
448 /* append */
Brian3c008a02007-04-12 15:22:32 -0600449 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
450 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700451 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700452}
453
454
455void
456_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
457 const GLchar *name)
458{
Brian65a18442006-12-19 18:46:56 -0700459 struct gl_shader_program *shProg
460 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700461 const GLint size = -1; /* unknown size */
462 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700463
Brian65a18442006-12-19 18:46:56 -0700464 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700465 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700466 return;
467 }
468
Brian9e4bae92006-12-20 09:27:42 -0700469 if (!name)
470 return;
471
472 if (strncmp(name, "gl_", 3) == 0) {
473 _mesa_error(ctx, GL_INVALID_OPERATION,
474 "glBindAttribLocation(illegal name)");
475 return;
476 }
477
Brian9f660252007-04-11 09:00:56 -0600478 if (shProg->LinkStatus) {
479 /* get current index/location for the attribute */
480 oldIndex = _mesa_get_attrib_location(ctx, program, name);
481 }
482 else {
483 oldIndex = -1;
484 }
Brian3209c3e2007-01-09 17:49:24 -0700485
486 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700487 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700488 if (i < 0) {
489 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
490 }
491
Brian9f660252007-04-11 09:00:56 -0600492 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
493 /* If the index changed, need to search/replace references to that attribute
494 * in the vertex program.
495 */
Brian3209c3e2007-01-09 17:49:24 -0700496 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
497 }
Brian34ae99d2006-12-18 08:28:54 -0700498}
499
500
Brian5b01c5e2006-12-19 18:02:03 -0700501GLuint
502_mesa_create_shader(GLcontext *ctx, GLenum type)
503{
Brian65a18442006-12-19 18:46:56 -0700504 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700505 GLuint name;
506
507 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
508
509 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700510 case GL_FRAGMENT_SHADER:
511 case GL_VERTEX_SHADER:
512 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700513 break;
514 default:
515 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
516 return 0;
517 }
518
Brian65a18442006-12-19 18:46:56 -0700519 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700520
521 return name;
522}
523
524
525GLuint
526_mesa_create_program(GLcontext *ctx)
527{
528 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700529 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700530
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800531 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700532 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700533
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800534 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700535
Brian3c008a02007-04-12 15:22:32 -0600536 assert(shProg->RefCount == 1);
537
Brian5b01c5e2006-12-19 18:02:03 -0700538 return name;
539}
540
541
Brian3c008a02007-04-12 15:22:32 -0600542/**
543 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
544 * DeleteProgramARB.
545 */
Brian5b01c5e2006-12-19 18:02:03 -0700546void
547_mesa_delete_program2(GLcontext *ctx, GLuint name)
548{
Brian3c008a02007-04-12 15:22:32 -0600549 /*
550 * NOTE: deleting shaders/programs works a bit differently than
551 * texture objects (and buffer objects, etc). Shader/program
552 * handles/IDs exist in the hash table until the object is really
553 * deleted (refcount==0). With texture objects, the handle/ID is
554 * removed from the hash table in glDeleteTextures() while the tex
555 * object itself might linger until its refcount goes to zero.
556 */
Brian65a18442006-12-19 18:46:56 -0700557 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700558
Brian65a18442006-12-19 18:46:56 -0700559 shProg = _mesa_lookup_shader_program(ctx, name);
560 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700561 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700562 return;
563 }
564
Brian9e4bae92006-12-20 09:27:42 -0700565 shProg->DeletePending = GL_TRUE;
566
Brian3c008a02007-04-12 15:22:32 -0600567 /* effectively, decr shProg's refcount */
568 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700569}
570
571
572void
573_mesa_delete_shader(GLcontext *ctx, GLuint shader)
574{
Brian9e4bae92006-12-20 09:27:42 -0700575 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
576 if (!sh) {
577 return;
578 }
Brian5b01c5e2006-12-19 18:02:03 -0700579
Brian9e4bae92006-12-20 09:27:42 -0700580 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600581
582 /* effectively, decr sh's refcount */
583 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700584}
585
586
587void
588_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
589{
Brian65a18442006-12-19 18:46:56 -0700590 struct gl_shader_program *shProg
591 = _mesa_lookup_shader_program(ctx, program);
Brian237b9852007-08-07 21:48:31 +0100592 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700593 GLuint i, j;
594
Brian65a18442006-12-19 18:46:56 -0700595 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700596 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700597 "glDetachShader(bad program or shader name)");
598 return;
599 }
600
Brian237b9852007-08-07 21:48:31 +0100601 n = shProg->NumShaders;
602
Brian5b01c5e2006-12-19 18:02:03 -0700603 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700604 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700605 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600606 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700607
Brian3c008a02007-04-12 15:22:32 -0600608 /* derefernce */
609 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700610
Brian5b01c5e2006-12-19 18:02:03 -0700611 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700612 newList = (struct gl_shader **)
613 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700614 if (!newList) {
615 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
616 return;
617 }
618 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700619 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700620 }
621 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700622 newList[j++] = shProg->Shaders[i];
623 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700624
Brian65a18442006-12-19 18:46:56 -0700625 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600626 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600627
628#ifdef DEBUG
629 /* sanity check */
630 {
631 for (j = 0; j < shProg->NumShaders; j++) {
632 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
633 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
634 assert(shProg->Shaders[j]->RefCount > 0);
635 }
636 }
637#endif
638
Brian5b01c5e2006-12-19 18:02:03 -0700639 return;
640 }
641 }
642
643 /* not found */
Brian43975832007-01-04 08:21:09 -0700644 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700645 "glDetachShader(shader not found)");
646}
647
648
649void
650_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
651 GLsizei maxLength, GLsizei *length, GLint *size,
652 GLenum *type, GLchar *nameOut)
653{
654 static const GLenum vec_types[] = {
655 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
656 };
Brian65a18442006-12-19 18:46:56 -0700657 struct gl_shader_program *shProg
658 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700659 GLint sz;
660
Brian65a18442006-12-19 18:46:56 -0700661 if (!shProg) {
Brianaaa57412007-04-18 15:22:43 -0600662 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib");
Brian5b01c5e2006-12-19 18:02:03 -0700663 return;
664 }
665
Brian65a18442006-12-19 18:46:56 -0700666 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600667 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700668 return;
669 }
670
671 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700672 shProg->Attributes->Parameters[index].Name);
673 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700674 if (size)
Brian Paulade50832008-05-14 16:09:46 -0600675 *size = sz;
676 if (type)
677 *type = vec_types[sz]; /* XXX this is a temporary hack */
Brian5b01c5e2006-12-19 18:02:03 -0700678}
679
680
681/**
682 * Called via ctx->Driver.GetActiveUniform().
683 */
684void
685_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
686 GLsizei maxLength, GLsizei *length, GLint *size,
687 GLenum *type, GLchar *nameOut)
688{
Brian65a18442006-12-19 18:46:56 -0700689 struct gl_shader_program *shProg
690 = _mesa_lookup_shader_program(ctx, program);
Brian Paulade50832008-05-14 16:09:46 -0600691 const struct gl_program *prog;
692 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700693
Brian65a18442006-12-19 18:46:56 -0700694 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700695 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700696 return;
697 }
698
Brian Paulade50832008-05-14 16:09:46 -0600699 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700700 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
701 return;
702 }
703
Brian Paulade50832008-05-14 16:09:46 -0600704 progPos = shProg->Uniforms->Uniforms[index].VertPos;
705 if (progPos >= 0) {
706 prog = &shProg->VertexProgram->Base;
707 }
708 else {
709 progPos = shProg->Uniforms->Uniforms[index].FragPos;
710 if (progPos >= 0) {
711 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600712 }
713 }
714
Brian Paulade50832008-05-14 16:09:46 -0600715 if (!prog || progPos < 0)
716 return; /* should never happen */
717
718 if (nameOut)
719 copy_string(nameOut, maxLength, length,
720 prog->Parameters->Parameters[progPos].Name);
721 if (size)
722 *size = prog->Parameters->Parameters[progPos].Size;
723
724 if (type)
725 *type = prog->Parameters->Parameters[progPos].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700726}
727
728
729/**
730 * Called via ctx->Driver.GetAttachedShaders().
731 */
732void
733_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
734 GLsizei *count, GLuint *obj)
735{
Brian65a18442006-12-19 18:46:56 -0700736 struct gl_shader_program *shProg
737 = _mesa_lookup_shader_program(ctx, program);
738 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700739 GLint i;
Brian65a18442006-12-19 18:46:56 -0700740 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
741 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700742 }
743 if (count)
744 *count = i;
745 }
746 else {
Brian43975832007-01-04 08:21:09 -0700747 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700748 }
749}
750
751
752GLint
753_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
754 const GLchar *name)
755{
Brian65a18442006-12-19 18:46:56 -0700756 struct gl_shader_program *shProg
757 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700758
Brian65a18442006-12-19 18:46:56 -0700759 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700760 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700761 return -1;
762 }
763
Brian65a18442006-12-19 18:46:56 -0700764 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700765 _mesa_error(ctx, GL_INVALID_OPERATION,
766 "glGetAttribLocation(program not linked)");
767 return -1;
768 }
769
770 if (!name)
771 return -1;
772
Brian65a18442006-12-19 18:46:56 -0700773 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700774 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
775 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700776 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700777 }
778 }
779 return -1;
780}
781
782
783GLuint
784_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700785{
786#if 0
787 GET_CURRENT_CONTEXT(ctx);
788
789 switch (pname) {
790 case GL_PROGRAM_OBJECT_ARB:
791 {
Brian5b01c5e2006-12-19 18:02:03 -0700792 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700793
794 if (pro != NULL)
795 return (**pro)._container._generic.
796 GetName((struct gl2_generic_intf **) (pro));
797 }
798 break;
799 default:
800 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
801 }
802#endif
803 return 0;
804}
805
806
Brian5b01c5e2006-12-19 18:02:03 -0700807void
808_mesa_get_programiv(GLcontext *ctx, GLuint program,
809 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700810{
Brian65a18442006-12-19 18:46:56 -0700811 struct gl_shader_program *shProg
812 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700813
Brian65a18442006-12-19 18:46:56 -0700814 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700815 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700816 return;
817 }
818
Brian5b01c5e2006-12-19 18:02:03 -0700819 switch (pname) {
820 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700821 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700822 break;
823 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700824 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700825 break;
Brian5b01c5e2006-12-19 18:02:03 -0700826 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700827 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700828 break;
829 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600830 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700831 break;
832 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700833 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700834 break;
835 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700836 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700837 break;
838 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian274ac7a2007-04-18 16:05:53 -0600839 *params = _mesa_longest_parameter_name(shProg->Attributes,
840 PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700841 break;
842 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600843 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700844 break;
845 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600846 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600847 if (*params > 0)
848 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700849 break;
850 default:
Brian5b01c5e2006-12-19 18:02:03 -0700851 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
852 return;
Brian34ae99d2006-12-18 08:28:54 -0700853 }
Brian5b01c5e2006-12-19 18:02:03 -0700854}
Brian34ae99d2006-12-18 08:28:54 -0700855
Brian34ae99d2006-12-18 08:28:54 -0700856
Brian5b01c5e2006-12-19 18:02:03 -0700857void
858_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
859{
Brian65a18442006-12-19 18:46:56 -0700860 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700861
862 if (!shader) {
863 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
864 return;
865 }
Brian65a18442006-12-19 18:46:56 -0700866
Brian5b01c5e2006-12-19 18:02:03 -0700867 switch (pname) {
868 case GL_SHADER_TYPE:
869 *params = shader->Type;
870 break;
871 case GL_DELETE_STATUS:
872 *params = shader->DeletePending;
873 break;
874 case GL_COMPILE_STATUS:
875 *params = shader->CompileStatus;
876 break;
877 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600878 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700879 break;
880 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600881 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700882 break;
883 default:
884 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
885 return;
886 }
887}
888
889
890void
891_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
892 GLsizei *length, GLchar *infoLog)
893{
Brian65a18442006-12-19 18:46:56 -0700894 struct gl_shader_program *shProg
895 = _mesa_lookup_shader_program(ctx, program);
896 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700897 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
898 return;
899 }
Brian65a18442006-12-19 18:46:56 -0700900 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700901}
902
903
904void
905_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
906 GLsizei *length, GLchar *infoLog)
907{
Brian65a18442006-12-19 18:46:56 -0700908 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
909 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700910 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
911 return;
912 }
Brian65a18442006-12-19 18:46:56 -0700913 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700914}
915
916
917/**
918 * Called via ctx->Driver.GetShaderSource().
919 */
920void
921_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
922 GLsizei *length, GLchar *sourceOut)
923{
Brian65a18442006-12-19 18:46:56 -0700924 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
925 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700926 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
927 return;
928 }
Brian65a18442006-12-19 18:46:56 -0700929 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700930}
931
932
933/**
934 * Called via ctx->Driver.GetUniformfv().
935 */
936void
937_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
938 GLfloat *params)
939{
Brian65a18442006-12-19 18:46:56 -0700940 struct gl_shader_program *shProg
941 = _mesa_lookup_shader_program(ctx, program);
942 if (shProg) {
Brian Paulade50832008-05-14 16:09:46 -0600943 if (location < shProg->Uniforms->NumUniforms) {
944 GLint progPos, i;
945 const struct gl_program *prog;
946
947 progPos = shProg->Uniforms->Uniforms[location].VertPos;
948 if (progPos >= 0) {
949 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -0700950 }
Brian Paulade50832008-05-14 16:09:46 -0600951 else {
952 progPos = shProg->Uniforms->Uniforms[location].FragPos;
953 if (progPos >= 0) {
954 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +0200955 }
Brian Paulade50832008-05-14 16:09:46 -0600956 }
957
958 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
959 params[i] = prog->Parameters->ParameterValues[progPos][i];
960 }
Brian5b01c5e2006-12-19 18:02:03 -0700961 }
962 else {
963 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
964 }
965 }
966 else {
Brian43975832007-01-04 08:21:09 -0700967 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700968 }
969}
970
971
972/**
973 * Called via ctx->Driver.GetUniformLocation().
974 */
975GLint
976_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
977{
Brian71623982007-01-30 16:55:03 -0700978 struct gl_shader_program *shProg
979 = _mesa_lookup_shader_program(ctx, program);
Brian Paulade50832008-05-14 16:09:46 -0600980 if (!shProg)
981 return -1;
Brian5b01c5e2006-12-19 18:02:03 -0700982
Brian Paulade50832008-05-14 16:09:46 -0600983 return _mesa_lookup_uniform(shProg->Uniforms, name);
Brian5b01c5e2006-12-19 18:02:03 -0700984}
985
986
987GLboolean
988_mesa_is_program(GLcontext *ctx, GLuint name)
989{
Brian65a18442006-12-19 18:46:56 -0700990 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
991 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700992}
993
994
995GLboolean
996_mesa_is_shader(GLcontext *ctx, GLuint name)
997{
Brian65a18442006-12-19 18:46:56 -0700998 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700999 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001000}
1001
1002
1003
Brian5b01c5e2006-12-19 18:02:03 -07001004/**
1005 * Called via ctx->Driver.ShaderSource()
1006 */
1007void
1008_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001009{
Brian65a18442006-12-19 18:46:56 -07001010 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
1011 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001012 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -07001013 return;
1014 }
1015
Brian34ae99d2006-12-18 08:28:54 -07001016 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001017 if (sh->Source) {
1018 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001019 }
Brian65a18442006-12-19 18:46:56 -07001020 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001021 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001022}
1023
1024
Brian5b01c5e2006-12-19 18:02:03 -07001025/**
1026 * Called via ctx->Driver.CompileShader()
1027 */
1028void
1029_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001030{
Brian65a18442006-12-19 18:46:56 -07001031 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -07001032
Brian65a18442006-12-19 18:46:56 -07001033 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -07001034 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
1035 return;
1036 }
1037
Brian43975832007-01-04 08:21:09 -07001038 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001039}
1040
1041
Brian5b01c5e2006-12-19 18:02:03 -07001042/**
1043 * Called via ctx->Driver.LinkProgram()
1044 */
1045void
1046_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001047{
Brian65a18442006-12-19 18:46:56 -07001048 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001049
Brian65a18442006-12-19 18:46:56 -07001050 shProg = _mesa_lookup_shader_program(ctx, program);
1051 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001052 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001053 return;
1054 }
1055
Briandf43fb62008-05-06 23:08:51 -06001056 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1057
Brianc1771912007-02-16 09:56:19 -07001058 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001059}
1060
1061
1062/**
Brian5b01c5e2006-12-19 18:02:03 -07001063 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001064 */
Brian5b01c5e2006-12-19 18:02:03 -07001065void
1066_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001067{
Brian3c008a02007-04-12 15:22:32 -06001068 struct gl_shader_program *shProg;
1069
Brian00d63aa2007-02-03 11:35:02 -07001070 if (ctx->Shader.CurrentProgram &&
1071 ctx->Shader.CurrentProgram->Name == program) {
1072 /* no-op */
1073 return;
1074 }
1075
1076 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1077
Brian5b01c5e2006-12-19 18:02:03 -07001078 if (program) {
Brian65a18442006-12-19 18:46:56 -07001079 shProg = _mesa_lookup_shader_program(ctx, program);
1080 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001081 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -07001082 "glUseProgramObjectARB(programObj)");
1083 return;
1084 }
Brian5b01c5e2006-12-19 18:02:03 -07001085 }
1086 else {
Brian3c008a02007-04-12 15:22:32 -06001087 shProg = NULL;
1088 }
1089
1090 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001091}
Brian34ae99d2006-12-18 08:28:54 -07001092
Brian5b01c5e2006-12-19 18:02:03 -07001093
Brian Paulade50832008-05-14 16:09:46 -06001094
1095/**
1096 * Update the vertex and fragment program's TexturesUsed arrays.
1097 */
1098static void
1099update_textures_used(struct gl_program *prog)
1100{
1101 GLuint s;
1102
1103 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1104
1105 for (s = 0; s < MAX_SAMPLERS; s++) {
1106 if (prog->SamplersUsed & (1 << s)) {
1107 GLuint u = prog->SamplerUnits[s];
1108 GLuint t = prog->SamplerTargets[s];
1109 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1110 prog->TexturesUsed[u] |= (1 << t);
1111 }
1112 }
1113}
1114
1115
1116/**
1117 * Set the value of a program's uniform variable.
1118 * \param program the program whose uniform to update
1119 * \param location the location/index of the uniform
1120 * \param type the datatype of the uniform
1121 * \param count the number of uniforms to set
1122 * \param elems number of elements per uniform
1123 * \param values the new values
1124 */
1125static void
1126set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
1127 GLenum type, GLint count, GLint elems, const void *values)
1128{
1129 if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
1130 /* This controls which texture unit which is used by a sampler */
1131 GLuint texUnit, sampler;
1132
1133 /* data type for setting samplers must be int */
1134 if (type != GL_INT || count != 1) {
1135 _mesa_error(ctx, GL_INVALID_OPERATION,
1136 "glUniform(only glUniform1i can be used "
1137 "to set sampler uniforms)");
1138 return;
1139 }
1140
1141 sampler = (GLuint) program->Parameters->ParameterValues[location][0];
1142 texUnit = ((GLuint *) values)[0];
1143
1144 /* check that the sampler (tex unit index) is legal */
1145 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1146 _mesa_error(ctx, GL_INVALID_VALUE,
1147 "glUniform1(invalid sampler/tex unit index)");
1148 return;
1149 }
1150
1151 /* This maps a sampler to a texture unit: */
1152 program->SamplerUnits[sampler] = texUnit;
1153 update_textures_used(program);
1154
1155 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1156 }
1157 else {
1158 /* ordinary uniform variable */
1159 GLint k, i;
1160
1161 if (count * elems > program->Parameters->Parameters[location].Size) {
1162 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1163 return;
1164 }
1165
1166 for (k = 0; k < count; k++) {
1167 GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
1168 if (type == GL_INT ||
1169 type == GL_INT_VEC2 ||
1170 type == GL_INT_VEC3 ||
1171 type == GL_INT_VEC4) {
1172 const GLint *iValues = ((const GLint *) values) + k * elems;
1173 for (i = 0; i < elems; i++) {
1174 uniformVal[i] = (GLfloat) iValues[i];
1175 }
1176 }
1177 else {
1178 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1179 for (i = 0; i < elems; i++) {
1180 uniformVal[i] = fValues[i];
1181 }
1182 }
1183 }
1184 }
1185}
1186
1187
Brian5b01c5e2006-12-19 18:02:03 -07001188/**
1189 * Called via ctx->Driver.Uniform().
1190 */
1191void
1192_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1193 const GLvoid *values, GLenum type)
1194{
Brian3a8e2772006-12-20 17:19:16 -07001195 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001196 GLint elems;
Brian3a8e2772006-12-20 17:19:16 -07001197
1198 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001199 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001200 return;
1201 }
1202
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001203 if (location == -1)
1204 return; /* The standard specifies this as a no-op */
1205
Brian Paulade50832008-05-14 16:09:46 -06001206 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1207 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001208 return;
1209 }
1210
Brian52363952007-03-13 16:50:24 -06001211 if (count < 0) {
1212 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1213 return;
1214 }
1215
Brian98650bd2007-03-13 16:32:48 -06001216 switch (type) {
1217 case GL_FLOAT:
1218 case GL_INT:
1219 elems = 1;
1220 break;
1221 case GL_FLOAT_VEC2:
1222 case GL_INT_VEC2:
1223 elems = 2;
1224 break;
1225 case GL_FLOAT_VEC3:
1226 case GL_INT_VEC3:
1227 elems = 3;
1228 break;
1229 case GL_FLOAT_VEC4:
1230 case GL_INT_VEC4:
1231 elems = 4;
1232 break;
1233 default:
1234 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1235 return;
Brian89dc4852007-01-04 14:35:44 -07001236 }
Brian98650bd2007-03-13 16:32:48 -06001237
Brian Paulade50832008-05-14 16:09:46 -06001238 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001239
Brian Paulade50832008-05-14 16:09:46 -06001240 /* A uniform var may be used by both a vertex shader and a fragment
1241 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001242 */
Brian Paulade50832008-05-14 16:09:46 -06001243 if (shProg->VertexProgram) {
1244 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1245 if (loc >= 0) {
1246 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1247 loc, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001248 }
Brian5b01c5e2006-12-19 18:02:03 -07001249 }
Brian5cf73262007-01-05 16:02:45 -07001250
Brian Paulade50832008-05-14 16:09:46 -06001251 if (shProg->FragmentProgram) {
1252 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1253 if (loc >= 0) {
1254 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1255 loc, type, count, elems, values);
1256 }
1257 }
1258}
1259
1260
1261static void
1262set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
1263 GLuint location, GLuint rows, GLuint cols,
1264 GLboolean transpose, const GLfloat *values)
1265{
1266 /*
1267 * Note: the _columns_ of a matrix are stored in program registers, not
1268 * the rows.
1269 */
1270 /* XXXX need to test 3x3 and 2x2 matrices... */
1271 if (transpose) {
1272 GLuint row, col;
1273 for (col = 0; col < cols; col++) {
1274 GLfloat *v = program->Parameters->ParameterValues[location + col];
1275 for (row = 0; row < rows; row++) {
1276 v[row] = values[row * cols + col];
1277 }
1278 }
1279 }
1280 else {
1281 GLuint row, col;
1282 for (col = 0; col < cols; col++) {
1283 GLfloat *v = program->Parameters->ParameterValues[location + col];
1284 for (row = 0; row < rows; row++) {
1285 v[row] = values[col * rows + row];
1286 }
1287 }
Brian5cf73262007-01-05 16:02:45 -07001288 }
Brian34ae99d2006-12-18 08:28:54 -07001289}
1290
1291
1292/**
Brian5b01c5e2006-12-19 18:02:03 -07001293 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -07001294 */
Brian5b01c5e2006-12-19 18:02:03 -07001295void
1296_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1297 GLenum matrixType, GLint location, GLsizei count,
1298 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001299{
Brian3a8e2772006-12-20 17:19:16 -07001300 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001301
Brian3a8e2772006-12-20 17:19:16 -07001302 if (!shProg || !shProg->LinkStatus) {
1303 _mesa_error(ctx, GL_INVALID_OPERATION,
1304 "glUniformMatrix(program not linked)");
1305 return;
1306 }
Brian Paulade50832008-05-14 16:09:46 -06001307
Bruce Merry89b80322007-12-21 15:20:17 +02001308 if (location == -1)
1309 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001310
1311 if (location < 0 || location >= shProg->Uniforms->NumUniforms) {
1312 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001313 return;
1314 }
Brian34ae99d2006-12-18 08:28:54 -07001315 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001316 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001317 return;
1318 }
1319
1320 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1321
Brian Paulade50832008-05-14 16:09:46 -06001322 if (shProg->VertexProgram) {
1323 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1324 if (loc >= 0) {
1325 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
1326 loc, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001327 }
Brian Paulade50832008-05-14 16:09:46 -06001328 }
1329
1330 if (shProg->FragmentProgram) {
1331 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1332 if (loc >= 0) {
1333 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
1334 loc, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001335 }
Brian34ae99d2006-12-18 08:28:54 -07001336 }
1337}
1338
1339
Brian5b01c5e2006-12-19 18:02:03 -07001340void
1341_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001342{
Brian65a18442006-12-19 18:46:56 -07001343 struct gl_shader_program *shProg;
1344 shProg = _mesa_lookup_shader_program(ctx, program);
1345 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001346 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001347 return;
1348 }
Brian5b01c5e2006-12-19 18:02:03 -07001349 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001350 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001351
Brian5b01c5e2006-12-19 18:02:03 -07001352 /* From the GL spec:
1353 any two active samplers in the current program object are of
1354 different types, but refer to the same texture image unit,
1355
1356 any active sampler in the current program object refers to a texture
1357 image unit where fixed-function fragment processing accesses a
1358 texture target that does not match the sampler type, or
1359
1360 the sum of the number of active samplers in the program and the
1361 number of texture image units enabled for fixed-function fragment
1362 processing exceeds the combined limit on the total number of texture
1363 image units allowed.
1364 */
Brian34ae99d2006-12-18 08:28:54 -07001365}