blob: 1831d0fb2e741f3697ec34009fed52cbe7e44cf3 [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
Brianb9fbedd2007-03-26 09:23:44 -060070/**
71 * Free the data that hangs off a shader program object, but not the object
72 * itself.
73 */
Brianf2923612006-12-20 09:56:44 -070074void
75_mesa_free_shader_program_data(GLcontext *ctx,
76 struct gl_shader_program *shProg)
77{
78 assert(shProg->Type == GL_SHADER_PROGRAM);
79
80 if (shProg->VertexProgram) {
81 if (shProg->VertexProgram->Base.Parameters == shProg->Uniforms) {
82 /* to prevent a double-free in the next call */
83 shProg->VertexProgram->Base.Parameters = NULL;
84 }
85 _mesa_delete_program(ctx, &shProg->VertexProgram->Base);
86 shProg->VertexProgram = NULL;
87 }
88
89 if (shProg->FragmentProgram) {
90 if (shProg->FragmentProgram->Base.Parameters == shProg->Uniforms) {
91 /* to prevent a double-free in the next call */
92 shProg->FragmentProgram->Base.Parameters = NULL;
93 }
94 _mesa_delete_program(ctx, &shProg->FragmentProgram->Base);
95 shProg->FragmentProgram = NULL;
96 }
97
98
99 if (shProg->Uniforms) {
100 _mesa_free_parameter_list(shProg->Uniforms);
101 shProg->Uniforms = NULL;
102 }
103
104 if (shProg->Varying) {
105 _mesa_free_parameter_list(shProg->Varying);
106 shProg->Varying = NULL;
107 }
108}
109
110
Brianb9fbedd2007-03-26 09:23:44 -0600111/**
112 * Free/delete a shader program object.
113 */
Brianf2923612006-12-20 09:56:44 -0700114void
115_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
116{
117 _mesa_free_shader_program_data(ctx, shProg);
Brianb9fbedd2007-03-26 09:23:44 -0600118 if (shProg->Shaders) {
119 _mesa_free(shProg->Shaders);
120 shProg->Shaders = NULL;
121 }
Brianf2923612006-12-20 09:56:44 -0700122 _mesa_free(shProg);
123}
124
125
126/**
127 * Lookup a GLSL program object.
128 */
129struct gl_shader_program *
130_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
131{
132 struct gl_shader_program *shProg;
133 if (name) {
134 shProg = (struct gl_shader_program *)
135 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
136 /* Note that both gl_shader and gl_shader_program objects are kept
137 * in the same hash table. Check the object's type to be sure it's
138 * what we're expecting.
139 */
140 if (shProg && shProg->Type != GL_SHADER_PROGRAM) {
141 return NULL;
142 }
143 return shProg;
144 }
145 return NULL;
146}
147
148
149/**
150 * Allocate a new gl_shader object, initialize it.
151 */
152struct gl_shader *
153_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
154{
155 struct gl_shader *shader;
156 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
157 shader = CALLOC_STRUCT(gl_shader);
158 if (shader) {
159 shader->Type = type;
160 shader->Name = name;
161 shader->RefCount = 1;
162 }
163 return shader;
164}
165
166
167void
168_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
169{
170 GLuint i;
171 if (sh->Source)
172 _mesa_free((void *) sh->Source);
173 if (sh->InfoLog)
174 _mesa_free(sh->InfoLog);
175 for (i = 0; i < sh->NumPrograms; i++) {
176 assert(sh->Programs[i]);
177 _mesa_delete_program(ctx, sh->Programs[i]);
178 }
179 if (sh->Programs)
180 _mesa_free(sh->Programs);
181 _mesa_free(sh);
182}
183
184
185/**
186 * Lookup a GLSL shader object.
187 */
188struct gl_shader *
189_mesa_lookup_shader(GLcontext *ctx, GLuint name)
190{
191 if (name) {
192 struct gl_shader *sh = (struct gl_shader *)
193 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
194 /* Note that both gl_shader and gl_shader_program objects are kept
195 * in the same hash table. Check the object's type to be sure it's
196 * what we're expecting.
197 */
198 if (sh && sh->Type == GL_SHADER_PROGRAM) {
199 assert(sh->Type == GL_VERTEX_SHADER ||
200 sh->Type == GL_FRAGMENT_SHADER);
201 return NULL;
202 }
203 return sh;
204 }
205 return NULL;
206}
207
208
Brianfa4d0362007-02-26 18:33:50 -0700209/**
210 * Initialize context's shader state.
211 */
Brianf2923612006-12-20 09:56:44 -0700212void
213_mesa_init_shader_state(GLcontext * ctx)
214{
Brianfa4d0362007-02-26 18:33:50 -0700215 /* Device drivers may override these to control what kind of instructions
216 * are generated by the GLSL compiler.
217 */
218 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600219 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700220 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700221}
222
223
Brian5b01c5e2006-12-19 18:02:03 -0700224/**
Brian935f93f2007-03-24 16:20:02 -0600225 * Free the per-context shader-related state.
226 */
227void
228_mesa_free_shader_state(GLcontext *ctx)
229{
230 if (ctx->Shader.CurrentProgram) {
231 ctx->Shader.CurrentProgram->RefCount--;
232 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
233 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
234 ctx->Shader.CurrentProgram = NULL;
235 }
236 }
237}
238
239
240/**
Brian5b01c5e2006-12-19 18:02:03 -0700241 * Copy string from <src> to <dst>, up to maxLength characters, returning
242 * length of <dst> in <length>.
243 * \param src the strings source
244 * \param maxLength max chars to copy
245 * \param length returns number of chars copied
246 * \param dst the string destination
247 */
248static void
249copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
250{
251 GLsizei len;
252 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
253 dst[len] = src[len];
254 if (maxLength > 0)
255 dst[len] = 0;
256 if (length)
257 *length = len;
258}
259
260
Brian5b01c5e2006-12-19 18:02:03 -0700261/**
262 * Called via ctx->Driver.AttachShader()
263 */
264void
265_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
266{
Brian65a18442006-12-19 18:46:56 -0700267 struct gl_shader_program *shProg
268 = _mesa_lookup_shader_program(ctx, program);
269 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
270 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700271 GLuint i;
272
Brian65a18442006-12-19 18:46:56 -0700273 if (!shProg || !sh) {
Brian43975832007-01-04 08:21:09 -0700274 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700275 "glAttachShader(bad program or shader name)");
276 return;
277 }
278
279 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700280 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700281 /* already attached */
282 return;
Brian34ae99d2006-12-18 08:28:54 -0700283 }
284 }
Brian5b01c5e2006-12-19 18:02:03 -0700285
286 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700287 shProg->Shaders = (struct gl_shader **)
288 _mesa_realloc(shProg->Shaders,
289 n * sizeof(struct gl_shader *),
290 (n + 1) * sizeof(struct gl_shader *));
291 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700292 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
293 return;
294 }
295
296 /* append */
Brian65a18442006-12-19 18:46:56 -0700297 shProg->Shaders[n] = sh;
298 sh->RefCount++;
299 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700300}
301
302
303void
304_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
305 const GLchar *name)
306{
Brian65a18442006-12-19 18:46:56 -0700307 struct gl_shader_program *shProg
308 = _mesa_lookup_shader_program(ctx, program);
Brianb7978af2007-01-09 19:17:17 -0700309 const GLint size = -1; /* unknown size */
310 GLint i, oldIndex;
Brian5b01c5e2006-12-19 18:02:03 -0700311
Brian65a18442006-12-19 18:46:56 -0700312 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700313 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700314 return;
315 }
316
Brian9e4bae92006-12-20 09:27:42 -0700317 if (!name)
318 return;
319
320 if (strncmp(name, "gl_", 3) == 0) {
321 _mesa_error(ctx, GL_INVALID_OPERATION,
322 "glBindAttribLocation(illegal name)");
323 return;
324 }
325
Brian3209c3e2007-01-09 17:49:24 -0700326 oldIndex = _mesa_get_attrib_location(ctx, program, name);
327
328 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700329 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700330 if (i < 0) {
331 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
332 }
333
334 if (shProg->VertexProgram && oldIndex >= 0) {
335 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
336 }
337
Brian88e2dbf2007-01-10 13:33:38 -0700338#if 0
Brian3209c3e2007-01-09 17:49:24 -0700339 printf("===== post BindAttrib:\n");
340 _mesa_print_program(&shProg->VertexProgram->Base);
Brian88e2dbf2007-01-10 13:33:38 -0700341#endif
Brian34ae99d2006-12-18 08:28:54 -0700342}
343
344
Brian5b01c5e2006-12-19 18:02:03 -0700345GLuint
346_mesa_create_shader(GLcontext *ctx, GLenum type)
347{
Brian65a18442006-12-19 18:46:56 -0700348 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700349 GLuint name;
350
351 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
352
353 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700354 case GL_FRAGMENT_SHADER:
355 case GL_VERTEX_SHADER:
356 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700357 break;
358 default:
359 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
360 return 0;
361 }
362
Brian65a18442006-12-19 18:46:56 -0700363 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700364
365 return name;
366}
367
368
369GLuint
370_mesa_create_program(GLcontext *ctx)
371{
372 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700373 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700374
Brian65a18442006-12-19 18:46:56 -0700375 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
376 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700377
Brian65a18442006-12-19 18:46:56 -0700378 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700379
380 return name;
381}
382
383
384void
385_mesa_delete_program2(GLcontext *ctx, GLuint name)
386{
Brian65a18442006-12-19 18:46:56 -0700387 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700388
Brian65a18442006-12-19 18:46:56 -0700389 shProg = _mesa_lookup_shader_program(ctx, name);
390 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700391 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700392 return;
393 }
394
Brian9e4bae92006-12-20 09:27:42 -0700395 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700396 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700397
398 shProg->DeletePending = GL_TRUE;
399
400 /* decrement refcount, delete if zero */
401 shProg->RefCount--;
402 if (shProg->RefCount <= 0) {
403 _mesa_free_shader_program(ctx, shProg);
404 }
Brian5b01c5e2006-12-19 18:02:03 -0700405}
406
407
408void
409_mesa_delete_shader(GLcontext *ctx, GLuint shader)
410{
Brian9e4bae92006-12-20 09:27:42 -0700411 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
412 if (!sh) {
413 return;
414 }
Brian5b01c5e2006-12-19 18:02:03 -0700415
Brian9e4bae92006-12-20 09:27:42 -0700416 sh->DeletePending = GL_TRUE;
417 sh->RefCount--;
418 if (sh->RefCount <= 0) {
419 _mesa_free_shader(ctx, sh);
420 }
Brian5b01c5e2006-12-19 18:02:03 -0700421}
422
423
424void
425_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
426{
Brian65a18442006-12-19 18:46:56 -0700427 struct gl_shader_program *shProg
428 = _mesa_lookup_shader_program(ctx, program);
429 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700430 GLuint i, j;
431
Brian65a18442006-12-19 18:46:56 -0700432 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700433 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700434 "glDetachShader(bad program or shader name)");
435 return;
436 }
437
438 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700439 if (shProg->Shaders[i]->Name == shader) {
440 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700441 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700442
443 shProg->Shaders[i]->RefCount--;
Brianb9fbedd2007-03-26 09:23:44 -0600444 if (shProg->Shaders[i]->RefCount == 0) {
445 /* delete now */
446 _mesa_free_shader(ctx, shProg->Shaders[i]);
447 }
Brian9e4bae92006-12-20 09:27:42 -0700448
Brian5b01c5e2006-12-19 18:02:03 -0700449 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700450 newList = (struct gl_shader **)
451 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700452 if (!newList) {
453 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
454 return;
455 }
456 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700457 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700458 }
459 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700460 newList[j++] = shProg->Shaders[i];
461 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700462
Brian65a18442006-12-19 18:46:56 -0700463 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700464 return;
465 }
466 }
467
468 /* not found */
Brian43975832007-01-04 08:21:09 -0700469 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700470 "glDetachShader(shader not found)");
471}
472
473
474void
475_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
476 GLsizei maxLength, GLsizei *length, GLint *size,
477 GLenum *type, GLchar *nameOut)
478{
479 static const GLenum vec_types[] = {
480 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
481 };
Brian65a18442006-12-19 18:46:56 -0700482 struct gl_shader_program *shProg
483 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700484 GLint sz;
485
Brian65a18442006-12-19 18:46:56 -0700486 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700487 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700488 return;
489 }
490
Brian65a18442006-12-19 18:46:56 -0700491 if (!shProg->Attributes || index >= shProg->Attributes->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700492 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
493 return;
494 }
495
496 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700497 shProg->Attributes->Parameters[index].Name);
498 sz = shProg->Attributes->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700499 if (size)
500 *size = sz;
501 if (type)
502 *type = vec_types[sz]; /* XXX this is a temporary hack */
503}
504
505
506/**
507 * Called via ctx->Driver.GetActiveUniform().
508 */
509void
510_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
511 GLsizei maxLength, GLsizei *length, GLint *size,
512 GLenum *type, GLchar *nameOut)
513{
514 static const GLenum vec_types[] = {
515 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
516 };
Brian65a18442006-12-19 18:46:56 -0700517 struct gl_shader_program *shProg
518 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700519 GLint sz;
520
Brian65a18442006-12-19 18:46:56 -0700521 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700522 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700523 return;
524 }
525
Brian65a18442006-12-19 18:46:56 -0700526 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700527 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
528 return;
529 }
530
531 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700532 shProg->Uniforms->Parameters[index].Name);
533 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700534 if (size)
535 *size = sz;
536 if (type)
537 *type = vec_types[sz]; /* XXX this is a temporary hack */
538}
539
540
541/**
542 * Called via ctx->Driver.GetAttachedShaders().
543 */
544void
545_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
546 GLsizei *count, GLuint *obj)
547{
Brian65a18442006-12-19 18:46:56 -0700548 struct gl_shader_program *shProg
549 = _mesa_lookup_shader_program(ctx, program);
550 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700551 GLint i;
Brian65a18442006-12-19 18:46:56 -0700552 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
553 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700554 }
555 if (count)
556 *count = i;
557 }
558 else {
Brian43975832007-01-04 08:21:09 -0700559 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700560 }
561}
562
563
564GLint
565_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
566 const GLchar *name)
567{
Brian65a18442006-12-19 18:46:56 -0700568 struct gl_shader_program *shProg
569 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700570
Brian65a18442006-12-19 18:46:56 -0700571 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700572 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700573 return -1;
574 }
575
Brian65a18442006-12-19 18:46:56 -0700576 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700577 _mesa_error(ctx, GL_INVALID_OPERATION,
578 "glGetAttribLocation(program not linked)");
579 return -1;
580 }
581
582 if (!name)
583 return -1;
584
Brian65a18442006-12-19 18:46:56 -0700585 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700586 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
587 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700588 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700589 }
590 }
591 return -1;
592}
593
594
595GLuint
596_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700597{
598#if 0
599 GET_CURRENT_CONTEXT(ctx);
600
601 switch (pname) {
602 case GL_PROGRAM_OBJECT_ARB:
603 {
Brian5b01c5e2006-12-19 18:02:03 -0700604 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700605
606 if (pro != NULL)
607 return (**pro)._container._generic.
608 GetName((struct gl2_generic_intf **) (pro));
609 }
610 break;
611 default:
612 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
613 }
614#endif
615 return 0;
616}
617
618
Brian5b01c5e2006-12-19 18:02:03 -0700619void
620_mesa_get_programiv(GLcontext *ctx, GLuint program,
621 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700622{
Brian65a18442006-12-19 18:46:56 -0700623 struct gl_shader_program *shProg
624 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700625
Brian65a18442006-12-19 18:46:56 -0700626 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700627 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700628 return;
629 }
630
Brian5b01c5e2006-12-19 18:02:03 -0700631 switch (pname) {
632 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700633 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700634 break;
635 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700636 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700637 break;
Brian5b01c5e2006-12-19 18:02:03 -0700638 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700639 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700640 break;
641 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700642 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700643 break;
644 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700645 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700646 break;
647 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700648 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700649 break;
650 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700651 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700652 break;
653 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700654 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700655 break;
656 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700657 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700658 break;
659 default:
Brian5b01c5e2006-12-19 18:02:03 -0700660 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
661 return;
Brian34ae99d2006-12-18 08:28:54 -0700662 }
Brian5b01c5e2006-12-19 18:02:03 -0700663}
Brian34ae99d2006-12-18 08:28:54 -0700664
Brian34ae99d2006-12-18 08:28:54 -0700665
Brian5b01c5e2006-12-19 18:02:03 -0700666void
667_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
668{
Brian65a18442006-12-19 18:46:56 -0700669 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700670
671 if (!shader) {
672 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
673 return;
674 }
Brian65a18442006-12-19 18:46:56 -0700675
Brian5b01c5e2006-12-19 18:02:03 -0700676 switch (pname) {
677 case GL_SHADER_TYPE:
678 *params = shader->Type;
679 break;
680 case GL_DELETE_STATUS:
681 *params = shader->DeletePending;
682 break;
683 case GL_COMPILE_STATUS:
684 *params = shader->CompileStatus;
685 break;
686 case GL_INFO_LOG_LENGTH:
687 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
688 break;
689 case GL_SHADER_SOURCE_LENGTH:
690 *params = shader->Source ? strlen((char *) shader->Source) : 0;
691 break;
692 default:
693 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
694 return;
695 }
696}
697
698
699void
700_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
701 GLsizei *length, GLchar *infoLog)
702{
Brian65a18442006-12-19 18:46:56 -0700703 struct gl_shader_program *shProg
704 = _mesa_lookup_shader_program(ctx, program);
705 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700706 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
707 return;
708 }
Brian65a18442006-12-19 18:46:56 -0700709 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700710}
711
712
713void
714_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
715 GLsizei *length, GLchar *infoLog)
716{
Brian65a18442006-12-19 18:46:56 -0700717 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
718 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700719 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
720 return;
721 }
Brian65a18442006-12-19 18:46:56 -0700722 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700723}
724
725
726/**
727 * Called via ctx->Driver.GetShaderSource().
728 */
729void
730_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
731 GLsizei *length, GLchar *sourceOut)
732{
Brian65a18442006-12-19 18:46:56 -0700733 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
734 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700735 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
736 return;
737 }
Brian65a18442006-12-19 18:46:56 -0700738 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700739}
740
741
742/**
743 * Called via ctx->Driver.GetUniformfv().
744 */
745void
746_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
747 GLfloat *params)
748{
Brian65a18442006-12-19 18:46:56 -0700749 struct gl_shader_program *shProg
750 = _mesa_lookup_shader_program(ctx, program);
751 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700752 GLint i;
Brian65a18442006-12-19 18:46:56 -0700753 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
754 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
755 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700756 }
757 }
758 else {
759 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
760 }
761 }
762 else {
Brian43975832007-01-04 08:21:09 -0700763 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700764 }
765}
766
767
768/**
769 * Called via ctx->Driver.GetUniformLocation().
770 */
771GLint
772_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
773{
Brian71623982007-01-30 16:55:03 -0700774 struct gl_shader_program *shProg
775 = _mesa_lookup_shader_program(ctx, program);
776 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700777 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700778 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700779 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700780 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700781 /* XXX this is a temporary simplification / short-cut.
782 * We need to handle things like "e.c[0].b" as seen in the
783 * GLSL orange book, page 189.
784 */
Brian5cf73262007-01-05 16:02:45 -0700785 if ((u->Type == PROGRAM_UNIFORM ||
786 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700787 return loc;
788 }
789 }
790 }
791 return -1;
792
793}
794
795
796GLboolean
797_mesa_is_program(GLcontext *ctx, GLuint name)
798{
Brian65a18442006-12-19 18:46:56 -0700799 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
800 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700801}
802
803
804GLboolean
805_mesa_is_shader(GLcontext *ctx, GLuint name)
806{
Brian65a18442006-12-19 18:46:56 -0700807 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700808 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700809}
810
811
812
Brian5b01c5e2006-12-19 18:02:03 -0700813/**
814 * Called via ctx->Driver.ShaderSource()
815 */
816void
817_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700818{
Brian65a18442006-12-19 18:46:56 -0700819 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
820 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700821 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700822 return;
823 }
824
Brian34ae99d2006-12-18 08:28:54 -0700825 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700826 if (sh->Source) {
827 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700828 }
Brian65a18442006-12-19 18:46:56 -0700829 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700830 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700831}
832
833
Brian5b01c5e2006-12-19 18:02:03 -0700834/**
835 * Called via ctx->Driver.CompileShader()
836 */
837void
838_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700839{
Brian65a18442006-12-19 18:46:56 -0700840 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700841
Brian65a18442006-12-19 18:46:56 -0700842 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700843 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
844 return;
845 }
846
Brian43975832007-01-04 08:21:09 -0700847 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700848}
849
850
Brian5b01c5e2006-12-19 18:02:03 -0700851/**
852 * Called via ctx->Driver.LinkProgram()
853 */
854void
855_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700856{
Brian65a18442006-12-19 18:46:56 -0700857 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700858
Brian65a18442006-12-19 18:46:56 -0700859 shProg = _mesa_lookup_shader_program(ctx, program);
860 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700861 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700862 return;
863 }
864
Brianc1771912007-02-16 09:56:19 -0700865 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700866}
867
868
869/**
Brian5b01c5e2006-12-19 18:02:03 -0700870 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700871 */
Brian5b01c5e2006-12-19 18:02:03 -0700872void
873_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700874{
Brian00d63aa2007-02-03 11:35:02 -0700875 if (ctx->Shader.CurrentProgram &&
876 ctx->Shader.CurrentProgram->Name == program) {
877 /* no-op */
878 return;
879 }
880
881 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
882
Brian9e4bae92006-12-20 09:27:42 -0700883 /* unbind old */
884 if (ctx->Shader.CurrentProgram) {
885 ctx->Shader.CurrentProgram->RefCount--;
886 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
887 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
888 }
889 ctx->Shader.CurrentProgram = NULL;
890 }
891
Brian5b01c5e2006-12-19 18:02:03 -0700892 if (program) {
Brian65a18442006-12-19 18:46:56 -0700893 struct gl_shader_program *shProg;
894 shProg = _mesa_lookup_shader_program(ctx, program);
895 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700896 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700897 "glUseProgramObjectARB(programObj)");
898 return;
899 }
Brian65a18442006-12-19 18:46:56 -0700900 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700901 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700902 }
903 else {
904 /* don't use a shader program */
905 ctx->Shader.CurrentProgram = NULL;
906 }
907}
Brian34ae99d2006-12-18 08:28:54 -0700908
Brian5b01c5e2006-12-19 18:02:03 -0700909
910/**
911 * Called via ctx->Driver.Uniform().
912 */
913void
914_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
915 const GLvoid *values, GLenum type)
916{
Brian3a8e2772006-12-20 17:19:16 -0700917 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -0600918 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -0700919
920 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700921 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700922 return;
923 }
924
Brian223d7cb2007-01-23 16:37:51 -0700925 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700926 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
927 return;
928 }
929
930 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
931
Brianfee9bbe2007-02-02 18:05:43 -0700932 /*
933 * If we're setting a sampler, we must use glUniformi1()!
934 */
935 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
936 if (type != GL_INT || count != 1) {
937 _mesa_error(ctx, GL_INVALID_OPERATION,
938 "glUniform(only glUniform1i can be used "
939 "to set sampler uniforms)");
940 return;
941 }
942 }
943
Brian52363952007-03-13 16:50:24 -0600944 if (count < 0) {
945 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
946 return;
947 }
948
Brian98650bd2007-03-13 16:32:48 -0600949 switch (type) {
950 case GL_FLOAT:
951 case GL_INT:
952 elems = 1;
953 break;
954 case GL_FLOAT_VEC2:
955 case GL_INT_VEC2:
956 elems = 2;
957 break;
958 case GL_FLOAT_VEC3:
959 case GL_INT_VEC3:
960 elems = 3;
961 break;
962 case GL_FLOAT_VEC4:
963 case GL_INT_VEC4:
964 elems = 4;
965 break;
966 default:
967 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
968 return;
Brian89dc4852007-01-04 14:35:44 -0700969 }
Brian98650bd2007-03-13 16:32:48 -0600970
971 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
972 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
973 return;
974 }
975
976 for (k = 0; k < count; k++) {
977 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
978 if (type == GL_INT ||
979 type == GL_INT_VEC2 ||
980 type == GL_INT_VEC3 ||
981 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -0600982 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600983 for (i = 0; i < elems; i++) {
984 uniformVal[i] = (GLfloat) iValues[i];
985 }
986 }
987 else {
Brian52363952007-03-13 16:50:24 -0600988 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600989 for (i = 0; i < elems; i++) {
990 uniformVal[i] = fValues[i];
991 }
Brian89dc4852007-01-04 14:35:44 -0700992 }
Brian5b01c5e2006-12-19 18:02:03 -0700993 }
Brian5cf73262007-01-05 16:02:45 -0700994
995 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -0700996 if (shProg->VertexProgram)
997 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
998 if (shProg->FragmentProgram)
999 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -07001000 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1001 }
Brian34ae99d2006-12-18 08:28:54 -07001002}
1003
1004
1005/**
Brian5b01c5e2006-12-19 18:02:03 -07001006 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -07001007 */
Brian5b01c5e2006-12-19 18:02:03 -07001008void
1009_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1010 GLenum matrixType, GLint location, GLsizei count,
1011 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001012{
Brian3a8e2772006-12-20 17:19:16 -07001013 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1014 if (!shProg || !shProg->LinkStatus) {
1015 _mesa_error(ctx, GL_INVALID_OPERATION,
1016 "glUniformMatrix(program not linked)");
1017 return;
1018 }
1019 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
1020 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1021 return;
1022 }
Brian34ae99d2006-12-18 08:28:54 -07001023 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001024 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001025 return;
1026 }
1027
1028 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1029
Brian3a8e2772006-12-20 17:19:16 -07001030 /*
1031 * Note: the _columns_ of a matrix are stored in program registers, not
1032 * the rows.
1033 */
1034 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001035 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001036 GLuint row, col;
1037 for (col = 0; col < cols; col++) {
1038 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1039 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001040 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001041 }
Brian34ae99d2006-12-18 08:28:54 -07001042 }
Brian34ae99d2006-12-18 08:28:54 -07001043 }
1044 else {
Brian3a8e2772006-12-20 17:19:16 -07001045 GLuint row, col;
1046 for (col = 0; col < cols; col++) {
1047 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1048 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001049 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001050 }
1051 }
Brian34ae99d2006-12-18 08:28:54 -07001052 }
1053}
1054
1055
Brian5b01c5e2006-12-19 18:02:03 -07001056void
1057_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001058{
Brian65a18442006-12-19 18:46:56 -07001059 struct gl_shader_program *shProg;
1060 shProg = _mesa_lookup_shader_program(ctx, program);
1061 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001062 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001063 return;
1064 }
Brian5b01c5e2006-12-19 18:02:03 -07001065 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001066 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001067
Brian5b01c5e2006-12-19 18:02:03 -07001068 /* From the GL spec:
1069 any two active samplers in the current program object are of
1070 different types, but refer to the same texture image unit,
1071
1072 any active sampler in the current program object refers to a texture
1073 image unit where fixed-function fragment processing accesses a
1074 texture target that does not match the sampler type, or
1075
1076 the sum of the number of active samplers in the program and the
1077 number of texture image units enabled for fixed-function fragment
1078 processing exceeds the combined limit on the total number of texture
1079 image units allowed.
1080 */
Brian34ae99d2006-12-18 08:28:54 -07001081}