blob: cf42a5843ec2a73c29c1f7beaa55e932e140b1fc [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
Brian9f660252007-04-11 09:00:56 -0600326 if (shProg->LinkStatus) {
327 /* get current index/location for the attribute */
328 oldIndex = _mesa_get_attrib_location(ctx, program, name);
329 }
330 else {
331 oldIndex = -1;
332 }
Brian3209c3e2007-01-09 17:49:24 -0700333
334 /* this will replace the current value if it's already in the list */
Brianb7978af2007-01-09 19:17:17 -0700335 i = _mesa_add_attribute(shProg->Attributes, name, size, index);
Brian3209c3e2007-01-09 17:49:24 -0700336 if (i < 0) {
337 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
338 }
339
Brian9f660252007-04-11 09:00:56 -0600340 if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) {
341 /* If the index changed, need to search/replace references to that attribute
342 * in the vertex program.
343 */
Brian3209c3e2007-01-09 17:49:24 -0700344 _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index);
345 }
Brian34ae99d2006-12-18 08:28:54 -0700346}
347
348
Brian5b01c5e2006-12-19 18:02:03 -0700349GLuint
350_mesa_create_shader(GLcontext *ctx, GLenum type)
351{
Brian65a18442006-12-19 18:46:56 -0700352 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700353 GLuint name;
354
355 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
356
357 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700358 case GL_FRAGMENT_SHADER:
359 case GL_VERTEX_SHADER:
360 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700361 break;
362 default:
363 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
364 return 0;
365 }
366
Brian65a18442006-12-19 18:46:56 -0700367 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700368
369 return name;
370}
371
372
373GLuint
374_mesa_create_program(GLcontext *ctx)
375{
376 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700377 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700378
Brian65a18442006-12-19 18:46:56 -0700379 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
380 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700381
Brian65a18442006-12-19 18:46:56 -0700382 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700383
384 return name;
385}
386
387
388void
389_mesa_delete_program2(GLcontext *ctx, GLuint name)
390{
Brian65a18442006-12-19 18:46:56 -0700391 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700392
Brian65a18442006-12-19 18:46:56 -0700393 shProg = _mesa_lookup_shader_program(ctx, name);
394 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700395 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteProgram(name)");
Brian5b01c5e2006-12-19 18:02:03 -0700396 return;
397 }
398
Brian9e4bae92006-12-20 09:27:42 -0700399 /* always remove from hash table */
Brian65a18442006-12-19 18:46:56 -0700400 _mesa_HashRemove(ctx->Shared->ShaderObjects, name);
Brian9e4bae92006-12-20 09:27:42 -0700401
402 shProg->DeletePending = GL_TRUE;
403
404 /* decrement refcount, delete if zero */
405 shProg->RefCount--;
406 if (shProg->RefCount <= 0) {
407 _mesa_free_shader_program(ctx, shProg);
408 }
Brian5b01c5e2006-12-19 18:02:03 -0700409}
410
411
412void
413_mesa_delete_shader(GLcontext *ctx, GLuint shader)
414{
Brian9e4bae92006-12-20 09:27:42 -0700415 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
416 if (!sh) {
417 return;
418 }
Brian5b01c5e2006-12-19 18:02:03 -0700419
Brian9e4bae92006-12-20 09:27:42 -0700420 sh->DeletePending = GL_TRUE;
421 sh->RefCount--;
422 if (sh->RefCount <= 0) {
423 _mesa_free_shader(ctx, sh);
424 }
Brian5b01c5e2006-12-19 18:02:03 -0700425}
426
427
428void
429_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
430{
Brian65a18442006-12-19 18:46:56 -0700431 struct gl_shader_program *shProg
432 = _mesa_lookup_shader_program(ctx, program);
433 const GLuint n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700434 GLuint i, j;
435
Brian65a18442006-12-19 18:46:56 -0700436 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700437 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700438 "glDetachShader(bad program or shader name)");
439 return;
440 }
441
442 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700443 if (shProg->Shaders[i]->Name == shader) {
444 struct gl_shader **newList;
Brian5b01c5e2006-12-19 18:02:03 -0700445 /* found it */
Brian9e4bae92006-12-20 09:27:42 -0700446
447 shProg->Shaders[i]->RefCount--;
Brianb9fbedd2007-03-26 09:23:44 -0600448 if (shProg->Shaders[i]->RefCount == 0) {
449 /* delete now */
450 _mesa_free_shader(ctx, shProg->Shaders[i]);
451 }
Brian9e4bae92006-12-20 09:27:42 -0700452
Brian5b01c5e2006-12-19 18:02:03 -0700453 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700454 newList = (struct gl_shader **)
455 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700456 if (!newList) {
457 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
458 return;
459 }
460 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700461 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700462 }
463 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700464 newList[j++] = shProg->Shaders[i];
465 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700466
Brian65a18442006-12-19 18:46:56 -0700467 shProg->Shaders = newList;
Brian5b01c5e2006-12-19 18:02:03 -0700468 return;
469 }
470 }
471
472 /* not found */
Brian43975832007-01-04 08:21:09 -0700473 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700474 "glDetachShader(shader not found)");
475}
476
477
478void
479_mesa_get_active_attrib(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->Attributes || index >= shProg->Attributes->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->Attributes->Parameters[index].Name);
502 sz = shProg->Attributes->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.GetActiveUniform().
512 */
513void
514_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
515 GLsizei maxLength, GLsizei *length, GLint *size,
516 GLenum *type, GLchar *nameOut)
517{
518 static const GLenum vec_types[] = {
519 GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4
520 };
Brian65a18442006-12-19 18:46:56 -0700521 struct gl_shader_program *shProg
522 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700523 GLint sz;
524
Brian65a18442006-12-19 18:46:56 -0700525 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700526 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform");
Brian5b01c5e2006-12-19 18:02:03 -0700527 return;
528 }
529
Brian65a18442006-12-19 18:46:56 -0700530 if (!shProg->Uniforms || index >= shProg->Uniforms->NumParameters) {
Brian5b01c5e2006-12-19 18:02:03 -0700531 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
532 return;
533 }
534
535 copy_string(nameOut, maxLength, length,
Brian65a18442006-12-19 18:46:56 -0700536 shProg->Uniforms->Parameters[index].Name);
537 sz = shProg->Uniforms->Parameters[index].Size;
Brian5b01c5e2006-12-19 18:02:03 -0700538 if (size)
539 *size = sz;
540 if (type)
541 *type = vec_types[sz]; /* XXX this is a temporary hack */
542}
543
544
545/**
546 * Called via ctx->Driver.GetAttachedShaders().
547 */
548void
549_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
550 GLsizei *count, GLuint *obj)
551{
Brian65a18442006-12-19 18:46:56 -0700552 struct gl_shader_program *shProg
553 = _mesa_lookup_shader_program(ctx, program);
554 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700555 GLint i;
Brian65a18442006-12-19 18:46:56 -0700556 for (i = 0; i < maxCount && i < shProg->NumShaders; i++) {
557 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700558 }
559 if (count)
560 *count = i;
561 }
562 else {
Brian43975832007-01-04 08:21:09 -0700563 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttachedShaders");
Brian5b01c5e2006-12-19 18:02:03 -0700564 }
565}
566
567
568GLint
569_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
570 const GLchar *name)
571{
Brian65a18442006-12-19 18:46:56 -0700572 struct gl_shader_program *shProg
573 = _mesa_lookup_shader_program(ctx, program);
Brian5b01c5e2006-12-19 18:02:03 -0700574
Brian65a18442006-12-19 18:46:56 -0700575 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700576 _mesa_error(ctx, GL_INVALID_VALUE, "glGetAttribLocation");
Brian5b01c5e2006-12-19 18:02:03 -0700577 return -1;
578 }
579
Brian65a18442006-12-19 18:46:56 -0700580 if (!shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700581 _mesa_error(ctx, GL_INVALID_OPERATION,
582 "glGetAttribLocation(program not linked)");
583 return -1;
584 }
585
586 if (!name)
587 return -1;
588
Brian65a18442006-12-19 18:46:56 -0700589 if (shProg->Attributes) {
Brian3209c3e2007-01-09 17:49:24 -0700590 GLint i = _mesa_lookup_parameter_index(shProg->Attributes, -1, name);
591 if (i >= 0) {
Brian01a91eb2007-01-09 19:26:22 -0700592 return shProg->Attributes->Parameters[i].StateIndexes[0];
Brian5b01c5e2006-12-19 18:02:03 -0700593 }
594 }
595 return -1;
596}
597
598
599GLuint
600_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700601{
602#if 0
603 GET_CURRENT_CONTEXT(ctx);
604
605 switch (pname) {
606 case GL_PROGRAM_OBJECT_ARB:
607 {
Brian5b01c5e2006-12-19 18:02:03 -0700608 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700609
610 if (pro != NULL)
611 return (**pro)._container._generic.
612 GetName((struct gl2_generic_intf **) (pro));
613 }
614 break;
615 default:
616 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
617 }
618#endif
619 return 0;
620}
621
622
Brian5b01c5e2006-12-19 18:02:03 -0700623void
624_mesa_get_programiv(GLcontext *ctx, GLuint program,
625 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700626{
Brian65a18442006-12-19 18:46:56 -0700627 struct gl_shader_program *shProg
628 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700629
Brian65a18442006-12-19 18:46:56 -0700630 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700631 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700632 return;
633 }
634
Brian5b01c5e2006-12-19 18:02:03 -0700635 switch (pname) {
636 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700637 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700638 break;
639 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700640 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700641 break;
Brian5b01c5e2006-12-19 18:02:03 -0700642 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700643 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700644 break;
645 case GL_INFO_LOG_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700646 *params = shProg->InfoLog ? strlen(shProg->InfoLog) : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700647 break;
648 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700649 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700650 break;
651 case GL_ACTIVE_ATTRIBUTES:
Brian3209c3e2007-01-09 17:49:24 -0700652 *params = shProg->Attributes ? shProg->Attributes->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700653 break;
654 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700655 *params = _mesa_parameter_longest_name(shProg->Attributes);
Brian5b01c5e2006-12-19 18:02:03 -0700656 break;
657 case GL_ACTIVE_UNIFORMS:
Brian65a18442006-12-19 18:46:56 -0700658 *params = shProg->Uniforms ? shProg->Uniforms->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700659 break;
660 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian65a18442006-12-19 18:46:56 -0700661 *params = _mesa_parameter_longest_name(shProg->Uniforms);
Brian34ae99d2006-12-18 08:28:54 -0700662 break;
663 default:
Brian5b01c5e2006-12-19 18:02:03 -0700664 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
665 return;
Brian34ae99d2006-12-18 08:28:54 -0700666 }
Brian5b01c5e2006-12-19 18:02:03 -0700667}
Brian34ae99d2006-12-18 08:28:54 -0700668
Brian34ae99d2006-12-18 08:28:54 -0700669
Brian5b01c5e2006-12-19 18:02:03 -0700670void
671_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
672{
Brian65a18442006-12-19 18:46:56 -0700673 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700674
675 if (!shader) {
676 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderiv(shader)");
677 return;
678 }
Brian65a18442006-12-19 18:46:56 -0700679
Brian5b01c5e2006-12-19 18:02:03 -0700680 switch (pname) {
681 case GL_SHADER_TYPE:
682 *params = shader->Type;
683 break;
684 case GL_DELETE_STATUS:
685 *params = shader->DeletePending;
686 break;
687 case GL_COMPILE_STATUS:
688 *params = shader->CompileStatus;
689 break;
690 case GL_INFO_LOG_LENGTH:
691 *params = shader->InfoLog ? strlen(shader->InfoLog) : 0;
692 break;
693 case GL_SHADER_SOURCE_LENGTH:
694 *params = shader->Source ? strlen((char *) shader->Source) : 0;
695 break;
696 default:
697 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
698 return;
699 }
700}
701
702
703void
704_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
705 GLsizei *length, GLchar *infoLog)
706{
Brian65a18442006-12-19 18:46:56 -0700707 struct gl_shader_program *shProg
708 = _mesa_lookup_shader_program(ctx, program);
709 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700710 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
711 return;
712 }
Brian65a18442006-12-19 18:46:56 -0700713 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700714}
715
716
717void
718_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
719 GLsizei *length, GLchar *infoLog)
720{
Brian65a18442006-12-19 18:46:56 -0700721 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
722 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700723 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
724 return;
725 }
Brian65a18442006-12-19 18:46:56 -0700726 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700727}
728
729
730/**
731 * Called via ctx->Driver.GetShaderSource().
732 */
733void
734_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
735 GLsizei *length, GLchar *sourceOut)
736{
Brian65a18442006-12-19 18:46:56 -0700737 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
738 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700739 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderSource(shader)");
740 return;
741 }
Brian65a18442006-12-19 18:46:56 -0700742 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -0700743}
744
745
746/**
747 * Called via ctx->Driver.GetUniformfv().
748 */
749void
750_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
751 GLfloat *params)
752{
Brian65a18442006-12-19 18:46:56 -0700753 struct gl_shader_program *shProg
754 = _mesa_lookup_shader_program(ctx, program);
755 if (shProg) {
Brian223d7cb2007-01-23 16:37:51 -0700756 GLint i;
Brian65a18442006-12-19 18:46:56 -0700757 if (location >= 0 && location < shProg->Uniforms->NumParameters) {
758 for (i = 0; i < shProg->Uniforms->Parameters[location].Size; i++) {
759 params[i] = shProg->Uniforms->ParameterValues[location][i];
Brian5b01c5e2006-12-19 18:02:03 -0700760 }
761 }
762 else {
763 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(location)");
764 }
765 }
766 else {
Brian43975832007-01-04 08:21:09 -0700767 _mesa_error(ctx, GL_INVALID_VALUE, "glGetUniformfv(program)");
Brian5b01c5e2006-12-19 18:02:03 -0700768 }
769}
770
771
772/**
773 * Called via ctx->Driver.GetUniformLocation().
774 */
775GLint
776_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
777{
Brian71623982007-01-30 16:55:03 -0700778 struct gl_shader_program *shProg
779 = _mesa_lookup_shader_program(ctx, program);
780 if (shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700781 GLuint loc;
Brian65a18442006-12-19 18:46:56 -0700782 for (loc = 0; loc < shProg->Uniforms->NumParameters; loc++) {
Brian5b01c5e2006-12-19 18:02:03 -0700783 const struct gl_program_parameter *u
Brian65a18442006-12-19 18:46:56 -0700784 = shProg->Uniforms->Parameters + loc;
Brian29053852006-12-21 11:21:26 -0700785 /* XXX this is a temporary simplification / short-cut.
786 * We need to handle things like "e.c[0].b" as seen in the
787 * GLSL orange book, page 189.
788 */
Brian5cf73262007-01-05 16:02:45 -0700789 if ((u->Type == PROGRAM_UNIFORM ||
790 u->Type == PROGRAM_SAMPLER) && !strcmp(u->Name, name)) {
Brian5b01c5e2006-12-19 18:02:03 -0700791 return loc;
792 }
793 }
794 }
795 return -1;
796
797}
798
799
800GLboolean
801_mesa_is_program(GLcontext *ctx, GLuint name)
802{
Brian65a18442006-12-19 18:46:56 -0700803 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
804 return shProg ? GL_TRUE : GL_FALSE;
Brian5b01c5e2006-12-19 18:02:03 -0700805}
806
807
808GLboolean
809_mesa_is_shader(GLcontext *ctx, GLuint name)
810{
Brian65a18442006-12-19 18:46:56 -0700811 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700812 return shader ? GL_TRUE : GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700813}
814
815
816
Brian5b01c5e2006-12-19 18:02:03 -0700817/**
818 * Called via ctx->Driver.ShaderSource()
819 */
820void
821_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -0700822{
Brian65a18442006-12-19 18:46:56 -0700823 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
824 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700825 _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSource(shaderObj)");
Brian34ae99d2006-12-18 08:28:54 -0700826 return;
827 }
828
Brian34ae99d2006-12-18 08:28:54 -0700829 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -0700830 if (sh->Source) {
831 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -0700832 }
Brian65a18442006-12-19 18:46:56 -0700833 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -0700834 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -0700835}
836
837
Brian5b01c5e2006-12-19 18:02:03 -0700838/**
839 * Called via ctx->Driver.CompileShader()
840 */
841void
842_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -0700843{
Brian65a18442006-12-19 18:46:56 -0700844 struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj);
Brian34ae99d2006-12-18 08:28:54 -0700845
Brian65a18442006-12-19 18:46:56 -0700846 if (!sh) {
Brian34ae99d2006-12-18 08:28:54 -0700847 _mesa_error(ctx, GL_INVALID_VALUE, "glCompileShader(shaderObj)");
848 return;
849 }
850
Brian43975832007-01-04 08:21:09 -0700851 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -0700852}
853
854
Brian5b01c5e2006-12-19 18:02:03 -0700855/**
856 * Called via ctx->Driver.LinkProgram()
857 */
858void
859_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700860{
Brian65a18442006-12-19 18:46:56 -0700861 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -0700862
Brian65a18442006-12-19 18:46:56 -0700863 shProg = _mesa_lookup_shader_program(ctx, program);
864 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700865 _mesa_error(ctx, GL_INVALID_VALUE, "glLinkProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -0700866 return;
867 }
868
Brianc1771912007-02-16 09:56:19 -0700869 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -0700870}
871
872
873/**
Brian5b01c5e2006-12-19 18:02:03 -0700874 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -0700875 */
Brian5b01c5e2006-12-19 18:02:03 -0700876void
877_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -0700878{
Brian00d63aa2007-02-03 11:35:02 -0700879 if (ctx->Shader.CurrentProgram &&
880 ctx->Shader.CurrentProgram->Name == program) {
881 /* no-op */
882 return;
883 }
884
885 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
886
Brian9e4bae92006-12-20 09:27:42 -0700887 /* unbind old */
888 if (ctx->Shader.CurrentProgram) {
889 ctx->Shader.CurrentProgram->RefCount--;
890 if (ctx->Shader.CurrentProgram->RefCount <= 0) {
891 _mesa_free_shader_program(ctx, ctx->Shader.CurrentProgram);
892 }
893 ctx->Shader.CurrentProgram = NULL;
894 }
895
Brian5b01c5e2006-12-19 18:02:03 -0700896 if (program) {
Brian65a18442006-12-19 18:46:56 -0700897 struct gl_shader_program *shProg;
898 shProg = _mesa_lookup_shader_program(ctx, program);
899 if (!shProg) {
Brian43975832007-01-04 08:21:09 -0700900 _mesa_error(ctx, GL_INVALID_VALUE,
Brian5b01c5e2006-12-19 18:02:03 -0700901 "glUseProgramObjectARB(programObj)");
902 return;
903 }
Brian65a18442006-12-19 18:46:56 -0700904 ctx->Shader.CurrentProgram = shProg;
Brian9e4bae92006-12-20 09:27:42 -0700905 shProg->RefCount++;
Brian5b01c5e2006-12-19 18:02:03 -0700906 }
907 else {
908 /* don't use a shader program */
909 ctx->Shader.CurrentProgram = NULL;
910 }
911}
Brian34ae99d2006-12-18 08:28:54 -0700912
Brian5b01c5e2006-12-19 18:02:03 -0700913
914/**
915 * Called via ctx->Driver.Uniform().
916 */
917void
918_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
919 const GLvoid *values, GLenum type)
920{
Brian3a8e2772006-12-20 17:19:16 -0700921 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian98650bd2007-03-13 16:32:48 -0600922 GLint elems, i, k;
Brian3a8e2772006-12-20 17:19:16 -0700923
924 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -0700925 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -0700926 return;
927 }
928
Brian223d7cb2007-01-23 16:37:51 -0700929 if (location < 0 || location >= (GLint) shProg->Uniforms->NumParameters) {
Brian3a8e2772006-12-20 17:19:16 -0700930 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
931 return;
932 }
933
934 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
935
Brianfee9bbe2007-02-02 18:05:43 -0700936 /*
937 * If we're setting a sampler, we must use glUniformi1()!
938 */
939 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
940 if (type != GL_INT || count != 1) {
941 _mesa_error(ctx, GL_INVALID_OPERATION,
942 "glUniform(only glUniform1i can be used "
943 "to set sampler uniforms)");
944 return;
945 }
946 }
947
Brian52363952007-03-13 16:50:24 -0600948 if (count < 0) {
949 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
950 return;
951 }
952
Brian98650bd2007-03-13 16:32:48 -0600953 switch (type) {
954 case GL_FLOAT:
955 case GL_INT:
956 elems = 1;
957 break;
958 case GL_FLOAT_VEC2:
959 case GL_INT_VEC2:
960 elems = 2;
961 break;
962 case GL_FLOAT_VEC3:
963 case GL_INT_VEC3:
964 elems = 3;
965 break;
966 case GL_FLOAT_VEC4:
967 case GL_INT_VEC4:
968 elems = 4;
969 break;
970 default:
971 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
972 return;
Brian89dc4852007-01-04 14:35:44 -0700973 }
Brian98650bd2007-03-13 16:32:48 -0600974
975 if (count * elems > shProg->Uniforms->Parameters[location].Size) {
976 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
977 return;
978 }
979
980 for (k = 0; k < count; k++) {
981 GLfloat *uniformVal = shProg->Uniforms->ParameterValues[location + k];
982 if (type == GL_INT ||
983 type == GL_INT_VEC2 ||
984 type == GL_INT_VEC3 ||
985 type == GL_INT_VEC4) {
Brian52363952007-03-13 16:50:24 -0600986 const GLint *iValues = ((const GLint *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600987 for (i = 0; i < elems; i++) {
988 uniformVal[i] = (GLfloat) iValues[i];
989 }
990 }
991 else {
Brian52363952007-03-13 16:50:24 -0600992 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
Brian98650bd2007-03-13 16:32:48 -0600993 for (i = 0; i < elems; i++) {
994 uniformVal[i] = fValues[i];
995 }
Brian89dc4852007-01-04 14:35:44 -0700996 }
Brian5b01c5e2006-12-19 18:02:03 -0700997 }
Brian5cf73262007-01-05 16:02:45 -0700998
999 if (shProg->Uniforms->Parameters[location].Type == PROGRAM_SAMPLER) {
Briancec81ee2007-03-07 08:04:06 -07001000 if (shProg->VertexProgram)
1001 _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base);
1002 if (shProg->FragmentProgram)
1003 _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base);
Brian5cf73262007-01-05 16:02:45 -07001004 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1005 }
Brian34ae99d2006-12-18 08:28:54 -07001006}
1007
1008
1009/**
Brian5b01c5e2006-12-19 18:02:03 -07001010 * Called by ctx->Driver.UniformMatrix().
Brian34ae99d2006-12-18 08:28:54 -07001011 */
Brian5b01c5e2006-12-19 18:02:03 -07001012void
1013_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1014 GLenum matrixType, GLint location, GLsizei count,
1015 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001016{
Brian3a8e2772006-12-20 17:19:16 -07001017 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
1018 if (!shProg || !shProg->LinkStatus) {
1019 _mesa_error(ctx, GL_INVALID_OPERATION,
1020 "glUniformMatrix(program not linked)");
1021 return;
1022 }
1023 if (location < 0 || location >= shProg->Uniforms->NumParameters) {
1024 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
1025 return;
1026 }
Brian34ae99d2006-12-18 08:28:54 -07001027 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001028 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001029 return;
1030 }
1031
1032 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1033
Brian3a8e2772006-12-20 17:19:16 -07001034 /*
1035 * Note: the _columns_ of a matrix are stored in program registers, not
1036 * the rows.
1037 */
1038 /* XXXX need to test 3x3 and 2x2 matrices... */
Brian34ae99d2006-12-18 08:28:54 -07001039 if (transpose) {
Brian3a8e2772006-12-20 17:19:16 -07001040 GLuint row, col;
1041 for (col = 0; col < cols; col++) {
1042 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1043 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001044 v[row] = values[row * cols + col];
Brian34ae99d2006-12-18 08:28:54 -07001045 }
Brian34ae99d2006-12-18 08:28:54 -07001046 }
Brian34ae99d2006-12-18 08:28:54 -07001047 }
1048 else {
Brian3a8e2772006-12-20 17:19:16 -07001049 GLuint row, col;
1050 for (col = 0; col < cols; col++) {
1051 GLfloat *v = shProg->Uniforms->ParameterValues[location + col];
1052 for (row = 0; row < rows; row++) {
Brian9f442472007-03-09 11:34:18 -07001053 v[row] = values[col * rows + row];
Brian3a8e2772006-12-20 17:19:16 -07001054 }
1055 }
Brian34ae99d2006-12-18 08:28:54 -07001056 }
1057}
1058
1059
Brian5b01c5e2006-12-19 18:02:03 -07001060void
1061_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001062{
Brian65a18442006-12-19 18:46:56 -07001063 struct gl_shader_program *shProg;
1064 shProg = _mesa_lookup_shader_program(ctx, program);
1065 if (!shProg) {
Brian43975832007-01-04 08:21:09 -07001066 _mesa_error(ctx, GL_INVALID_VALUE, "glValidateProgram(program)");
Brian34ae99d2006-12-18 08:28:54 -07001067 return;
1068 }
Brian5b01c5e2006-12-19 18:02:03 -07001069 /* XXX temporary */
Brian65a18442006-12-19 18:46:56 -07001070 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001071
Brian5b01c5e2006-12-19 18:02:03 -07001072 /* From the GL spec:
1073 any two active samplers in the current program object are of
1074 different types, but refer to the same texture image unit,
1075
1076 any active sampler in the current program object refers to a texture
1077 image unit where fixed-function fragment processing accesses a
1078 texture target that does not match the sampler type, or
1079
1080 the sum of the number of active samplers in the program and the
1081 number of texture image units enabled for fixed-function fragment
1082 processing exceeds the combined limit on the total number of texture
1083 image units allowed.
1084 */
Brian34ae99d2006-12-18 08:28:54 -07001085}