blob: 6e13c72f7ca222d04f824e712ab9567415a6bab4 [file] [log] [blame]
Brian34ae99d2006-12-18 08:28:54 -07001/*
2 * Mesa 3-D graphics library
Brian Paul27341a92008-09-16 16:28:36 -06003 * Version: 7.2
Brian34ae99d2006-12-18 08:28:54 -07004 *
Brian Paul8c51e002008-08-11 15:09:47 -06005 * Copyright (C) 2004-2008 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
Brian Paulbbd28712008-09-18 12:26:54 -060038#include "main/glheader.h"
39#include "main/context.h"
40#include "main/hash.h"
41#include "main/macros.h"
42#include "shader/program.h"
43#include "shader/prog_parameter.h"
44#include "shader/prog_print.h"
45#include "shader/prog_statevars.h"
46#include "shader/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
Brian Paulbda6ad22008-08-06 12:45:14 -060053#ifndef GL_PROGRAM_BINARY_LENGTH_OES
54#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
55#endif
56
57
Brianf2923612006-12-20 09:56:44 -070058/**
59 * Allocate a new gl_shader_program object, initialize it.
60 */
Brian Paulfd59f192008-05-18 16:04:55 -060061static struct gl_shader_program *
Brianf2923612006-12-20 09:56:44 -070062_mesa_new_shader_program(GLcontext *ctx, GLuint name)
63{
64 struct gl_shader_program *shProg;
65 shProg = CALLOC_STRUCT(gl_shader_program);
66 if (shProg) {
Brianf3e8c322007-04-18 14:53:23 -060067 shProg->Type = GL_SHADER_PROGRAM_MESA;
Brianf2923612006-12-20 09:56:44 -070068 shProg->Name = name;
69 shProg->RefCount = 1;
Brian3209c3e2007-01-09 17:49:24 -070070 shProg->Attributes = _mesa_new_parameter_list();
Brianf2923612006-12-20 09:56:44 -070071 }
72 return shProg;
73}
74
75
Brianb9fbedd2007-03-26 09:23:44 -060076/**
Brian3c008a02007-04-12 15:22:32 -060077 * Clear (free) the shader program state that gets produced by linking.
Brianb9fbedd2007-03-26 09:23:44 -060078 */
Brianf2923612006-12-20 09:56:44 -070079void
Brian3c008a02007-04-12 15:22:32 -060080_mesa_clear_shader_program_data(GLcontext *ctx,
81 struct gl_shader_program *shProg)
Brianf2923612006-12-20 09:56:44 -070082{
Brian Paul8bdf5b62008-05-16 09:56:59 -060083 _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);
84 _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);
Brianf2923612006-12-20 09:56:44 -070085
Brianf2923612006-12-20 09:56:44 -070086 if (shProg->Uniforms) {
Brian Paulade50832008-05-14 16:09:46 -060087 _mesa_free_uniform_list(shProg->Uniforms);
Brianf2923612006-12-20 09:56:44 -070088 shProg->Uniforms = NULL;
89 }
90
91 if (shProg->Varying) {
92 _mesa_free_parameter_list(shProg->Varying);
93 shProg->Varying = NULL;
94 }
95}
96
97
Brianb9fbedd2007-03-26 09:23:44 -060098/**
Brian3c008a02007-04-12 15:22:32 -060099 * Free all the data that hangs off a shader program object, but not the
100 * object itself.
101 */
102void
103_mesa_free_shader_program_data(GLcontext *ctx,
104 struct gl_shader_program *shProg)
105{
106 GLuint i;
107
Brianf3e8c322007-04-18 14:53:23 -0600108 assert(shProg->Type == GL_SHADER_PROGRAM_MESA);
Brian3c008a02007-04-12 15:22:32 -0600109
110 _mesa_clear_shader_program_data(ctx, shProg);
111
Brian4b7c6fc2007-04-19 15:23:34 -0600112 if (shProg->Attributes) {
113 _mesa_free_parameter_list(shProg->Attributes);
114 shProg->Attributes = NULL;
115 }
116
Brian3c008a02007-04-12 15:22:32 -0600117 /* detach shaders */
118 for (i = 0; i < shProg->NumShaders; i++) {
119 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
120 }
Xiang, Haihao63d8a842008-03-31 17:02:47 +0800121 shProg->NumShaders = 0;
122
Brian3c008a02007-04-12 15:22:32 -0600123 if (shProg->Shaders) {
124 _mesa_free(shProg->Shaders);
125 shProg->Shaders = NULL;
126 }
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100127
128 if (shProg->InfoLog) {
129 _mesa_free(shProg->InfoLog);
130 shProg->InfoLog = NULL;
131 }
Brian3c008a02007-04-12 15:22:32 -0600132}
133
134
135/**
Brianb9fbedd2007-03-26 09:23:44 -0600136 * Free/delete a shader program object.
137 */
Brianf2923612006-12-20 09:56:44 -0700138void
139_mesa_free_shader_program(GLcontext *ctx, struct gl_shader_program *shProg)
140{
141 _mesa_free_shader_program_data(ctx, shProg);
Alan Hourihaneeec20c32008-04-22 20:29:42 +0100142
Brianf2923612006-12-20 09:56:44 -0700143 _mesa_free(shProg);
144}
145
146
147/**
Brian3c008a02007-04-12 15:22:32 -0600148 * Set ptr to point to shProg.
149 * If ptr is pointing to another object, decrement its refcount (and delete
150 * if refcount hits zero).
151 * Then set ptr to point to shProg, incrementing its refcount.
152 */
153/* XXX this could be static */
154void
155_mesa_reference_shader_program(GLcontext *ctx,
156 struct gl_shader_program **ptr,
157 struct gl_shader_program *shProg)
158{
159 assert(ptr);
160 if (*ptr == shProg) {
161 /* no-op */
162 return;
163 }
164 if (*ptr) {
165 /* Unreference the old shader program */
166 GLboolean deleteFlag = GL_FALSE;
167 struct gl_shader_program *old = *ptr;
168
169 ASSERT(old->RefCount > 0);
170 old->RefCount--;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600171#if 0
172 printf("ShaderProgram %p ID=%u RefCount-- to %d\n",
173 (void *) old, old->Name, old->RefCount);
174#endif
Brian3c008a02007-04-12 15:22:32 -0600175 deleteFlag = (old->RefCount == 0);
176
177 if (deleteFlag) {
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800178 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
Brian3c008a02007-04-12 15:22:32 -0600179 _mesa_free_shader_program(ctx, old);
180 }
181
182 *ptr = NULL;
183 }
184 assert(!*ptr);
185
186 if (shProg) {
187 shProg->RefCount++;
Brian Paul8bdf5b62008-05-16 09:56:59 -0600188#if 0
189 printf("ShaderProgram %p ID=%u RefCount++ to %d\n",
190 (void *) shProg, shProg->Name, shProg->RefCount);
191#endif
Brian3c008a02007-04-12 15:22:32 -0600192 *ptr = shProg;
193 }
194}
195
196
197/**
Brianf2923612006-12-20 09:56:44 -0700198 * Lookup a GLSL program object.
199 */
200struct gl_shader_program *
201_mesa_lookup_shader_program(GLcontext *ctx, GLuint name)
202{
203 struct gl_shader_program *shProg;
204 if (name) {
205 shProg = (struct gl_shader_program *)
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800206 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
Brianf2923612006-12-20 09:56:44 -0700207 /* Note that both gl_shader and gl_shader_program objects are kept
208 * in the same hash table. Check the object's type to be sure it's
209 * what we're expecting.
210 */
Brianf3e8c322007-04-18 14:53:23 -0600211 if (shProg && shProg->Type != GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700212 return NULL;
213 }
214 return shProg;
215 }
216 return NULL;
217}
218
219
220/**
Brian Paul530df582008-07-03 16:21:11 -0600221 * As above, but record an error if program is not found.
222 */
223static struct gl_shader_program *
224_mesa_lookup_shader_program_err(GLcontext *ctx, GLuint name,
225 const char *caller)
226{
227 if (!name) {
228 _mesa_error(ctx, GL_INVALID_VALUE, caller);
229 return NULL;
230 }
231 else {
232 struct gl_shader_program *shProg = (struct gl_shader_program *)
233 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
234 if (!shProg) {
235 _mesa_error(ctx, GL_INVALID_VALUE, caller);
236 return NULL;
237 }
238 if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
239 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
240 return NULL;
241 }
242 return shProg;
243 }
244}
245
246
247
248
249/**
Brianf2923612006-12-20 09:56:44 -0700250 * Allocate a new gl_shader object, initialize it.
251 */
252struct gl_shader *
253_mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
254{
255 struct gl_shader *shader;
256 assert(type == GL_FRAGMENT_SHADER || type == GL_VERTEX_SHADER);
257 shader = CALLOC_STRUCT(gl_shader);
258 if (shader) {
259 shader->Type = type;
260 shader->Name = name;
261 shader->RefCount = 1;
262 }
263 return shader;
264}
265
266
267void
268_mesa_free_shader(GLcontext *ctx, struct gl_shader *sh)
269{
Brianf2923612006-12-20 09:56:44 -0700270 if (sh->Source)
271 _mesa_free((void *) sh->Source);
272 if (sh->InfoLog)
273 _mesa_free(sh->InfoLog);
Brian Paul3d500f02008-07-24 14:56:54 -0600274 _mesa_reference_program(ctx, &sh->Program, NULL);
Brianf2923612006-12-20 09:56:44 -0700275 _mesa_free(sh);
276}
277
278
279/**
Brian3c008a02007-04-12 15:22:32 -0600280 * Set ptr to point to sh.
281 * If ptr is pointing to another shader, decrement its refcount (and delete
282 * if refcount hits zero).
283 * Then set ptr to point to sh, incrementing its refcount.
284 */
285/* XXX this could be static */
286void
287_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
288 struct gl_shader *sh)
289{
290 assert(ptr);
291 if (*ptr == sh) {
292 /* no-op */
293 return;
294 }
295 if (*ptr) {
296 /* Unreference the old shader */
297 GLboolean deleteFlag = GL_FALSE;
298 struct gl_shader *old = *ptr;
299
300 ASSERT(old->RefCount > 0);
301 old->RefCount--;
Brian99193e42007-04-12 15:45:02 -0600302 /*printf("SHADER DECR %p (%d) to %d\n",
303 (void*) old, old->Name, old->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600304 deleteFlag = (old->RefCount == 0);
305
306 if (deleteFlag) {
307 _mesa_HashRemove(ctx->Shared->ShaderObjects, old->Name);
308 _mesa_free_shader(ctx, old);
309 }
310
311 *ptr = NULL;
312 }
313 assert(!*ptr);
314
315 if (sh) {
316 /* reference new */
317 sh->RefCount++;
Brian99193e42007-04-12 15:45:02 -0600318 /*printf("SHADER INCR %p (%d) to %d\n",
319 (void*) sh, sh->Name, sh->RefCount);*/
Brian3c008a02007-04-12 15:22:32 -0600320 *ptr = sh;
321 }
322}
323
324
325/**
Brianf2923612006-12-20 09:56:44 -0700326 * Lookup a GLSL shader object.
327 */
328struct gl_shader *
329_mesa_lookup_shader(GLcontext *ctx, GLuint name)
330{
331 if (name) {
332 struct gl_shader *sh = (struct gl_shader *)
333 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
334 /* Note that both gl_shader and gl_shader_program objects are kept
335 * in the same hash table. Check the object's type to be sure it's
336 * what we're expecting.
337 */
Brianf3e8c322007-04-18 14:53:23 -0600338 if (sh && sh->Type == GL_SHADER_PROGRAM_MESA) {
Brianf2923612006-12-20 09:56:44 -0700339 return NULL;
340 }
341 return sh;
342 }
343 return NULL;
344}
345
346
Brianfa4d0362007-02-26 18:33:50 -0700347/**
Brian Paul530df582008-07-03 16:21:11 -0600348 * As above, but record an error if shader is not found.
349 */
350static struct gl_shader *
351_mesa_lookup_shader_err(GLcontext *ctx, GLuint name, const char *caller)
352{
353 if (!name) {
354 _mesa_error(ctx, GL_INVALID_VALUE, caller);
355 return NULL;
356 }
357 else {
358 struct gl_shader *sh = (struct gl_shader *)
359 _mesa_HashLookup(ctx->Shared->ShaderObjects, name);
360 if (!sh) {
361 _mesa_error(ctx, GL_INVALID_VALUE, caller);
362 return NULL;
363 }
364 if (sh->Type == GL_SHADER_PROGRAM_MESA) {
365 _mesa_error(ctx, GL_INVALID_OPERATION, caller);
366 return NULL;
367 }
368 return sh;
369 }
370}
371
372
373
374/**
Brianfa4d0362007-02-26 18:33:50 -0700375 * Initialize context's shader state.
376 */
Brianf2923612006-12-20 09:56:44 -0700377void
378_mesa_init_shader_state(GLcontext * ctx)
379{
Brianfa4d0362007-02-26 18:33:50 -0700380 /* Device drivers may override these to control what kind of instructions
381 * are generated by the GLSL compiler.
382 */
383 ctx->Shader.EmitHighLevelInstructions = GL_TRUE;
Brian63556fa2007-03-23 14:47:46 -0600384 ctx->Shader.EmitCondCodes = GL_TRUE; /* XXX probably want GL_FALSE... */
Brianfa4d0362007-02-26 18:33:50 -0700385 ctx->Shader.EmitComments = GL_FALSE;
Brianf2923612006-12-20 09:56:44 -0700386}
387
388
Brian5b01c5e2006-12-19 18:02:03 -0700389/**
Brian935f93f2007-03-24 16:20:02 -0600390 * Free the per-context shader-related state.
391 */
392void
393_mesa_free_shader_state(GLcontext *ctx)
394{
Brian3c008a02007-04-12 15:22:32 -0600395 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, NULL);
Brian935f93f2007-03-24 16:20:02 -0600396}
397
398
399/**
Brian5b01c5e2006-12-19 18:02:03 -0700400 * Copy string from <src> to <dst>, up to maxLength characters, returning
401 * length of <dst> in <length>.
402 * \param src the strings source
403 * \param maxLength max chars to copy
404 * \param length returns number of chars copied
405 * \param dst the string destination
406 */
407static void
408copy_string(GLchar *dst, GLsizei maxLength, GLsizei *length, const GLchar *src)
409{
410 GLsizei len;
411 for (len = 0; len < maxLength - 1 && src && src[len]; len++)
412 dst[len] = src[len];
413 if (maxLength > 0)
414 dst[len] = 0;
415 if (length)
416 *length = len;
417}
418
419
Brian Paul7acb7c12008-07-03 13:49:48 -0600420static GLboolean
421_mesa_is_program(GLcontext *ctx, GLuint name)
422{
423 struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name);
424 return shProg ? GL_TRUE : GL_FALSE;
425}
426
427
428static GLboolean
429_mesa_is_shader(GLcontext *ctx, GLuint name)
430{
431 struct gl_shader *shader = _mesa_lookup_shader(ctx, name);
432 return shader ? GL_TRUE : GL_FALSE;
433}
434
435
Brian5b01c5e2006-12-19 18:02:03 -0700436/**
437 * Called via ctx->Driver.AttachShader()
438 */
Brian Paulfd59f192008-05-18 16:04:55 -0600439static void
Brian5b01c5e2006-12-19 18:02:03 -0700440_mesa_attach_shader(GLcontext *ctx, GLuint program, GLuint shader)
441{
Brian Paul530df582008-07-03 16:21:11 -0600442 struct gl_shader_program *shProg;
443 struct gl_shader *sh;
444 GLuint i, n;
Brian5b01c5e2006-12-19 18:02:03 -0700445
Brian Paul530df582008-07-03 16:21:11 -0600446 shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader");
447 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700448 return;
Brian5b01c5e2006-12-19 18:02:03 -0700449
Brian Paul530df582008-07-03 16:21:11 -0600450 sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader");
Brian Paul7acb7c12008-07-03 13:49:48 -0600451 if (!sh) {
Brian Paul7acb7c12008-07-03 13:49:48 -0600452 return;
453 }
454
Brian237b9852007-08-07 21:48:31 +0100455 n = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700456 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700457 if (shProg->Shaders[i] == sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700458 /* already attached */
459 return;
Brian34ae99d2006-12-18 08:28:54 -0700460 }
461 }
Brian5b01c5e2006-12-19 18:02:03 -0700462
463 /* grow list */
Brian65a18442006-12-19 18:46:56 -0700464 shProg->Shaders = (struct gl_shader **)
465 _mesa_realloc(shProg->Shaders,
466 n * sizeof(struct gl_shader *),
467 (n + 1) * sizeof(struct gl_shader *));
468 if (!shProg->Shaders) {
Brian5b01c5e2006-12-19 18:02:03 -0700469 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader");
470 return;
471 }
472
473 /* append */
Brian3c008a02007-04-12 15:22:32 -0600474 shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */
475 _mesa_reference_shader(ctx, &shProg->Shaders[n], sh);
Brian65a18442006-12-19 18:46:56 -0700476 shProg->NumShaders++;
Brian5b01c5e2006-12-19 18:02:03 -0700477}
478
479
Brian Paulfd59f192008-05-18 16:04:55 -0600480static GLint
Brian Paul896c0cc2008-05-16 15:47:55 -0600481_mesa_get_attrib_location(GLcontext *ctx, GLuint program,
482 const GLchar *name)
483{
484 struct gl_shader_program *shProg
Brian Paul530df582008-07-03 16:21:11 -0600485 = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation");
Brian Paul896c0cc2008-05-16 15:47:55 -0600486
487 if (!shProg) {
Brian Paul896c0cc2008-05-16 15:47:55 -0600488 return -1;
489 }
490
491 if (!shProg->LinkStatus) {
492 _mesa_error(ctx, GL_INVALID_OPERATION,
493 "glGetAttribLocation(program not linked)");
494 return -1;
495 }
496
497 if (!name)
498 return -1;
499
Brian Paul27341a92008-09-16 16:28:36 -0600500 if (shProg->VertexProgram) {
501 const struct gl_program_parameter_list *attribs =
502 shProg->VertexProgram->Base.Attributes;
503 if (attribs) {
504 GLint i = _mesa_lookup_parameter_index(attribs, -1, name);
505 if (i >= 0) {
506 return attribs->Parameters[i].StateIndexes[0];
507 }
Brian Paul896c0cc2008-05-16 15:47:55 -0600508 }
509 }
510 return -1;
511}
512
513
Brian Paulfd59f192008-05-18 16:04:55 -0600514static void
Brian5b01c5e2006-12-19 18:02:03 -0700515_mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index,
516 const GLchar *name)
517{
Brian Paul530df582008-07-03 16:21:11 -0600518 struct gl_shader_program *shProg;
Brianb7978af2007-01-09 19:17:17 -0700519 const GLint size = -1; /* unknown size */
Brian Paul6bc87492008-07-25 08:34:54 -0600520 GLint i, oldIndex;
Brian Paul6f1abb92008-07-29 17:27:22 -0600521 GLenum datatype = GL_FLOAT_VEC4;
Brian5b01c5e2006-12-19 18:02:03 -0700522
Brian Paul530df582008-07-03 16:21:11 -0600523 shProg = _mesa_lookup_shader_program_err(ctx, program,
524 "glBindAttribLocation");
Brian65a18442006-12-19 18:46:56 -0700525 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700526 return;
527 }
528
Brian9e4bae92006-12-20 09:27:42 -0700529 if (!name)
530 return;
531
532 if (strncmp(name, "gl_", 3) == 0) {
533 _mesa_error(ctx, GL_INVALID_OPERATION,
534 "glBindAttribLocation(illegal name)");
535 return;
536 }
537
Brian Paul7acb7c12008-07-03 13:49:48 -0600538 if (index >= ctx->Const.VertexProgram.MaxAttribs) {
539 _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)");
540 return;
541 }
542
Brian Paul6bc87492008-07-25 08:34:54 -0600543 if (shProg->LinkStatus) {
544 /* get current index/location for the attribute */
545 oldIndex = _mesa_get_attrib_location(ctx, program, name);
546 }
547 else {
548 oldIndex = -1;
549 }
550
Brian3209c3e2007-01-09 17:49:24 -0700551 /* this will replace the current value if it's already in the list */
Brian Paulffbc66b2008-07-21 13:58:50 -0600552 i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index);
Brian3209c3e2007-01-09 17:49:24 -0700553 if (i < 0) {
554 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation");
Brian Paul6f1abb92008-07-29 17:27:22 -0600555 return;
Brian3209c3e2007-01-09 17:49:24 -0700556 }
557
Brian Paul27341a92008-09-16 16:28:36 -0600558 /*
559 * Note that this attribute binding won't go into effect until
560 * glLinkProgram is called again.
561 */
Brian34ae99d2006-12-18 08:28:54 -0700562}
563
564
Brian Paulfd59f192008-05-18 16:04:55 -0600565static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700566_mesa_create_shader(GLcontext *ctx, GLenum type)
567{
Brian65a18442006-12-19 18:46:56 -0700568 struct gl_shader *sh;
Brian5b01c5e2006-12-19 18:02:03 -0700569 GLuint name;
570
571 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
572
573 switch (type) {
Brian65a18442006-12-19 18:46:56 -0700574 case GL_FRAGMENT_SHADER:
575 case GL_VERTEX_SHADER:
576 sh = _mesa_new_shader(ctx, name, type);
Brian5b01c5e2006-12-19 18:02:03 -0700577 break;
578 default:
579 _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)");
580 return 0;
581 }
582
Brian65a18442006-12-19 18:46:56 -0700583 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh);
Brian5b01c5e2006-12-19 18:02:03 -0700584
585 return name;
586}
587
588
Brian Paulfd59f192008-05-18 16:04:55 -0600589static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700590_mesa_create_program(GLcontext *ctx)
591{
592 GLuint name;
Brian65a18442006-12-19 18:46:56 -0700593 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700594
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800595 name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1);
Brian65a18442006-12-19 18:46:56 -0700596 shProg = _mesa_new_shader_program(ctx, name);
Brian5b01c5e2006-12-19 18:02:03 -0700597
Xiang, Haihaoaef47c42008-03-31 16:27:47 +0800598 _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg);
Brian5b01c5e2006-12-19 18:02:03 -0700599
Brian3c008a02007-04-12 15:22:32 -0600600 assert(shProg->RefCount == 1);
601
Brian5b01c5e2006-12-19 18:02:03 -0700602 return name;
603}
604
605
Brian3c008a02007-04-12 15:22:32 -0600606/**
607 * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's
608 * DeleteProgramARB.
609 */
Brian Paulfd59f192008-05-18 16:04:55 -0600610static void
Brian5b01c5e2006-12-19 18:02:03 -0700611_mesa_delete_program2(GLcontext *ctx, GLuint name)
612{
Brian3c008a02007-04-12 15:22:32 -0600613 /*
614 * NOTE: deleting shaders/programs works a bit differently than
615 * texture objects (and buffer objects, etc). Shader/program
616 * handles/IDs exist in the hash table until the object is really
617 * deleted (refcount==0). With texture objects, the handle/ID is
618 * removed from the hash table in glDeleteTextures() while the tex
619 * object itself might linger until its refcount goes to zero.
620 */
Brian65a18442006-12-19 18:46:56 -0700621 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700622
Brian Paul530df582008-07-03 16:21:11 -0600623 shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram");
624 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700625 return;
Brian5b01c5e2006-12-19 18:02:03 -0700626
Brian9e4bae92006-12-20 09:27:42 -0700627 shProg->DeletePending = GL_TRUE;
628
Brian3c008a02007-04-12 15:22:32 -0600629 /* effectively, decr shProg's refcount */
630 _mesa_reference_shader_program(ctx, &shProg, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700631}
632
633
Brian Paulfd59f192008-05-18 16:04:55 -0600634static void
Brian5b01c5e2006-12-19 18:02:03 -0700635_mesa_delete_shader(GLcontext *ctx, GLuint shader)
636{
Brian Paul530df582008-07-03 16:21:11 -0600637 struct gl_shader *sh;
638
639 sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader");
640 if (!sh)
Brian9e4bae92006-12-20 09:27:42 -0700641 return;
Brian5b01c5e2006-12-19 18:02:03 -0700642
Brian9e4bae92006-12-20 09:27:42 -0700643 sh->DeletePending = GL_TRUE;
Brian3c008a02007-04-12 15:22:32 -0600644
645 /* effectively, decr sh's refcount */
646 _mesa_reference_shader(ctx, &sh, NULL);
Brian5b01c5e2006-12-19 18:02:03 -0700647}
648
649
Brian Paulfd59f192008-05-18 16:04:55 -0600650static void
Brian5b01c5e2006-12-19 18:02:03 -0700651_mesa_detach_shader(GLcontext *ctx, GLuint program, GLuint shader)
652{
Brian Paul530df582008-07-03 16:21:11 -0600653 struct gl_shader_program *shProg;
Brian237b9852007-08-07 21:48:31 +0100654 GLuint n;
Brian5b01c5e2006-12-19 18:02:03 -0700655 GLuint i, j;
656
Brian Paul530df582008-07-03 16:21:11 -0600657 shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader");
658 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700659 return;
Brian5b01c5e2006-12-19 18:02:03 -0700660
Brian237b9852007-08-07 21:48:31 +0100661 n = shProg->NumShaders;
662
Brian5b01c5e2006-12-19 18:02:03 -0700663 for (i = 0; i < n; i++) {
Brian65a18442006-12-19 18:46:56 -0700664 if (shProg->Shaders[i]->Name == shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700665 /* found it */
Brian3c008a02007-04-12 15:22:32 -0600666 struct gl_shader **newList;
Brian9e4bae92006-12-20 09:27:42 -0700667
Brian Paul530df582008-07-03 16:21:11 -0600668 /* release */
Brian3c008a02007-04-12 15:22:32 -0600669 _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL);
Brian9e4bae92006-12-20 09:27:42 -0700670
Brian5b01c5e2006-12-19 18:02:03 -0700671 /* alloc new, smaller array */
Brian65a18442006-12-19 18:46:56 -0700672 newList = (struct gl_shader **)
673 _mesa_malloc((n - 1) * sizeof(struct gl_shader *));
Brian5b01c5e2006-12-19 18:02:03 -0700674 if (!newList) {
675 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader");
676 return;
677 }
678 for (j = 0; j < i; j++) {
Brian65a18442006-12-19 18:46:56 -0700679 newList[j] = shProg->Shaders[j];
Brian5b01c5e2006-12-19 18:02:03 -0700680 }
681 while (++i < n)
Brian65a18442006-12-19 18:46:56 -0700682 newList[j++] = shProg->Shaders[i];
683 _mesa_free(shProg->Shaders);
Brian5b01c5e2006-12-19 18:02:03 -0700684
Brian65a18442006-12-19 18:46:56 -0700685 shProg->Shaders = newList;
Brianbac15c82007-04-18 14:55:18 -0600686 shProg->NumShaders = n - 1;
Brianaaa57412007-04-18 15:22:43 -0600687
688#ifdef DEBUG
689 /* sanity check */
690 {
691 for (j = 0; j < shProg->NumShaders; j++) {
692 assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER ||
693 shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER);
694 assert(shProg->Shaders[j]->RefCount > 0);
695 }
696 }
697#endif
698
Brian5b01c5e2006-12-19 18:02:03 -0700699 return;
700 }
701 }
702
703 /* not found */
Brian Paul530df582008-07-03 16:21:11 -0600704 {
705 GLenum err;
706 if (_mesa_is_shader(ctx, shader))
707 err = GL_INVALID_OPERATION;
708 else if (_mesa_is_program(ctx, shader))
709 err = GL_INVALID_OPERATION;
710 else
711 err = GL_INVALID_VALUE;
712 _mesa_error(ctx, err, "glDetachProgram(shader)");
713 return;
714 }
Brian5b01c5e2006-12-19 18:02:03 -0700715}
716
717
Brian Paulffbc66b2008-07-21 13:58:50 -0600718static GLint
719sizeof_glsl_type(GLenum type)
720{
721 switch (type) {
722 case GL_FLOAT:
723 case GL_INT:
724 case GL_BOOL:
Brian Paul8c51e002008-08-11 15:09:47 -0600725 case GL_SAMPLER_1D:
726 case GL_SAMPLER_2D:
727 case GL_SAMPLER_3D:
728 case GL_SAMPLER_CUBE:
729 case GL_SAMPLER_1D_SHADOW:
730 case GL_SAMPLER_2D_SHADOW:
731 case GL_SAMPLER_2D_RECT_ARB:
732 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
733 case GL_SAMPLER_1D_ARRAY_SHADOW_EXT:
734 case GL_SAMPLER_2D_ARRAY_SHADOW_EXT:
735 case GL_SAMPLER_CUBE_SHADOW_EXT:
Brian Paulffbc66b2008-07-21 13:58:50 -0600736 return 1;
737 case GL_FLOAT_VEC2:
738 case GL_INT_VEC2:
739 case GL_BOOL_VEC2:
740 return 2;
741 case GL_FLOAT_VEC3:
742 case GL_INT_VEC3:
743 case GL_BOOL_VEC3:
744 return 3;
745 case GL_FLOAT_VEC4:
746 case GL_INT_VEC4:
747 case GL_BOOL_VEC4:
748 return 4;
749 case GL_FLOAT_MAT2:
750 case GL_FLOAT_MAT2x3:
751 case GL_FLOAT_MAT2x4:
752 return 8; /* two float[4] vectors */
753 case GL_FLOAT_MAT3:
754 case GL_FLOAT_MAT3x2:
755 case GL_FLOAT_MAT3x4:
756 return 12; /* three float[4] vectors */
757 case GL_FLOAT_MAT4:
758 case GL_FLOAT_MAT4x2:
759 case GL_FLOAT_MAT4x3:
760 return 16; /* four float[4] vectors */
761 default:
762 _mesa_problem(NULL, "Invalid type in sizeof_glsl_type()");
763 return 1;
764 }
765}
766
767
Brian Paulfd59f192008-05-18 16:04:55 -0600768static void
Brian5b01c5e2006-12-19 18:02:03 -0700769_mesa_get_active_attrib(GLcontext *ctx, GLuint program, GLuint index,
770 GLsizei maxLength, GLsizei *length, GLint *size,
771 GLenum *type, GLchar *nameOut)
772{
Brian Paul27341a92008-09-16 16:28:36 -0600773 const struct gl_program_parameter_list *attribs = NULL;
Brian Paul530df582008-07-03 16:21:11 -0600774 struct gl_shader_program *shProg;
Brian5b01c5e2006-12-19 18:02:03 -0700775
Brian Paul530df582008-07-03 16:21:11 -0600776 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib");
777 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700778 return;
Brian5b01c5e2006-12-19 18:02:03 -0700779
Brian Paul27341a92008-09-16 16:28:36 -0600780 if (shProg->VertexProgram)
781 attribs = shProg->VertexProgram->Base.Attributes;
782
783 if (!attribs || index >= attribs->NumParameters) {
Brianaaa57412007-04-18 15:22:43 -0600784 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)");
Brian5b01c5e2006-12-19 18:02:03 -0700785 return;
786 }
787
Brian Paul27341a92008-09-16 16:28:36 -0600788 copy_string(nameOut, maxLength, length, attribs->Parameters[index].Name);
789
Brian5b01c5e2006-12-19 18:02:03 -0700790 if (size)
Brian Paul27341a92008-09-16 16:28:36 -0600791 *size = attribs->Parameters[index].Size
792 / sizeof_glsl_type(attribs->Parameters[index].DataType);
793
Brian Paulade50832008-05-14 16:09:46 -0600794 if (type)
Brian Paul27341a92008-09-16 16:28:36 -0600795 *type = attribs->Parameters[index].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700796}
797
798
799/**
800 * Called via ctx->Driver.GetActiveUniform().
801 */
Brian Paulfd59f192008-05-18 16:04:55 -0600802static void
Brian5b01c5e2006-12-19 18:02:03 -0700803_mesa_get_active_uniform(GLcontext *ctx, GLuint program, GLuint index,
804 GLsizei maxLength, GLsizei *length, GLint *size,
805 GLenum *type, GLchar *nameOut)
806{
Brian Paul530df582008-07-03 16:21:11 -0600807 const struct gl_shader_program *shProg;
Brian Paulade50832008-05-14 16:09:46 -0600808 const struct gl_program *prog;
809 GLint progPos;
Brian5b01c5e2006-12-19 18:02:03 -0700810
Brian Paul530df582008-07-03 16:21:11 -0600811 shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
812 if (!shProg)
Brian5b01c5e2006-12-19 18:02:03 -0700813 return;
Brian5b01c5e2006-12-19 18:02:03 -0700814
Brian Paulade50832008-05-14 16:09:46 -0600815 if (!shProg->Uniforms || index >= shProg->Uniforms->NumUniforms) {
Brian5b01c5e2006-12-19 18:02:03 -0700816 _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
817 return;
818 }
819
Brian Paulade50832008-05-14 16:09:46 -0600820 progPos = shProg->Uniforms->Uniforms[index].VertPos;
821 if (progPos >= 0) {
822 prog = &shProg->VertexProgram->Base;
823 }
824 else {
825 progPos = shProg->Uniforms->Uniforms[index].FragPos;
826 if (progPos >= 0) {
827 prog = &shProg->FragmentProgram->Base;
Brian274ac7a2007-04-18 16:05:53 -0600828 }
829 }
830
Brian Paulade50832008-05-14 16:09:46 -0600831 if (!prog || progPos < 0)
832 return; /* should never happen */
833
834 if (nameOut)
835 copy_string(nameOut, maxLength, length,
836 prog->Parameters->Parameters[progPos].Name);
837 if (size)
Brian Paulffbc66b2008-07-21 13:58:50 -0600838 *size = prog->Parameters->Parameters[progPos].Size
839 / sizeof_glsl_type(prog->Parameters->Parameters[progPos].DataType);
Brian Paulade50832008-05-14 16:09:46 -0600840 if (type)
841 *type = prog->Parameters->Parameters[progPos].DataType;
Brian5b01c5e2006-12-19 18:02:03 -0700842}
843
844
845/**
846 * Called via ctx->Driver.GetAttachedShaders().
847 */
Brian Paulfd59f192008-05-18 16:04:55 -0600848static void
Brian5b01c5e2006-12-19 18:02:03 -0700849_mesa_get_attached_shaders(GLcontext *ctx, GLuint program, GLsizei maxCount,
850 GLsizei *count, GLuint *obj)
851{
Brian Paul530df582008-07-03 16:21:11 -0600852 struct gl_shader_program *shProg =
853 _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders");
Brian65a18442006-12-19 18:46:56 -0700854 if (shProg) {
Brian Paul530df582008-07-03 16:21:11 -0600855 GLuint i;
856 for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) {
Brian65a18442006-12-19 18:46:56 -0700857 obj[i] = shProg->Shaders[i]->Name;
Brian5b01c5e2006-12-19 18:02:03 -0700858 }
859 if (count)
860 *count = i;
861 }
Brian5b01c5e2006-12-19 18:02:03 -0700862}
863
864
Brian Paulfd59f192008-05-18 16:04:55 -0600865static GLuint
Brian5b01c5e2006-12-19 18:02:03 -0700866_mesa_get_handle(GLcontext *ctx, GLenum pname)
Brian34ae99d2006-12-18 08:28:54 -0700867{
868#if 0
869 GET_CURRENT_CONTEXT(ctx);
870
871 switch (pname) {
872 case GL_PROGRAM_OBJECT_ARB:
873 {
Brian5b01c5e2006-12-19 18:02:03 -0700874 struct gl2_program_intf **pro = ctx->Shader.CurrentProgram;
Brian34ae99d2006-12-18 08:28:54 -0700875
876 if (pro != NULL)
877 return (**pro)._container._generic.
878 GetName((struct gl2_generic_intf **) (pro));
879 }
880 break;
881 default:
882 _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB");
883 }
884#endif
885 return 0;
886}
887
888
Brian Paulfd59f192008-05-18 16:04:55 -0600889static void
Brian5b01c5e2006-12-19 18:02:03 -0700890_mesa_get_programiv(GLcontext *ctx, GLuint program,
891 GLenum pname, GLint *params)
Brian34ae99d2006-12-18 08:28:54 -0700892{
Brian Paul27341a92008-09-16 16:28:36 -0600893 const struct gl_program_parameter_list *attribs;
Brian65a18442006-12-19 18:46:56 -0700894 struct gl_shader_program *shProg
895 = _mesa_lookup_shader_program(ctx, program);
Brian34ae99d2006-12-18 08:28:54 -0700896
Brian65a18442006-12-19 18:46:56 -0700897 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700898 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)");
Brian34ae99d2006-12-18 08:28:54 -0700899 return;
900 }
901
Brian Paul27341a92008-09-16 16:28:36 -0600902 if (shProg->VertexProgram)
903 attribs = shProg->VertexProgram->Base.Attributes;
904 else
905 attribs = NULL;
906
Brian5b01c5e2006-12-19 18:02:03 -0700907 switch (pname) {
908 case GL_DELETE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700909 *params = shProg->DeletePending;
Brian5b01c5e2006-12-19 18:02:03 -0700910 break;
911 case GL_LINK_STATUS:
Brian65a18442006-12-19 18:46:56 -0700912 *params = shProg->LinkStatus;
Brian34ae99d2006-12-18 08:28:54 -0700913 break;
Brian5b01c5e2006-12-19 18:02:03 -0700914 case GL_VALIDATE_STATUS:
Brian65a18442006-12-19 18:46:56 -0700915 *params = shProg->Validated;
Brian5b01c5e2006-12-19 18:02:03 -0700916 break;
917 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600918 *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700919 break;
920 case GL_ATTACHED_SHADERS:
Brian65a18442006-12-19 18:46:56 -0700921 *params = shProg->NumShaders;
Brian5b01c5e2006-12-19 18:02:03 -0700922 break;
923 case GL_ACTIVE_ATTRIBUTES:
Brian Paul27341a92008-09-16 16:28:36 -0600924 *params = attribs ? attribs->NumParameters : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700925 break;
926 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
Brian Paul27341a92008-09-16 16:28:36 -0600927 *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1;
Brian5b01c5e2006-12-19 18:02:03 -0700928 break;
929 case GL_ACTIVE_UNIFORMS:
Brian Paulade50832008-05-14 16:09:46 -0600930 *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700931 break;
932 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
Brian Paulade50832008-05-14 16:09:46 -0600933 *params = _mesa_longest_uniform_name(shProg->Uniforms);
Brian274ac7a2007-04-18 16:05:53 -0600934 if (*params > 0)
935 (*params)++; /* add one for terminating zero */
Brian34ae99d2006-12-18 08:28:54 -0700936 break;
Brian Paulbda6ad22008-08-06 12:45:14 -0600937 case GL_PROGRAM_BINARY_LENGTH_OES:
938 *params = 0;
939 break;
Brian34ae99d2006-12-18 08:28:54 -0700940 default:
Brian5b01c5e2006-12-19 18:02:03 -0700941 _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)");
942 return;
Brian34ae99d2006-12-18 08:28:54 -0700943 }
Brian5b01c5e2006-12-19 18:02:03 -0700944}
Brian34ae99d2006-12-18 08:28:54 -0700945
Brian34ae99d2006-12-18 08:28:54 -0700946
Brian Paulfd59f192008-05-18 16:04:55 -0600947static void
Brian5b01c5e2006-12-19 18:02:03 -0700948_mesa_get_shaderiv(GLcontext *ctx, GLuint name, GLenum pname, GLint *params)
949{
Brian Paul530df582008-07-03 16:21:11 -0600950 struct gl_shader *shader = _mesa_lookup_shader_err(ctx, name, "glGetShaderiv");
Brian5b01c5e2006-12-19 18:02:03 -0700951
952 if (!shader) {
Brian5b01c5e2006-12-19 18:02:03 -0700953 return;
954 }
Brian65a18442006-12-19 18:46:56 -0700955
Brian5b01c5e2006-12-19 18:02:03 -0700956 switch (pname) {
957 case GL_SHADER_TYPE:
958 *params = shader->Type;
959 break;
960 case GL_DELETE_STATUS:
961 *params = shader->DeletePending;
962 break;
963 case GL_COMPILE_STATUS:
964 *params = shader->CompileStatus;
965 break;
966 case GL_INFO_LOG_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600967 *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700968 break;
969 case GL_SHADER_SOURCE_LENGTH:
Jan Dvorak5a0f02a2007-07-13 16:36:00 -0600970 *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0;
Brian5b01c5e2006-12-19 18:02:03 -0700971 break;
972 default:
973 _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)");
974 return;
975 }
976}
977
978
Brian Paulfd59f192008-05-18 16:04:55 -0600979static void
Brian5b01c5e2006-12-19 18:02:03 -0700980_mesa_get_program_info_log(GLcontext *ctx, GLuint program, GLsizei bufSize,
981 GLsizei *length, GLchar *infoLog)
982{
Brian65a18442006-12-19 18:46:56 -0700983 struct gl_shader_program *shProg
984 = _mesa_lookup_shader_program(ctx, program);
985 if (!shProg) {
Brian5b01c5e2006-12-19 18:02:03 -0700986 _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)");
987 return;
988 }
Brian65a18442006-12-19 18:46:56 -0700989 copy_string(infoLog, bufSize, length, shProg->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -0700990}
991
992
Brian Paulfd59f192008-05-18 16:04:55 -0600993static void
Brian5b01c5e2006-12-19 18:02:03 -0700994_mesa_get_shader_info_log(GLcontext *ctx, GLuint shader, GLsizei bufSize,
995 GLsizei *length, GLchar *infoLog)
996{
Brian65a18442006-12-19 18:46:56 -0700997 struct gl_shader *sh = _mesa_lookup_shader(ctx, shader);
998 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -0700999 _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)");
1000 return;
1001 }
Brian65a18442006-12-19 18:46:56 -07001002 copy_string(infoLog, bufSize, length, sh->InfoLog);
Brian5b01c5e2006-12-19 18:02:03 -07001003}
1004
1005
1006/**
1007 * Called via ctx->Driver.GetShaderSource().
1008 */
Brian Paulfd59f192008-05-18 16:04:55 -06001009static void
Brian5b01c5e2006-12-19 18:02:03 -07001010_mesa_get_shader_source(GLcontext *ctx, GLuint shader, GLsizei maxLength,
1011 GLsizei *length, GLchar *sourceOut)
1012{
Brian Paul530df582008-07-03 16:21:11 -06001013 struct gl_shader *sh;
1014 sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource");
Brian65a18442006-12-19 18:46:56 -07001015 if (!sh) {
Brian5b01c5e2006-12-19 18:02:03 -07001016 return;
1017 }
Brian65a18442006-12-19 18:46:56 -07001018 copy_string(sourceOut, maxLength, length, sh->Source);
Brian5b01c5e2006-12-19 18:02:03 -07001019}
1020
1021
Brian Paul2be54a82008-07-08 16:17:04 -06001022#define MAX_UNIFORM_ELEMENTS 16
1023
Brian5b01c5e2006-12-19 18:02:03 -07001024/**
Brian Paul2be54a82008-07-08 16:17:04 -06001025 * Helper for GetUniformfv(), GetUniformiv()
1026 * Returns number of elements written to 'params' output.
Brian5b01c5e2006-12-19 18:02:03 -07001027 */
Brian Paul2be54a82008-07-08 16:17:04 -06001028static GLuint
1029get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1030 GLfloat *params)
Brian5b01c5e2006-12-19 18:02:03 -07001031{
Brian65a18442006-12-19 18:46:56 -07001032 struct gl_shader_program *shProg
Brian Paulbda6ad22008-08-06 12:45:14 -06001033 = _mesa_lookup_shader_program_err(ctx, program, "glGetUniform[if]v");
Brian65a18442006-12-19 18:46:56 -07001034 if (shProg) {
Brian Paul6cb12702008-06-28 16:48:31 -06001035 if (shProg->Uniforms &&
Brian Paul016701f2008-07-29 17:43:35 -06001036 location >= 0 && location < (GLint) shProg->Uniforms->NumUniforms) {
Brian Paul6cb12702008-06-28 16:48:31 -06001037 GLint progPos;
1038 GLuint i;
Brian Paulf2632212008-05-16 10:49:44 -06001039 const struct gl_program *prog = NULL;
Brian Paulade50832008-05-14 16:09:46 -06001040
1041 progPos = shProg->Uniforms->Uniforms[location].VertPos;
1042 if (progPos >= 0) {
1043 prog = &shProg->VertexProgram->Base;
Brian5b01c5e2006-12-19 18:02:03 -07001044 }
Brian Paulade50832008-05-14 16:09:46 -06001045 else {
1046 progPos = shProg->Uniforms->Uniforms[location].FragPos;
1047 if (progPos >= 0) {
1048 prog = &shProg->FragmentProgram->Base;
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001049 }
Brian Paulade50832008-05-14 16:09:46 -06001050 }
1051
Brian Paulf2632212008-05-16 10:49:44 -06001052 ASSERT(prog);
1053 if (prog) {
Brian Paul2be54a82008-07-08 16:17:04 -06001054 /* See uniformiv() below */
1055 assert(prog->Parameters->Parameters[progPos].Size <= MAX_UNIFORM_ELEMENTS);
1056
Brian Paulf2632212008-05-16 10:49:44 -06001057 for (i = 0; i < prog->Parameters->Parameters[progPos].Size; i++) {
1058 params[i] = prog->Parameters->ParameterValues[progPos][i];
1059 }
Brian Paul2be54a82008-07-08 16:17:04 -06001060 return prog->Parameters->Parameters[progPos].Size;
Brian Paulade50832008-05-14 16:09:46 -06001061 }
Brian5b01c5e2006-12-19 18:02:03 -07001062 }
1063 else {
Brian Paul6cb12702008-06-28 16:48:31 -06001064 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(location)");
Brian5b01c5e2006-12-19 18:02:03 -07001065 }
1066 }
Brian Paul2be54a82008-07-08 16:17:04 -06001067 return 0;
1068}
1069
1070
1071/**
1072 * Called via ctx->Driver.GetUniformfv().
1073 */
1074static void
1075_mesa_get_uniformfv(GLcontext *ctx, GLuint program, GLint location,
1076 GLfloat *params)
1077{
1078 (void) get_uniformfv(ctx, program, location, params);
1079}
1080
1081
1082/**
1083 * Called via ctx->Driver.GetUniformiv().
1084 */
1085static void
1086_mesa_get_uniformiv(GLcontext *ctx, GLuint program, GLint location,
1087 GLint *params)
1088{
1089 GLfloat fparams[MAX_UNIFORM_ELEMENTS];
1090 GLuint n = get_uniformfv(ctx, program, location, fparams);
1091 GLuint i;
1092 assert(n <= MAX_UNIFORM_ELEMENTS);
1093 for (i = 0; i < n; i++) {
1094 params[i] = (GLint) fparams[i];
1095 }
Brian5b01c5e2006-12-19 18:02:03 -07001096}
1097
1098
1099/**
1100 * Called via ctx->Driver.GetUniformLocation().
1101 */
Brian Paulfd59f192008-05-18 16:04:55 -06001102static GLint
Brian5b01c5e2006-12-19 18:02:03 -07001103_mesa_get_uniform_location(GLcontext *ctx, GLuint program, const GLchar *name)
1104{
Brian Paul530df582008-07-03 16:21:11 -06001105 struct gl_shader_program *shProg =
1106 _mesa_lookup_shader_program_err(ctx, program, "glGetUniformLocation");
1107
Brian Paulade50832008-05-14 16:09:46 -06001108 if (!shProg)
1109 return -1;
Brian5b01c5e2006-12-19 18:02:03 -07001110
Brian Paule06565b2008-07-04 09:58:55 -06001111 if (shProg->LinkStatus == GL_FALSE) {
1112 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformfv(program)");
1113 return -1;
1114 }
1115
Brian Paul530df582008-07-03 16:21:11 -06001116 /* XXX we should return -1 if the uniform was declared, but not
1117 * actually used.
1118 */
1119
Brian Paulade50832008-05-14 16:09:46 -06001120 return _mesa_lookup_uniform(shProg->Uniforms, name);
Brian5b01c5e2006-12-19 18:02:03 -07001121}
1122
1123
Brian34ae99d2006-12-18 08:28:54 -07001124
Brian5b01c5e2006-12-19 18:02:03 -07001125/**
1126 * Called via ctx->Driver.ShaderSource()
1127 */
Brian Paulfd59f192008-05-18 16:04:55 -06001128static void
Brian5b01c5e2006-12-19 18:02:03 -07001129_mesa_shader_source(GLcontext *ctx, GLuint shader, const GLchar *source)
Brian34ae99d2006-12-18 08:28:54 -07001130{
Brian Paul530df582008-07-03 16:21:11 -06001131 struct gl_shader *sh;
1132
1133 sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource");
1134 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001135 return;
Brian34ae99d2006-12-18 08:28:54 -07001136
Brian34ae99d2006-12-18 08:28:54 -07001137 /* free old shader source string and install new one */
Brian65a18442006-12-19 18:46:56 -07001138 if (sh->Source) {
1139 _mesa_free((void *) sh->Source);
Brian34ae99d2006-12-18 08:28:54 -07001140 }
Brian65a18442006-12-19 18:46:56 -07001141 sh->Source = source;
Brian9e4bae92006-12-20 09:27:42 -07001142 sh->CompileStatus = GL_FALSE;
Brian34ae99d2006-12-18 08:28:54 -07001143}
1144
1145
Brian5b01c5e2006-12-19 18:02:03 -07001146/**
1147 * Called via ctx->Driver.CompileShader()
1148 */
Brian Paulfd59f192008-05-18 16:04:55 -06001149static void
Brian5b01c5e2006-12-19 18:02:03 -07001150_mesa_compile_shader(GLcontext *ctx, GLuint shaderObj)
Brian34ae99d2006-12-18 08:28:54 -07001151{
Brian Paul530df582008-07-03 16:21:11 -06001152 struct gl_shader *sh;
Brian34ae99d2006-12-18 08:28:54 -07001153
Brian Paul530df582008-07-03 16:21:11 -06001154 sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader");
1155 if (!sh)
Brian34ae99d2006-12-18 08:28:54 -07001156 return;
Brian34ae99d2006-12-18 08:28:54 -07001157
Brian43975832007-01-04 08:21:09 -07001158 sh->CompileStatus = _slang_compile(ctx, sh);
Brian34ae99d2006-12-18 08:28:54 -07001159}
1160
1161
Brian5b01c5e2006-12-19 18:02:03 -07001162/**
1163 * Called via ctx->Driver.LinkProgram()
1164 */
Brian Paulfd59f192008-05-18 16:04:55 -06001165static void
Brian5b01c5e2006-12-19 18:02:03 -07001166_mesa_link_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001167{
Brian65a18442006-12-19 18:46:56 -07001168 struct gl_shader_program *shProg;
Brian34ae99d2006-12-18 08:28:54 -07001169
Brian Paul530df582008-07-03 16:21:11 -06001170 shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram");
1171 if (!shProg)
Brian34ae99d2006-12-18 08:28:54 -07001172 return;
Brian34ae99d2006-12-18 08:28:54 -07001173
Briandf43fb62008-05-06 23:08:51 -06001174 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1175
Brianc1771912007-02-16 09:56:19 -07001176 _slang_link(ctx, program, shProg);
Brian34ae99d2006-12-18 08:28:54 -07001177}
1178
1179
1180/**
Brian5b01c5e2006-12-19 18:02:03 -07001181 * Called via ctx->Driver.UseProgram()
Brian34ae99d2006-12-18 08:28:54 -07001182 */
Brian5b01c5e2006-12-19 18:02:03 -07001183void
1184_mesa_use_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001185{
Brian3c008a02007-04-12 15:22:32 -06001186 struct gl_shader_program *shProg;
1187
Brian00d63aa2007-02-03 11:35:02 -07001188 if (ctx->Shader.CurrentProgram &&
1189 ctx->Shader.CurrentProgram->Name == program) {
1190 /* no-op */
1191 return;
1192 }
1193
1194 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1195
Brian5b01c5e2006-12-19 18:02:03 -07001196 if (program) {
Brian Paul530df582008-07-03 16:21:11 -06001197 shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram");
Brian65a18442006-12-19 18:46:56 -07001198 if (!shProg) {
Brian Paul530df582008-07-03 16:21:11 -06001199 return;
1200 }
1201 if (!shProg->LinkStatus) {
1202 _mesa_error(ctx, GL_INVALID_OPERATION, "glUseProgram");
Brian5b01c5e2006-12-19 18:02:03 -07001203 return;
1204 }
Brian5b01c5e2006-12-19 18:02:03 -07001205 }
1206 else {
Brian3c008a02007-04-12 15:22:32 -06001207 shProg = NULL;
1208 }
1209
1210 _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentProgram, shProg);
Brian5b01c5e2006-12-19 18:02:03 -07001211}
Brian34ae99d2006-12-18 08:28:54 -07001212
Brian5b01c5e2006-12-19 18:02:03 -07001213
Brian Paulade50832008-05-14 16:09:46 -06001214
1215/**
1216 * Update the vertex and fragment program's TexturesUsed arrays.
1217 */
1218static void
1219update_textures_used(struct gl_program *prog)
1220{
1221 GLuint s;
1222
1223 memset(prog->TexturesUsed, 0, sizeof(prog->TexturesUsed));
1224
1225 for (s = 0; s < MAX_SAMPLERS; s++) {
1226 if (prog->SamplersUsed & (1 << s)) {
1227 GLuint u = prog->SamplerUnits[s];
1228 GLuint t = prog->SamplerTargets[s];
1229 assert(u < MAX_TEXTURE_IMAGE_UNITS);
1230 prog->TexturesUsed[u] |= (1 << t);
1231 }
1232 }
1233}
1234
1235
Brianb36749d2008-07-21 20:42:05 -06001236static GLboolean
1237is_sampler_type(GLenum type)
1238{
1239 switch (type) {
1240 case GL_SAMPLER_1D:
1241 case GL_SAMPLER_2D:
1242 case GL_SAMPLER_3D:
1243 case GL_SAMPLER_CUBE:
1244 case GL_SAMPLER_1D_SHADOW:
1245 case GL_SAMPLER_2D_SHADOW:
1246 case GL_SAMPLER_2D_RECT_ARB:
1247 case GL_SAMPLER_2D_RECT_SHADOW_ARB:
1248 case GL_SAMPLER_1D_ARRAY_EXT:
1249 case GL_SAMPLER_2D_ARRAY_EXT:
1250 return GL_TRUE;
1251 default:
1252 return GL_FALSE;
1253 }
1254}
1255
1256
Brian Paulade50832008-05-14 16:09:46 -06001257/**
Brian Paulffbc66b2008-07-21 13:58:50 -06001258 * Check if the type given by userType is allowed to set a uniform of the
1259 * target type. Generally, equivalence is required, but setting Boolean
1260 * uniforms can be done with glUniformiv or glUniformfv.
1261 */
1262static GLboolean
1263compatible_types(GLenum userType, GLenum targetType)
1264{
1265 if (userType == targetType)
1266 return GL_TRUE;
1267
1268 if (targetType == GL_BOOL && (userType == GL_FLOAT || userType == GL_INT))
1269 return GL_TRUE;
1270
1271 if (targetType == GL_BOOL_VEC2 && (userType == GL_FLOAT_VEC2 ||
1272 userType == GL_INT_VEC2))
1273 return GL_TRUE;
1274
1275 if (targetType == GL_BOOL_VEC3 && (userType == GL_FLOAT_VEC3 ||
1276 userType == GL_INT_VEC3))
1277 return GL_TRUE;
1278
1279 if (targetType == GL_BOOL_VEC4 && (userType == GL_FLOAT_VEC4 ||
1280 userType == GL_INT_VEC4))
1281 return GL_TRUE;
1282
Brianb36749d2008-07-21 20:42:05 -06001283 if (is_sampler_type(targetType) && userType == GL_INT)
1284 return GL_TRUE;
1285
Brian Paulffbc66b2008-07-21 13:58:50 -06001286 return GL_FALSE;
1287}
1288
1289
1290/**
Brian Paulade50832008-05-14 16:09:46 -06001291 * Set the value of a program's uniform variable.
1292 * \param program the program whose uniform to update
1293 * \param location the location/index of the uniform
1294 * \param type the datatype of the uniform
1295 * \param count the number of uniforms to set
1296 * \param elems number of elements per uniform
1297 * \param values the new values
1298 */
1299static void
1300set_program_uniform(GLcontext *ctx, struct gl_program *program, GLint location,
Brian Paul530df582008-07-03 16:21:11 -06001301 GLenum type, GLsizei count, GLint elems, const void *values)
Brian Paulade50832008-05-14 16:09:46 -06001302{
Brian Paulffbc66b2008-07-21 13:58:50 -06001303 if (!compatible_types(type,
1304 program->Parameters->Parameters[location].DataType)) {
1305 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(type mismatch)");
1306 return;
1307 }
1308
Brian Paulade50832008-05-14 16:09:46 -06001309 if (program->Parameters->Parameters[location].Type == PROGRAM_SAMPLER) {
1310 /* This controls which texture unit which is used by a sampler */
1311 GLuint texUnit, sampler;
1312
1313 /* data type for setting samplers must be int */
1314 if (type != GL_INT || count != 1) {
1315 _mesa_error(ctx, GL_INVALID_OPERATION,
1316 "glUniform(only glUniform1i can be used "
1317 "to set sampler uniforms)");
1318 return;
1319 }
1320
1321 sampler = (GLuint) program->Parameters->ParameterValues[location][0];
1322 texUnit = ((GLuint *) values)[0];
1323
1324 /* check that the sampler (tex unit index) is legal */
1325 if (texUnit >= ctx->Const.MaxTextureImageUnits) {
1326 _mesa_error(ctx, GL_INVALID_VALUE,
1327 "glUniform1(invalid sampler/tex unit index)");
1328 return;
1329 }
1330
1331 /* This maps a sampler to a texture unit: */
1332 program->SamplerUnits[sampler] = texUnit;
1333 update_textures_used(program);
1334
1335 FLUSH_VERTICES(ctx, _NEW_TEXTURE);
1336 }
1337 else {
1338 /* ordinary uniform variable */
Brian Paul530df582008-07-03 16:21:11 -06001339 GLsizei k, i;
Brian Paulade50832008-05-14 16:09:46 -06001340
Brian Paul016701f2008-07-29 17:43:35 -06001341 if (count * elems > (GLint) program->Parameters->Parameters[location].Size) {
Brian Paulade50832008-05-14 16:09:46 -06001342 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(count too large)");
1343 return;
1344 }
1345
1346 for (k = 0; k < count; k++) {
1347 GLfloat *uniformVal = program->Parameters->ParameterValues[location + k];
1348 if (type == GL_INT ||
1349 type == GL_INT_VEC2 ||
1350 type == GL_INT_VEC3 ||
1351 type == GL_INT_VEC4) {
1352 const GLint *iValues = ((const GLint *) values) + k * elems;
1353 for (i = 0; i < elems; i++) {
1354 uniformVal[i] = (GLfloat) iValues[i];
1355 }
1356 }
1357 else {
1358 const GLfloat *fValues = ((const GLfloat *) values) + k * elems;
1359 for (i = 0; i < elems; i++) {
1360 uniformVal[i] = fValues[i];
1361 }
1362 }
1363 }
1364 }
1365}
1366
1367
Brian5b01c5e2006-12-19 18:02:03 -07001368/**
1369 * Called via ctx->Driver.Uniform().
1370 */
Brian Paulfd59f192008-05-18 16:04:55 -06001371static void
Brian5b01c5e2006-12-19 18:02:03 -07001372_mesa_uniform(GLcontext *ctx, GLint location, GLsizei count,
1373 const GLvoid *values, GLenum type)
1374{
Brian3a8e2772006-12-20 17:19:16 -07001375 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001376 GLint elems;
Brian3a8e2772006-12-20 17:19:16 -07001377
1378 if (!shProg || !shProg->LinkStatus) {
Brian5b01c5e2006-12-19 18:02:03 -07001379 _mesa_error(ctx, GL_INVALID_OPERATION, "glUniform(program not linked)");
Brian3a8e2772006-12-20 17:19:16 -07001380 return;
1381 }
1382
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001383 if (location == -1)
1384 return; /* The standard specifies this as a no-op */
1385
Brian Paulade50832008-05-14 16:09:46 -06001386 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
1387 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(location)");
Brian3a8e2772006-12-20 17:19:16 -07001388 return;
1389 }
1390
Brian52363952007-03-13 16:50:24 -06001391 if (count < 0) {
1392 _mesa_error(ctx, GL_INVALID_VALUE, "glUniform(count < 0)");
1393 return;
1394 }
1395
Brian98650bd2007-03-13 16:32:48 -06001396 switch (type) {
1397 case GL_FLOAT:
1398 case GL_INT:
1399 elems = 1;
1400 break;
1401 case GL_FLOAT_VEC2:
1402 case GL_INT_VEC2:
1403 elems = 2;
1404 break;
1405 case GL_FLOAT_VEC3:
1406 case GL_INT_VEC3:
1407 elems = 3;
1408 break;
1409 case GL_FLOAT_VEC4:
1410 case GL_INT_VEC4:
1411 elems = 4;
1412 break;
1413 default:
1414 _mesa_problem(ctx, "Invalid type in _mesa_uniform");
1415 return;
Brian89dc4852007-01-04 14:35:44 -07001416 }
Brian98650bd2007-03-13 16:32:48 -06001417
Brian Paulade50832008-05-14 16:09:46 -06001418 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
Brian98650bd2007-03-13 16:32:48 -06001419
Brian Paulade50832008-05-14 16:09:46 -06001420 /* A uniform var may be used by both a vertex shader and a fragment
1421 * shader. We may need to update one or both shader's uniform here:
Bruce Merryeeb03fa2007-12-21 14:41:45 +02001422 */
Brian Paulade50832008-05-14 16:09:46 -06001423 if (shProg->VertexProgram) {
1424 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1425 if (loc >= 0) {
1426 set_program_uniform(ctx, &shProg->VertexProgram->Base,
1427 loc, type, count, elems, values);
Bruce Merry2bf2a8c2007-12-21 23:18:40 +02001428 }
Brian5b01c5e2006-12-19 18:02:03 -07001429 }
Brian5cf73262007-01-05 16:02:45 -07001430
Brian Paulade50832008-05-14 16:09:46 -06001431 if (shProg->FragmentProgram) {
1432 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1433 if (loc >= 0) {
1434 set_program_uniform(ctx, &shProg->FragmentProgram->Base,
1435 loc, type, count, elems, values);
1436 }
1437 }
1438}
1439
1440
1441static void
Brian Paulffbc66b2008-07-21 13:58:50 -06001442get_matrix_dims(GLenum type, GLint *rows, GLint *cols)
1443{
1444 switch (type) {
1445 case GL_FLOAT_MAT2:
1446 *rows = *cols = 2;
1447 break;
1448 case GL_FLOAT_MAT2x3:
1449 *rows = 3;
1450 *cols = 2;
1451 break;
1452 case GL_FLOAT_MAT2x4:
1453 *rows = 4;
1454 *cols = 2;
1455 break;
1456 case GL_FLOAT_MAT3:
1457 *rows = 3;
1458 *cols = 3;
1459 break;
1460 case GL_FLOAT_MAT3x2:
1461 *rows = 2;
1462 *cols = 3;
1463 break;
1464 case GL_FLOAT_MAT3x4:
1465 *rows = 4;
1466 *cols = 3;
1467 break;
1468 case GL_FLOAT_MAT4:
1469 *rows = 4;
1470 *cols = 4;
1471 break;
1472 case GL_FLOAT_MAT4x2:
1473 *rows = 2;
1474 *cols = 4;
1475 break;
1476 case GL_FLOAT_MAT4x3:
1477 *rows = 3;
1478 *cols = 4;
1479 break;
1480 default:
1481 *rows = *cols = 0;
1482 }
1483}
1484
1485
1486static void
Brian Paulade50832008-05-14 16:09:46 -06001487set_program_uniform_matrix(GLcontext *ctx, struct gl_program *program,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001488 GLuint location, GLuint count,
1489 GLuint rows, GLuint cols,
Brian Paulade50832008-05-14 16:09:46 -06001490 GLboolean transpose, const GLfloat *values)
1491{
Brian Paulffbc66b2008-07-21 13:58:50 -06001492 GLuint mat, row, col;
1493 GLuint dst = location, src = 0;
1494 GLint nr, nc;
1495
1496 /* check that the number of rows, columns is correct */
1497 get_matrix_dims(program->Parameters->Parameters[location].DataType, &nr, &nc);
1498 if (rows != nr || cols != nc) {
1499 _mesa_error(ctx, GL_INVALID_OPERATION,
1500 "glUniformMatrix(matrix size mismatch");
1501 return;
1502 }
1503
Brian Paulade50832008-05-14 16:09:46 -06001504 /*
1505 * Note: the _columns_ of a matrix are stored in program registers, not
Brian Paulf45ed0e2008-07-18 12:51:39 -06001506 * the rows. So, the loops below look a little funny.
1507 * XXX could optimize this a bit...
Brian Paulade50832008-05-14 16:09:46 -06001508 */
Brian Paulf45ed0e2008-07-18 12:51:39 -06001509
1510 /* loop over matrices */
1511 for (mat = 0; mat < count; mat++) {
1512
1513 /* each matrix: */
Brian Paulade50832008-05-14 16:09:46 -06001514 for (col = 0; col < cols; col++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001515 GLfloat *v = program->Parameters->ParameterValues[dst];
Brian Paulade50832008-05-14 16:09:46 -06001516 for (row = 0; row < rows; row++) {
Brian Paulf45ed0e2008-07-18 12:51:39 -06001517 if (transpose) {
1518 v[row] = values[src + row * cols + col];
1519 }
1520 else {
1521 v[row] = values[src + col * rows + row];
1522 }
Brian Paulade50832008-05-14 16:09:46 -06001523 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001524 dst++;
Brian Paulade50832008-05-14 16:09:46 -06001525 }
Brian Paulf45ed0e2008-07-18 12:51:39 -06001526
1527 src += rows * cols; /* next matrix */
Brian5cf73262007-01-05 16:02:45 -07001528 }
Brian34ae99d2006-12-18 08:28:54 -07001529}
1530
1531
1532/**
Brian5b01c5e2006-12-19 18:02:03 -07001533 * Called by ctx->Driver.UniformMatrix().
Brian Paulf45ed0e2008-07-18 12:51:39 -06001534 * Note: cols=2, rows=4 ==> array[2] of vec4
Brian34ae99d2006-12-18 08:28:54 -07001535 */
Brian Paulfd59f192008-05-18 16:04:55 -06001536static void
Brian5b01c5e2006-12-19 18:02:03 -07001537_mesa_uniform_matrix(GLcontext *ctx, GLint cols, GLint rows,
1538 GLenum matrixType, GLint location, GLsizei count,
1539 GLboolean transpose, const GLfloat *values)
Brian34ae99d2006-12-18 08:28:54 -07001540{
Brian3a8e2772006-12-20 17:19:16 -07001541 struct gl_shader_program *shProg = ctx->Shader.CurrentProgram;
Brian Paulade50832008-05-14 16:09:46 -06001542
Brian3a8e2772006-12-20 17:19:16 -07001543 if (!shProg || !shProg->LinkStatus) {
1544 _mesa_error(ctx, GL_INVALID_OPERATION,
1545 "glUniformMatrix(program not linked)");
1546 return;
1547 }
Brian Paulade50832008-05-14 16:09:46 -06001548
Bruce Merry89b80322007-12-21 15:20:17 +02001549 if (location == -1)
1550 return; /* The standard specifies this as a no-op */
Brian Paulade50832008-05-14 16:09:46 -06001551
Brian Paul016701f2008-07-29 17:43:35 -06001552 if (location < 0 || location >= (GLint) shProg->Uniforms->NumUniforms) {
Brian Paulade50832008-05-14 16:09:46 -06001553 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix(location)");
Brian3a8e2772006-12-20 17:19:16 -07001554 return;
1555 }
Brian34ae99d2006-12-18 08:28:54 -07001556 if (values == NULL) {
Brian3a8e2772006-12-20 17:19:16 -07001557 _mesa_error(ctx, GL_INVALID_VALUE, "glUniformMatrix");
Brian34ae99d2006-12-18 08:28:54 -07001558 return;
1559 }
1560
1561 FLUSH_VERTICES(ctx, _NEW_PROGRAM);
1562
Brian Paulade50832008-05-14 16:09:46 -06001563 if (shProg->VertexProgram) {
1564 GLint loc = shProg->Uniforms->Uniforms[location].VertPos;
1565 if (loc >= 0) {
1566 set_program_uniform_matrix(ctx, &shProg->VertexProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001567 loc, count, rows, cols, transpose, values);
Brian34ae99d2006-12-18 08:28:54 -07001568 }
Brian Paulade50832008-05-14 16:09:46 -06001569 }
1570
1571 if (shProg->FragmentProgram) {
1572 GLint loc = shProg->Uniforms->Uniforms[location].FragPos;
1573 if (loc >= 0) {
1574 set_program_uniform_matrix(ctx, &shProg->FragmentProgram->Base,
Brian Paulf45ed0e2008-07-18 12:51:39 -06001575 loc, count, rows, cols, transpose, values);
Brian3a8e2772006-12-20 17:19:16 -07001576 }
Brian34ae99d2006-12-18 08:28:54 -07001577 }
1578}
1579
1580
Brian Paulfd59f192008-05-18 16:04:55 -06001581static void
Brian5b01c5e2006-12-19 18:02:03 -07001582_mesa_validate_program(GLcontext *ctx, GLuint program)
Brian34ae99d2006-12-18 08:28:54 -07001583{
Brian65a18442006-12-19 18:46:56 -07001584 struct gl_shader_program *shProg;
Brian Paulbc985b52008-07-21 14:16:07 -06001585
1586 shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram");
Brian65a18442006-12-19 18:46:56 -07001587 if (!shProg) {
Brian34ae99d2006-12-18 08:28:54 -07001588 return;
1589 }
1590
Brian Paulbc985b52008-07-21 14:16:07 -06001591 if (!shProg->LinkStatus) {
1592 shProg->Validated = GL_FALSE;
1593 return;
1594 }
1595
1596 /* From the GL spec, a program is invalid if any of these are true:
1597
Brian5b01c5e2006-12-19 18:02:03 -07001598 any two active samplers in the current program object are of
1599 different types, but refer to the same texture image unit,
1600
1601 any active sampler in the current program object refers to a texture
1602 image unit where fixed-function fragment processing accesses a
1603 texture target that does not match the sampler type, or
1604
1605 the sum of the number of active samplers in the program and the
1606 number of texture image units enabled for fixed-function fragment
1607 processing exceeds the combined limit on the total number of texture
1608 image units allowed.
1609 */
Brian Paulbc985b52008-07-21 14:16:07 -06001610
1611 shProg->Validated = GL_TRUE;
Brian34ae99d2006-12-18 08:28:54 -07001612}
Brian Paulfd59f192008-05-18 16:04:55 -06001613
1614
1615/**
1616 * Plug in Mesa's GLSL functions into the device driver function table.
1617 */
1618void
1619_mesa_init_glsl_driver_functions(struct dd_function_table *driver)
1620{
1621 driver->AttachShader = _mesa_attach_shader;
1622 driver->BindAttribLocation = _mesa_bind_attrib_location;
1623 driver->CompileShader = _mesa_compile_shader;
1624 driver->CreateProgram = _mesa_create_program;
1625 driver->CreateShader = _mesa_create_shader;
1626 driver->DeleteProgram2 = _mesa_delete_program2;
1627 driver->DeleteShader = _mesa_delete_shader;
1628 driver->DetachShader = _mesa_detach_shader;
1629 driver->GetActiveAttrib = _mesa_get_active_attrib;
1630 driver->GetActiveUniform = _mesa_get_active_uniform;
1631 driver->GetAttachedShaders = _mesa_get_attached_shaders;
1632 driver->GetAttribLocation = _mesa_get_attrib_location;
1633 driver->GetHandle = _mesa_get_handle;
1634 driver->GetProgramiv = _mesa_get_programiv;
1635 driver->GetProgramInfoLog = _mesa_get_program_info_log;
1636 driver->GetShaderiv = _mesa_get_shaderiv;
1637 driver->GetShaderInfoLog = _mesa_get_shader_info_log;
1638 driver->GetShaderSource = _mesa_get_shader_source;
1639 driver->GetUniformfv = _mesa_get_uniformfv;
Brian Paul2be54a82008-07-08 16:17:04 -06001640 driver->GetUniformiv = _mesa_get_uniformiv;
Brian Paulfd59f192008-05-18 16:04:55 -06001641 driver->GetUniformLocation = _mesa_get_uniform_location;
1642 driver->IsProgram = _mesa_is_program;
1643 driver->IsShader = _mesa_is_shader;
1644 driver->LinkProgram = _mesa_link_program;
1645 driver->ShaderSource = _mesa_shader_source;
1646 driver->Uniform = _mesa_uniform;
1647 driver->UniformMatrix = _mesa_uniform_matrix;
1648 driver->UseProgram = _mesa_use_program;
1649 driver->ValidateProgram = _mesa_validate_program;
1650}