Rev 1901 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1901 | serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 2004-2008 Brian Paul All Rights Reserved. |
||
5 | * Copyright (C) 2009-2010 VMware, Inc. All Rights Reserved. |
||
6 | * |
||
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 shaderapi.c |
||
27 | * \author Brian Paul |
||
28 | * |
||
29 | * Implementation of GLSL-related API functions. |
||
30 | * The glUniform* functions are in uniforms.c |
||
31 | * |
||
32 | * |
||
33 | * XXX things to do: |
||
34 | * 1. Check that the right error code is generated for all _mesa_error() calls. |
||
35 | * 2. Insert FLUSH_VERTICES calls in various places |
||
36 | */ |
||
37 | |||
38 | |||
39 | #include "main/glheader.h" |
||
40 | #include "main/context.h" |
||
41 | #include "main/dispatch.h" |
||
42 | #include "main/enums.h" |
||
43 | #include "main/hash.h" |
||
44 | #include "main/shaderapi.h" |
||
45 | #include "main/shaderobj.h" |
||
46 | #include "program/program.h" |
||
47 | #include "program/prog_parameter.h" |
||
48 | #include "program/prog_uniform.h" |
||
49 | #include "ralloc.h" |
||
50 | #include |
||
51 | #include "../glsl/glsl_parser_extras.h" |
||
52 | |||
53 | /** Define this to enable shader substitution (see below) */ |
||
54 | #define SHADER_SUBST 0 |
||
55 | |||
56 | |||
57 | /** |
||
58 | * Return mask of GLSL_x flags by examining the MESA_GLSL env var. |
||
59 | */ |
||
60 | static GLbitfield |
||
61 | get_shader_flags(void) |
||
62 | { |
||
63 | GLbitfield flags = 0x0; |
||
64 | const char *env = _mesa_getenv("MESA_GLSL"); |
||
65 | |||
66 | if (env) { |
||
67 | if (strstr(env, "dump")) |
||
68 | flags |= GLSL_DUMP; |
||
69 | if (strstr(env, "log")) |
||
70 | flags |= GLSL_LOG; |
||
71 | if (strstr(env, "nopvert")) |
||
72 | flags |= GLSL_NOP_VERT; |
||
73 | if (strstr(env, "nopfrag")) |
||
74 | flags |= GLSL_NOP_FRAG; |
||
75 | if (strstr(env, "nopt")) |
||
76 | flags |= GLSL_NO_OPT; |
||
77 | else if (strstr(env, "opt")) |
||
78 | flags |= GLSL_OPT; |
||
79 | if (strstr(env, "uniform")) |
||
80 | flags |= GLSL_UNIFORMS; |
||
81 | if (strstr(env, "useprog")) |
||
82 | flags |= GLSL_USE_PROG; |
||
83 | } |
||
84 | |||
85 | return flags; |
||
86 | } |
||
87 | |||
88 | |||
89 | /** |
||
90 | * Initialize context's shader state. |
||
91 | */ |
||
92 | void |
||
93 | _mesa_init_shader_state(struct gl_context *ctx) |
||
94 | { |
||
95 | /* Device drivers may override these to control what kind of instructions |
||
96 | * are generated by the GLSL compiler. |
||
97 | */ |
||
98 | struct gl_shader_compiler_options options; |
||
99 | gl_shader_type sh; |
||
100 | |||
101 | memset(&options, 0, sizeof(options)); |
||
102 | options.MaxUnrollIterations = 32; |
||
103 | |||
104 | /* Default pragma settings */ |
||
105 | options.DefaultPragmas.Optimize = GL_TRUE; |
||
106 | |||
107 | for (sh = 0; sh < MESA_SHADER_TYPES; ++sh) |
||
108 | memcpy(&ctx->ShaderCompilerOptions[sh], &options, sizeof(options)); |
||
109 | |||
110 | ctx->Shader.Flags = get_shader_flags(); |
||
111 | } |
||
112 | |||
113 | |||
114 | /** |
||
115 | * Free the per-context shader-related state. |
||
116 | */ |
||
117 | void |
||
118 | _mesa_free_shader_state(struct gl_context *ctx) |
||
119 | { |
||
120 | _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentVertexProgram, NULL); |
||
121 | _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentGeometryProgram, |
||
122 | NULL); |
||
123 | _mesa_reference_shader_program(ctx, &ctx->Shader.CurrentFragmentProgram, |
||
124 | NULL); |
||
125 | _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, NULL); |
||
126 | } |
||
127 | |||
128 | |||
129 | /** |
||
130 | * Return the size of the given GLSL datatype, in floats (components). |
||
131 | */ |
||
132 | GLint |
||
133 | _mesa_sizeof_glsl_type(GLenum type) |
||
134 | { |
||
135 | switch (type) { |
||
136 | case GL_FLOAT: |
||
137 | case GL_INT: |
||
138 | case GL_BOOL: |
||
139 | case GL_SAMPLER_1D: |
||
140 | case GL_SAMPLER_2D: |
||
141 | case GL_SAMPLER_3D: |
||
142 | case GL_SAMPLER_CUBE: |
||
143 | case GL_SAMPLER_1D_SHADOW: |
||
144 | case GL_SAMPLER_2D_SHADOW: |
||
145 | case GL_SAMPLER_2D_RECT_ARB: |
||
146 | case GL_SAMPLER_2D_RECT_SHADOW_ARB: |
||
147 | case GL_SAMPLER_1D_ARRAY_EXT: |
||
148 | case GL_SAMPLER_2D_ARRAY_EXT: |
||
149 | case GL_SAMPLER_1D_ARRAY_SHADOW_EXT: |
||
150 | case GL_SAMPLER_2D_ARRAY_SHADOW_EXT: |
||
151 | case GL_SAMPLER_CUBE_SHADOW_EXT: |
||
152 | return 1; |
||
153 | case GL_FLOAT_VEC2: |
||
154 | case GL_INT_VEC2: |
||
155 | case GL_UNSIGNED_INT_VEC2: |
||
156 | case GL_BOOL_VEC2: |
||
157 | return 2; |
||
158 | case GL_FLOAT_VEC3: |
||
159 | case GL_INT_VEC3: |
||
160 | case GL_UNSIGNED_INT_VEC3: |
||
161 | case GL_BOOL_VEC3: |
||
162 | return 3; |
||
163 | case GL_FLOAT_VEC4: |
||
164 | case GL_INT_VEC4: |
||
165 | case GL_UNSIGNED_INT_VEC4: |
||
166 | case GL_BOOL_VEC4: |
||
167 | return 4; |
||
168 | case GL_FLOAT_MAT2: |
||
169 | case GL_FLOAT_MAT2x3: |
||
170 | case GL_FLOAT_MAT2x4: |
||
171 | return 8; /* two float[4] vectors */ |
||
172 | case GL_FLOAT_MAT3: |
||
173 | case GL_FLOAT_MAT3x2: |
||
174 | case GL_FLOAT_MAT3x4: |
||
175 | return 12; /* three float[4] vectors */ |
||
176 | case GL_FLOAT_MAT4: |
||
177 | case GL_FLOAT_MAT4x2: |
||
178 | case GL_FLOAT_MAT4x3: |
||
179 | return 16; /* four float[4] vectors */ |
||
180 | default: |
||
181 | _mesa_problem(NULL, "Invalid type in _mesa_sizeof_glsl_type()"); |
||
182 | return 1; |
||
183 | } |
||
184 | } |
||
185 | |||
186 | |||
187 | /** |
||
188 | * Copy string from |
||
189 | * length of |
||
190 | * \param src the strings source |
||
191 | * \param maxLength max chars to copy |
||
192 | * \param length returns number of chars copied |
||
193 | * \param dst the string destination |
||
194 | */ |
||
195 | void |
||
196 | _mesa_copy_string(GLchar *dst, GLsizei maxLength, |
||
197 | GLsizei *length, const GLchar *src) |
||
198 | { |
||
199 | GLsizei len; |
||
200 | for (len = 0; len < maxLength - 1 && src && src[len]; len++) |
||
201 | dst[len] = src[len]; |
||
202 | if (maxLength > 0) |
||
203 | dst[len] = 0; |
||
204 | if (length) |
||
205 | *length = len; |
||
206 | } |
||
207 | |||
208 | |||
209 | |||
210 | /** |
||
211 | * Confirm that the a shader type is valid and supported by the implementation |
||
212 | * |
||
213 | * \param ctx Current GL context |
||
214 | * \param type Shader target |
||
215 | * |
||
216 | */ |
||
217 | static bool |
||
218 | validate_shader_target(const struct gl_context *ctx, GLenum type) |
||
219 | { |
||
220 | switch (type) { |
||
221 | #if FEATURE_ARB_fragment_shader |
||
222 | case GL_FRAGMENT_SHADER: |
||
223 | return ctx->Extensions.ARB_fragment_shader; |
||
224 | #endif |
||
225 | #if FEATURE_ARB_vertex_shader |
||
226 | case GL_VERTEX_SHADER: |
||
227 | return ctx->Extensions.ARB_vertex_shader; |
||
228 | #endif |
||
229 | #if FEATURE_ARB_geometry_shader4 |
||
230 | case GL_GEOMETRY_SHADER_ARB: |
||
231 | return ctx->Extensions.ARB_geometry_shader4; |
||
232 | #endif |
||
233 | default: |
||
234 | return false; |
||
235 | } |
||
236 | } |
||
237 | |||
238 | |||
239 | /** |
||
240 | * Find the length of the longest transform feedback varying name |
||
241 | * which was specified with glTransformFeedbackVaryings(). |
||
242 | */ |
||
243 | static GLint |
||
244 | longest_feedback_varying_name(const struct gl_shader_program *shProg) |
||
245 | { |
||
246 | GLuint i; |
||
247 | GLint max = 0; |
||
248 | for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { |
||
249 | GLint len = strlen(shProg->TransformFeedback.VaryingNames[i]); |
||
250 | if (len > max) |
||
251 | max = len; |
||
252 | } |
||
253 | return max; |
||
254 | } |
||
255 | |||
256 | |||
257 | |||
258 | static GLboolean |
||
259 | is_program(struct gl_context *ctx, GLuint name) |
||
260 | { |
||
261 | struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, name); |
||
262 | return shProg ? GL_TRUE : GL_FALSE; |
||
263 | } |
||
264 | |||
265 | |||
266 | static GLboolean |
||
267 | is_shader(struct gl_context *ctx, GLuint name) |
||
268 | { |
||
269 | struct gl_shader *shader = _mesa_lookup_shader(ctx, name); |
||
270 | return shader ? GL_TRUE : GL_FALSE; |
||
271 | } |
||
272 | |||
273 | |||
274 | /** |
||
275 | * Attach shader to a shader program. |
||
276 | */ |
||
277 | static void |
||
278 | attach_shader(struct gl_context *ctx, GLuint program, GLuint shader) |
||
279 | { |
||
280 | struct gl_shader_program *shProg; |
||
281 | struct gl_shader *sh; |
||
282 | GLuint i, n; |
||
283 | |||
284 | shProg = _mesa_lookup_shader_program_err(ctx, program, "glAttachShader"); |
||
285 | if (!shProg) |
||
286 | return; |
||
287 | |||
288 | sh = _mesa_lookup_shader_err(ctx, shader, "glAttachShader"); |
||
289 | if (!sh) { |
||
290 | return; |
||
291 | } |
||
292 | |||
293 | n = shProg->NumShaders; |
||
294 | for (i = 0; i < n; i++) { |
||
295 | if (shProg->Shaders[i] == sh) { |
||
296 | /* The shader is already attched to this program. The |
||
297 | * GL_ARB_shader_objects spec says: |
||
298 | * |
||
299 | * "The error INVALID_OPERATION is generated by AttachObjectARB |
||
300 | * if |
||
301 | */ |
||
302 | _mesa_error(ctx, GL_INVALID_OPERATION, "glAttachShader"); |
||
303 | return; |
||
304 | } |
||
305 | } |
||
306 | |||
307 | /* grow list */ |
||
308 | shProg->Shaders = (struct gl_shader **) |
||
309 | _mesa_realloc(shProg->Shaders, |
||
310 | n * sizeof(struct gl_shader *), |
||
311 | (n + 1) * sizeof(struct gl_shader *)); |
||
312 | if (!shProg->Shaders) { |
||
313 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glAttachShader"); |
||
314 | return; |
||
315 | } |
||
316 | |||
317 | /* append */ |
||
318 | shProg->Shaders[n] = NULL; /* since realloc() didn't zero the new space */ |
||
319 | _mesa_reference_shader(ctx, &shProg->Shaders[n], sh); |
||
320 | shProg->NumShaders++; |
||
321 | } |
||
322 | |||
323 | |||
324 | static GLint |
||
325 | get_attrib_location(struct gl_context *ctx, GLuint program, const GLchar *name) |
||
326 | { |
||
327 | struct gl_shader_program *shProg |
||
328 | = _mesa_lookup_shader_program_err(ctx, program, "glGetAttribLocation"); |
||
329 | |||
330 | if (!shProg) { |
||
331 | return -1; |
||
332 | } |
||
333 | |||
334 | if (!shProg->LinkStatus) { |
||
335 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
336 | "glGetAttribLocation(program not linked)"); |
||
337 | return -1; |
||
338 | } |
||
339 | |||
340 | if (!name) |
||
341 | return -1; |
||
342 | |||
343 | if (shProg->VertexProgram) { |
||
344 | const struct gl_program_parameter_list *attribs = |
||
345 | shProg->VertexProgram->Base.Attributes; |
||
346 | if (attribs) { |
||
347 | GLint i = _mesa_lookup_parameter_index(attribs, -1, name); |
||
348 | if (i >= 0) { |
||
349 | return attribs->Parameters[i].StateIndexes[0]; |
||
350 | } |
||
351 | } |
||
352 | } |
||
353 | return -1; |
||
354 | } |
||
355 | |||
356 | |||
357 | static void |
||
358 | bind_attrib_location(struct gl_context *ctx, GLuint program, GLuint index, |
||
359 | const GLchar *name) |
||
360 | { |
||
361 | struct gl_shader_program *shProg; |
||
362 | const GLint size = -1; /* unknown size */ |
||
363 | GLint i, oldIndex; |
||
364 | GLenum datatype = GL_FLOAT_VEC4; |
||
365 | |||
366 | shProg = _mesa_lookup_shader_program_err(ctx, program, |
||
367 | "glBindAttribLocation"); |
||
368 | if (!shProg) { |
||
369 | return; |
||
370 | } |
||
371 | |||
372 | if (!name) |
||
373 | return; |
||
374 | |||
375 | if (strncmp(name, "gl_", 3) == 0) { |
||
376 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
377 | "glBindAttribLocation(illegal name)"); |
||
378 | return; |
||
379 | } |
||
380 | |||
381 | if (index >= ctx->Const.VertexProgram.MaxAttribs) { |
||
382 | _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(index)"); |
||
383 | return; |
||
384 | } |
||
385 | |||
386 | if (shProg->LinkStatus) { |
||
387 | /* get current index/location for the attribute */ |
||
388 | oldIndex = get_attrib_location(ctx, program, name); |
||
389 | } |
||
390 | else { |
||
391 | oldIndex = -1; |
||
392 | } |
||
393 | |||
394 | /* this will replace the current value if it's already in the list */ |
||
395 | i = _mesa_add_attribute(shProg->Attributes, name, size, datatype, index); |
||
396 | if (i < 0) { |
||
397 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation"); |
||
398 | return; |
||
399 | } |
||
400 | |||
401 | /* |
||
402 | * Note that this attribute binding won't go into effect until |
||
403 | * glLinkProgram is called again. |
||
404 | */ |
||
405 | } |
||
406 | |||
407 | |||
408 | static void |
||
409 | bind_frag_data_location(struct gl_context *ctx, GLuint program, |
||
410 | GLuint colorNumber, const GLchar *name) |
||
411 | { |
||
412 | _mesa_problem(ctx, "bind_frag_data_location() not implemented yet"); |
||
413 | } |
||
414 | |||
415 | |||
416 | static GLuint |
||
417 | create_shader(struct gl_context *ctx, GLenum type) |
||
418 | { |
||
419 | struct gl_shader *sh; |
||
420 | GLuint name; |
||
421 | |||
422 | if (!validate_shader_target(ctx, type)) { |
||
423 | _mesa_error(ctx, GL_INVALID_ENUM, "CreateShader(type)"); |
||
424 | return 0; |
||
425 | } |
||
426 | |||
427 | name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); |
||
428 | sh = ctx->Driver.NewShader(ctx, name, type); |
||
429 | _mesa_HashInsert(ctx->Shared->ShaderObjects, name, sh); |
||
430 | |||
431 | return name; |
||
432 | } |
||
433 | |||
434 | |||
435 | static GLuint |
||
436 | create_shader_program(struct gl_context *ctx) |
||
437 | { |
||
438 | GLuint name; |
||
439 | struct gl_shader_program *shProg; |
||
440 | |||
441 | name = _mesa_HashFindFreeKeyBlock(ctx->Shared->ShaderObjects, 1); |
||
442 | |||
443 | shProg = ctx->Driver.NewShaderProgram(ctx, name); |
||
444 | |||
445 | _mesa_HashInsert(ctx->Shared->ShaderObjects, name, shProg); |
||
446 | |||
447 | assert(shProg->RefCount == 1); |
||
448 | |||
449 | return name; |
||
450 | } |
||
451 | |||
452 | |||
453 | /** |
||
454 | * Named w/ "2" to indicate OpenGL 2.x vs GL_ARB_fragment_programs's |
||
455 | * DeleteProgramARB. |
||
456 | */ |
||
457 | static void |
||
458 | delete_shader_program(struct gl_context *ctx, GLuint name) |
||
459 | { |
||
460 | /* |
||
461 | * NOTE: deleting shaders/programs works a bit differently than |
||
462 | * texture objects (and buffer objects, etc). Shader/program |
||
463 | * handles/IDs exist in the hash table until the object is really |
||
464 | * deleted (refcount==0). With texture objects, the handle/ID is |
||
465 | * removed from the hash table in glDeleteTextures() while the tex |
||
466 | * object itself might linger until its refcount goes to zero. |
||
467 | */ |
||
468 | struct gl_shader_program *shProg; |
||
469 | |||
470 | shProg = _mesa_lookup_shader_program_err(ctx, name, "glDeleteProgram"); |
||
471 | if (!shProg) |
||
472 | return; |
||
473 | |||
474 | shProg->DeletePending = GL_TRUE; |
||
475 | |||
476 | /* effectively, decr shProg's refcount */ |
||
477 | _mesa_reference_shader_program(ctx, &shProg, NULL); |
||
478 | } |
||
479 | |||
480 | |||
481 | static void |
||
482 | delete_shader(struct gl_context *ctx, GLuint shader) |
||
483 | { |
||
484 | struct gl_shader *sh; |
||
485 | |||
486 | sh = _mesa_lookup_shader_err(ctx, shader, "glDeleteShader"); |
||
487 | if (!sh) |
||
488 | return; |
||
489 | |||
490 | sh->DeletePending = GL_TRUE; |
||
491 | |||
492 | /* effectively, decr sh's refcount */ |
||
493 | _mesa_reference_shader(ctx, &sh, NULL); |
||
494 | } |
||
495 | |||
496 | |||
497 | static void |
||
498 | detach_shader(struct gl_context *ctx, GLuint program, GLuint shader) |
||
499 | { |
||
500 | struct gl_shader_program *shProg; |
||
501 | GLuint n; |
||
502 | GLuint i, j; |
||
503 | |||
504 | shProg = _mesa_lookup_shader_program_err(ctx, program, "glDetachShader"); |
||
505 | if (!shProg) |
||
506 | return; |
||
507 | |||
508 | n = shProg->NumShaders; |
||
509 | |||
510 | for (i = 0; i < n; i++) { |
||
511 | if (shProg->Shaders[i]->Name == shader) { |
||
512 | /* found it */ |
||
513 | struct gl_shader **newList; |
||
514 | |||
515 | /* release */ |
||
516 | _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); |
||
517 | |||
518 | /* alloc new, smaller array */ |
||
519 | newList = (struct gl_shader **) |
||
520 | malloc((n - 1) * sizeof(struct gl_shader *)); |
||
521 | if (!newList) { |
||
522 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDetachShader"); |
||
523 | return; |
||
524 | } |
||
525 | for (j = 0; j < i; j++) { |
||
526 | newList[j] = shProg->Shaders[j]; |
||
527 | } |
||
528 | while (++i < n) |
||
529 | newList[j++] = shProg->Shaders[i]; |
||
530 | free(shProg->Shaders); |
||
531 | |||
532 | shProg->Shaders = newList; |
||
533 | shProg->NumShaders = n - 1; |
||
534 | |||
535 | #ifdef DEBUG |
||
536 | /* sanity check */ |
||
537 | { |
||
538 | for (j = 0; j < shProg->NumShaders; j++) { |
||
539 | assert(shProg->Shaders[j]->Type == GL_VERTEX_SHADER || |
||
540 | shProg->Shaders[j]->Type == GL_FRAGMENT_SHADER); |
||
541 | assert(shProg->Shaders[j]->RefCount > 0); |
||
542 | } |
||
543 | } |
||
544 | #endif |
||
545 | |||
546 | return; |
||
547 | } |
||
548 | } |
||
549 | |||
550 | /* not found */ |
||
551 | { |
||
552 | GLenum err; |
||
553 | if (is_shader(ctx, shader)) |
||
554 | err = GL_INVALID_OPERATION; |
||
555 | else if (is_program(ctx, shader)) |
||
556 | err = GL_INVALID_OPERATION; |
||
557 | else |
||
558 | err = GL_INVALID_VALUE; |
||
559 | _mesa_error(ctx, err, "glDetachProgram(shader)"); |
||
560 | return; |
||
561 | } |
||
562 | } |
||
563 | |||
564 | |||
565 | static void |
||
566 | get_active_attrib(struct gl_context *ctx, GLuint program, GLuint index, |
||
567 | GLsizei maxLength, GLsizei *length, GLint *size, |
||
568 | GLenum *type, GLchar *nameOut) |
||
569 | { |
||
570 | const struct gl_program_parameter_list *attribs = NULL; |
||
571 | struct gl_shader_program *shProg; |
||
572 | |||
573 | shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveAttrib"); |
||
574 | if (!shProg) |
||
575 | return; |
||
576 | |||
577 | if (shProg->VertexProgram) |
||
578 | attribs = shProg->VertexProgram->Base.Attributes; |
||
579 | |||
580 | if (!attribs || index >= attribs->NumParameters) { |
||
581 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveAttrib(index)"); |
||
582 | return; |
||
583 | } |
||
584 | |||
585 | _mesa_copy_string(nameOut, maxLength, length, |
||
586 | attribs->Parameters[index].Name); |
||
587 | |||
588 | if (size) |
||
589 | *size = attribs->Parameters[index].Size |
||
590 | / _mesa_sizeof_glsl_type(attribs->Parameters[index].DataType); |
||
591 | |||
592 | if (type) |
||
593 | *type = attribs->Parameters[index].DataType; |
||
594 | } |
||
595 | |||
596 | |||
597 | /** |
||
598 | * Return list of shaders attached to shader program. |
||
599 | */ |
||
600 | static void |
||
601 | get_attached_shaders(struct gl_context *ctx, GLuint program, GLsizei maxCount, |
||
602 | GLsizei *count, GLuint *obj) |
||
603 | { |
||
604 | struct gl_shader_program *shProg = |
||
605 | _mesa_lookup_shader_program_err(ctx, program, "glGetAttachedShaders"); |
||
606 | if (shProg) { |
||
607 | GLuint i; |
||
608 | for (i = 0; i < (GLuint) maxCount && i < shProg->NumShaders; i++) { |
||
609 | obj[i] = shProg->Shaders[i]->Name; |
||
610 | } |
||
611 | if (count) |
||
612 | *count = i; |
||
613 | } |
||
614 | } |
||
615 | |||
616 | |||
617 | static GLint |
||
618 | get_frag_data_location(struct gl_context *ctx, GLuint program, |
||
619 | const GLchar *name) |
||
620 | { |
||
621 | _mesa_problem(ctx, "get_frag_data_location() not implemented yet"); |
||
622 | return -1; |
||
623 | } |
||
624 | |||
625 | |||
626 | |||
627 | /** |
||
628 | * glGetHandleARB() - return ID/name of currently bound shader program. |
||
629 | */ |
||
630 | static GLuint |
||
631 | get_handle(struct gl_context *ctx, GLenum pname) |
||
632 | { |
||
633 | if (pname == GL_PROGRAM_OBJECT_ARB) { |
||
634 | if (ctx->Shader.ActiveProgram) |
||
635 | return ctx->Shader.ActiveProgram->Name; |
||
636 | else |
||
637 | return 0; |
||
638 | } |
||
639 | else { |
||
640 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetHandleARB"); |
||
641 | return 0; |
||
642 | } |
||
643 | } |
||
644 | |||
645 | |||
646 | /** |
||
647 | * glGetProgramiv() - get shader program state. |
||
648 | * Note that this is for GLSL shader programs, not ARB vertex/fragment |
||
649 | * programs (see glGetProgramivARB). |
||
650 | */ |
||
651 | static void |
||
652 | get_programiv(struct gl_context *ctx, GLuint program, GLenum pname, GLint *params) |
||
653 | { |
||
654 | const struct gl_program_parameter_list *attribs; |
||
655 | struct gl_shader_program *shProg |
||
656 | = _mesa_lookup_shader_program(ctx, program); |
||
657 | |||
658 | if (!shProg) { |
||
659 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramiv(program)"); |
||
660 | return; |
||
661 | } |
||
662 | |||
663 | if (shProg->VertexProgram) |
||
664 | attribs = shProg->VertexProgram->Base.Attributes; |
||
665 | else |
||
666 | attribs = NULL; |
||
667 | |||
668 | switch (pname) { |
||
669 | case GL_DELETE_STATUS: |
||
670 | *params = shProg->DeletePending; |
||
671 | break; |
||
672 | case GL_LINK_STATUS: |
||
673 | *params = shProg->LinkStatus; |
||
674 | break; |
||
675 | case GL_VALIDATE_STATUS: |
||
676 | *params = shProg->Validated; |
||
677 | break; |
||
678 | case GL_INFO_LOG_LENGTH: |
||
679 | *params = shProg->InfoLog ? strlen(shProg->InfoLog) + 1 : 0; |
||
680 | break; |
||
681 | case GL_ATTACHED_SHADERS: |
||
682 | *params = shProg->NumShaders; |
||
683 | break; |
||
684 | case GL_ACTIVE_ATTRIBUTES: |
||
685 | *params = attribs ? attribs->NumParameters : 0; |
||
686 | break; |
||
687 | case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: |
||
688 | *params = _mesa_longest_parameter_name(attribs, PROGRAM_INPUT) + 1; |
||
689 | break; |
||
690 | case GL_ACTIVE_UNIFORMS: |
||
691 | *params = shProg->Uniforms ? shProg->Uniforms->NumUniforms : 0; |
||
692 | break; |
||
693 | case GL_ACTIVE_UNIFORM_MAX_LENGTH: |
||
694 | *params = _mesa_longest_uniform_name(shProg->Uniforms); |
||
695 | if (*params > 0) |
||
696 | (*params)++; /* add one for terminating zero */ |
||
697 | break; |
||
698 | case GL_PROGRAM_BINARY_LENGTH_OES: |
||
699 | *params = 0; |
||
700 | break; |
||
701 | #if FEATURE_EXT_transform_feedback |
||
702 | case GL_TRANSFORM_FEEDBACK_VARYINGS: |
||
703 | *params = shProg->TransformFeedback.NumVarying; |
||
704 | break; |
||
705 | case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: |
||
706 | *params = longest_feedback_varying_name(shProg) + 1; |
||
707 | break; |
||
708 | case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: |
||
709 | *params = shProg->TransformFeedback.BufferMode; |
||
710 | break; |
||
711 | #endif |
||
712 | #if FEATURE_ARB_geometry_shader4 |
||
713 | case GL_GEOMETRY_VERTICES_OUT_ARB: |
||
714 | *params = shProg->Geom.VerticesOut; |
||
715 | break; |
||
716 | case GL_GEOMETRY_INPUT_TYPE_ARB: |
||
717 | *params = shProg->Geom.InputType; |
||
718 | break; |
||
719 | case GL_GEOMETRY_OUTPUT_TYPE_ARB: |
||
720 | *params = shProg->Geom.OutputType; |
||
721 | break; |
||
722 | #endif |
||
723 | default: |
||
724 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramiv(pname)"); |
||
725 | return; |
||
726 | } |
||
727 | } |
||
728 | |||
729 | |||
730 | /** |
||
731 | * glGetShaderiv() - get GLSL shader state |
||
732 | */ |
||
733 | static void |
||
734 | get_shaderiv(struct gl_context *ctx, GLuint name, GLenum pname, GLint *params) |
||
735 | { |
||
736 | struct gl_shader *shader = |
||
737 | _mesa_lookup_shader_err(ctx, name, "glGetShaderiv"); |
||
738 | |||
739 | if (!shader) { |
||
740 | return; |
||
741 | } |
||
742 | |||
743 | switch (pname) { |
||
744 | case GL_SHADER_TYPE: |
||
745 | *params = shader->Type; |
||
746 | break; |
||
747 | case GL_DELETE_STATUS: |
||
748 | *params = shader->DeletePending; |
||
749 | break; |
||
750 | case GL_COMPILE_STATUS: |
||
751 | *params = shader->CompileStatus; |
||
752 | break; |
||
753 | case GL_INFO_LOG_LENGTH: |
||
754 | *params = shader->InfoLog ? strlen(shader->InfoLog) + 1 : 0; |
||
755 | break; |
||
756 | case GL_SHADER_SOURCE_LENGTH: |
||
757 | *params = shader->Source ? strlen((char *) shader->Source) + 1 : 0; |
||
758 | break; |
||
759 | default: |
||
760 | _mesa_error(ctx, GL_INVALID_ENUM, "glGetShaderiv(pname)"); |
||
761 | return; |
||
762 | } |
||
763 | } |
||
764 | |||
765 | |||
766 | static void |
||
767 | get_program_info_log(struct gl_context *ctx, GLuint program, GLsizei bufSize, |
||
768 | GLsizei *length, GLchar *infoLog) |
||
769 | { |
||
770 | struct gl_shader_program *shProg |
||
771 | = _mesa_lookup_shader_program(ctx, program); |
||
772 | if (!shProg) { |
||
773 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetProgramInfoLog(program)"); |
||
774 | return; |
||
775 | } |
||
776 | _mesa_copy_string(infoLog, bufSize, length, shProg->InfoLog); |
||
777 | } |
||
778 | |||
779 | |||
780 | static void |
||
781 | get_shader_info_log(struct gl_context *ctx, GLuint shader, GLsizei bufSize, |
||
782 | GLsizei *length, GLchar *infoLog) |
||
783 | { |
||
784 | struct gl_shader *sh = _mesa_lookup_shader(ctx, shader); |
||
785 | if (!sh) { |
||
786 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetShaderInfoLog(shader)"); |
||
787 | return; |
||
788 | } |
||
789 | _mesa_copy_string(infoLog, bufSize, length, sh->InfoLog); |
||
790 | } |
||
791 | |||
792 | |||
793 | /** |
||
794 | * Return shader source code. |
||
795 | */ |
||
796 | static void |
||
797 | get_shader_source(struct gl_context *ctx, GLuint shader, GLsizei maxLength, |
||
798 | GLsizei *length, GLchar *sourceOut) |
||
799 | { |
||
800 | struct gl_shader *sh; |
||
801 | sh = _mesa_lookup_shader_err(ctx, shader, "glGetShaderSource"); |
||
802 | if (!sh) { |
||
803 | return; |
||
804 | } |
||
805 | _mesa_copy_string(sourceOut, maxLength, length, sh->Source); |
||
806 | } |
||
807 | |||
808 | |||
809 | /** |
||
810 | * Set/replace shader source code. |
||
811 | */ |
||
812 | static void |
||
813 | shader_source(struct gl_context *ctx, GLuint shader, const GLchar *source) |
||
814 | { |
||
815 | struct gl_shader *sh; |
||
816 | |||
817 | sh = _mesa_lookup_shader_err(ctx, shader, "glShaderSource"); |
||
818 | if (!sh) |
||
819 | return; |
||
820 | |||
821 | /* free old shader source string and install new one */ |
||
822 | if (sh->Source) { |
||
823 | free((void *) sh->Source); |
||
824 | } |
||
825 | sh->Source = source; |
||
826 | sh->CompileStatus = GL_FALSE; |
||
827 | #ifdef DEBUG |
||
828 | sh->SourceChecksum = _mesa_str_checksum(sh->Source); |
||
829 | #endif |
||
830 | } |
||
831 | |||
832 | |||
833 | /** |
||
834 | * Compile a shader. |
||
835 | */ |
||
836 | static void |
||
837 | compile_shader(struct gl_context *ctx, GLuint shaderObj) |
||
838 | { |
||
839 | struct gl_shader *sh; |
||
840 | struct gl_shader_compiler_options *options; |
||
841 | |||
842 | sh = _mesa_lookup_shader_err(ctx, shaderObj, "glCompileShader"); |
||
843 | if (!sh) |
||
844 | return; |
||
845 | |||
846 | options = &ctx->ShaderCompilerOptions[_mesa_shader_type_to_index(sh->Type)]; |
||
847 | |||
848 | /* set default pragma state for shader */ |
||
849 | sh->Pragmas = options->DefaultPragmas; |
||
850 | |||
851 | /* this call will set the sh->CompileStatus field to indicate if |
||
852 | * compilation was successful. |
||
853 | */ |
||
1902 | serge | 854 | _mesa_glsl_compile_shader(ctx, sh); |
1901 | serge | 855 | } |
856 | |||
857 | |||
858 | /** |
||
859 | * Link a program's shaders. |
||
860 | */ |
||
861 | static void |
||
862 | link_program(struct gl_context *ctx, GLuint program) |
||
863 | { |
||
864 | struct gl_shader_program *shProg; |
||
865 | struct gl_transform_feedback_object *obj = |
||
866 | ctx->TransformFeedback.CurrentObject; |
||
867 | |||
868 | shProg = _mesa_lookup_shader_program_err(ctx, program, "glLinkProgram"); |
||
869 | if (!shProg) |
||
870 | return; |
||
871 | |||
872 | if (obj->Active |
||
873 | && (shProg == ctx->Shader.CurrentVertexProgram |
||
874 | || shProg == ctx->Shader.CurrentGeometryProgram |
||
875 | || shProg == ctx->Shader.CurrentFragmentProgram)) { |
||
876 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
877 | "glLinkProgram(transform feedback active"); |
||
878 | return; |
||
879 | } |
||
880 | |||
881 | FLUSH_VERTICES(ctx, _NEW_PROGRAM); |
||
882 | |||
1902 | serge | 883 | _mesa_glsl_link_shader(ctx, shProg); |
1901 | serge | 884 | |
885 | /* debug code */ |
||
886 | if (0) { |
||
887 | GLuint i; |
||
888 | |||
889 | printf("Link %u shaders in program %u: %s\n", |
||
890 | shProg->NumShaders, shProg->Name, |
||
891 | shProg->LinkStatus ? "Success" : "Failed"); |
||
892 | |||
893 | for (i = 0; i < shProg->NumShaders; i++) { |
||
894 | printf(" shader %u, type 0x%x\n", |
||
895 | shProg->Shaders[i]->Name, |
||
896 | shProg->Shaders[i]->Type); |
||
897 | } |
||
898 | } |
||
899 | } |
||
900 | |||
901 | |||
902 | /** |
||
903 | * Print basic shader info (for debug). |
||
904 | */ |
||
905 | static void |
||
906 | print_shader_info(const struct gl_shader_program *shProg) |
||
907 | { |
||
908 | GLuint i; |
||
909 | |||
910 | printf("Mesa: glUseProgram(%u)\n", shProg->Name); |
||
911 | for (i = 0; i < shProg->NumShaders; i++) { |
||
912 | const char *s; |
||
913 | switch (shProg->Shaders[i]->Type) { |
||
914 | case GL_VERTEX_SHADER: |
||
915 | s = "vertex"; |
||
916 | break; |
||
917 | case GL_FRAGMENT_SHADER: |
||
918 | s = "fragment"; |
||
919 | break; |
||
920 | case GL_GEOMETRY_SHADER: |
||
921 | s = "geometry"; |
||
922 | break; |
||
923 | default: |
||
924 | s = ""; |
||
925 | } |
||
926 | printf(" %s shader %u, checksum %u\n", s, |
||
927 | shProg->Shaders[i]->Name, |
||
928 | shProg->Shaders[i]->SourceChecksum); |
||
929 | } |
||
930 | if (shProg->VertexProgram) |
||
931 | printf(" vert prog %u\n", shProg->VertexProgram->Base.Id); |
||
932 | if (shProg->FragmentProgram) |
||
933 | printf(" frag prog %u\n", shProg->FragmentProgram->Base.Id); |
||
934 | } |
||
935 | |||
936 | |||
937 | /** |
||
938 | * Use the named shader program for subsequent glUniform calls |
||
939 | */ |
||
940 | void |
||
941 | _mesa_active_program(struct gl_context *ctx, struct gl_shader_program *shProg, |
||
942 | const char *caller) |
||
943 | { |
||
944 | if ((shProg != NULL) && !shProg->LinkStatus) { |
||
945 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
946 | "%s(program %u not linked)", caller, shProg->Name); |
||
947 | return; |
||
948 | } |
||
949 | |||
950 | if (ctx->Shader.ActiveProgram != shProg) { |
||
951 | _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, shProg); |
||
952 | } |
||
953 | } |
||
954 | |||
955 | /** |
||
956 | */ |
||
957 | static bool |
||
958 | use_shader_program(struct gl_context *ctx, GLenum type, |
||
959 | struct gl_shader_program *shProg) |
||
960 | { |
||
961 | struct gl_shader_program **target; |
||
962 | |||
963 | switch (type) { |
||
964 | #if FEATURE_ARB_vertex_shader |
||
965 | case GL_VERTEX_SHADER: |
||
966 | target = &ctx->Shader.CurrentVertexProgram; |
||
967 | if ((shProg == NULL) |
||
968 | || (shProg->_LinkedShaders[MESA_SHADER_VERTEX] == NULL)) { |
||
969 | shProg = NULL; |
||
970 | } |
||
971 | break; |
||
972 | #endif |
||
973 | #if FEATURE_ARB_geometry_shader4 |
||
974 | case GL_GEOMETRY_SHADER_ARB: |
||
975 | target = &ctx->Shader.CurrentGeometryProgram; |
||
976 | if ((shProg == NULL) |
||
977 | || (shProg->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)) { |
||
978 | shProg = NULL; |
||
979 | } |
||
980 | break; |
||
981 | #endif |
||
982 | #if FEATURE_ARB_fragment_shader |
||
983 | case GL_FRAGMENT_SHADER: |
||
984 | target = &ctx->Shader.CurrentFragmentProgram; |
||
985 | if ((shProg == NULL) |
||
986 | || (shProg->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL)) { |
||
987 | shProg = NULL; |
||
988 | } |
||
989 | break; |
||
990 | #endif |
||
991 | default: |
||
992 | return false; |
||
993 | } |
||
994 | |||
995 | if (*target != shProg) { |
||
996 | FLUSH_VERTICES(ctx, _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS); |
||
997 | _mesa_reference_shader_program(ctx, target, shProg); |
||
998 | return true; |
||
999 | } |
||
1000 | |||
1001 | return false; |
||
1002 | } |
||
1003 | |||
1004 | /** |
||
1005 | * Use the named shader program for subsequent rendering. |
||
1006 | */ |
||
1007 | void |
||
1008 | _mesa_use_program(struct gl_context *ctx, struct gl_shader_program *shProg) |
||
1009 | { |
||
1010 | use_shader_program(ctx, GL_VERTEX_SHADER, shProg); |
||
1011 | use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, shProg); |
||
1012 | use_shader_program(ctx, GL_FRAGMENT_SHADER, shProg); |
||
1013 | _mesa_active_program(ctx, shProg, "glUseProgram"); |
||
1014 | |||
1015 | if (ctx->Driver.UseProgram) |
||
1016 | ctx->Driver.UseProgram(ctx, shProg); |
||
1017 | } |
||
1018 | |||
1019 | |||
1020 | /** |
||
1021 | * Validate a program's samplers. |
||
1022 | * Specifically, check that there aren't two samplers of different types |
||
1023 | * pointing to the same texture unit. |
||
1024 | * \return GL_TRUE if valid, GL_FALSE if invalid |
||
1025 | */ |
||
1026 | static GLboolean |
||
1027 | validate_samplers(const struct gl_program *prog, char *errMsg) |
||
1028 | { |
||
1029 | static const char *targetName[] = { |
||
1030 | "TEXTURE_2D_ARRAY", |
||
1031 | "TEXTURE_1D_ARRAY", |
||
1032 | "TEXTURE_CUBE", |
||
1033 | "TEXTURE_3D", |
||
1034 | "TEXTURE_RECT", |
||
1035 | "TEXTURE_2D", |
||
1036 | "TEXTURE_1D", |
||
1037 | }; |
||
1038 | GLint targetUsed[MAX_TEXTURE_IMAGE_UNITS]; |
||
1039 | GLbitfield samplersUsed = prog->SamplersUsed; |
||
1040 | GLuint i; |
||
1041 | |||
1042 | assert(Elements(targetName) == NUM_TEXTURE_TARGETS); |
||
1043 | |||
1044 | if (samplersUsed == 0x0) |
||
1045 | return GL_TRUE; |
||
1046 | |||
1047 | for (i = 0; i < Elements(targetUsed); i++) |
||
1048 | targetUsed[i] = -1; |
||
1049 | |||
1050 | /* walk over bits which are set in 'samplers' */ |
||
1051 | while (samplersUsed) { |
||
1052 | GLuint unit; |
||
1053 | gl_texture_index target; |
||
1054 | GLint sampler = _mesa_ffs(samplersUsed) - 1; |
||
1055 | assert(sampler >= 0); |
||
1056 | assert(sampler < MAX_TEXTURE_IMAGE_UNITS); |
||
1057 | unit = prog->SamplerUnits[sampler]; |
||
1058 | target = prog->SamplerTargets[sampler]; |
||
1059 | if (targetUsed[unit] != -1 && targetUsed[unit] != (int) target) { |
||
1060 | _mesa_snprintf(errMsg, 100, |
||
1061 | "Texture unit %d is accessed both as %s and %s", |
||
1062 | unit, targetName[targetUsed[unit]], targetName[target]); |
||
1063 | return GL_FALSE; |
||
1064 | } |
||
1065 | targetUsed[unit] = target; |
||
1066 | samplersUsed ^= (1 << sampler); |
||
1067 | } |
||
1068 | |||
1069 | return GL_TRUE; |
||
1070 | } |
||
1071 | |||
1072 | |||
1073 | /** |
||
1074 | * Do validation of the given shader program. |
||
1075 | * \param errMsg returns error message if validation fails. |
||
1076 | * \return GL_TRUE if valid, GL_FALSE if invalid (and set errMsg) |
||
1077 | */ |
||
1078 | static GLboolean |
||
1079 | validate_shader_program(const struct gl_shader_program *shProg, |
||
1080 | char *errMsg) |
||
1081 | { |
||
1082 | const struct gl_vertex_program *vp = shProg->VertexProgram; |
||
1083 | const struct gl_fragment_program *fp = shProg->FragmentProgram; |
||
1084 | |||
1085 | if (!shProg->LinkStatus) { |
||
1086 | return GL_FALSE; |
||
1087 | } |
||
1088 | |||
1089 | /* From the GL spec, a program is invalid if any of these are true: |
||
1090 | |||
1091 | any two active samplers in the current program object are of |
||
1092 | different types, but refer to the same texture image unit, |
||
1093 | |||
1094 | any active sampler in the current program object refers to a texture |
||
1095 | image unit where fixed-function fragment processing accesses a |
||
1096 | texture target that does not match the sampler type, or |
||
1097 | |||
1098 | the sum of the number of active samplers in the program and the |
||
1099 | number of texture image units enabled for fixed-function fragment |
||
1100 | processing exceeds the combined limit on the total number of texture |
||
1101 | image units allowed. |
||
1102 | */ |
||
1103 | |||
1104 | |||
1105 | /* |
||
1106 | * Check: any two active samplers in the current program object are of |
||
1107 | * different types, but refer to the same texture image unit, |
||
1108 | */ |
||
1109 | if (vp && !validate_samplers(&vp->Base, errMsg)) { |
||
1110 | return GL_FALSE; |
||
1111 | } |
||
1112 | if (fp && !validate_samplers(&fp->Base, errMsg)) { |
||
1113 | return GL_FALSE; |
||
1114 | } |
||
1115 | |||
1116 | return GL_TRUE; |
||
1117 | } |
||
1118 | |||
1119 | |||
1120 | /** |
||
1121 | * Called via glValidateProgram() |
||
1122 | */ |
||
1123 | static void |
||
1124 | validate_program(struct gl_context *ctx, GLuint program) |
||
1125 | { |
||
1126 | struct gl_shader_program *shProg; |
||
1127 | char errMsg[100]; |
||
1128 | |||
1129 | shProg = _mesa_lookup_shader_program_err(ctx, program, "glValidateProgram"); |
||
1130 | if (!shProg) { |
||
1131 | return; |
||
1132 | } |
||
1133 | |||
1134 | shProg->Validated = validate_shader_program(shProg, errMsg); |
||
1135 | if (!shProg->Validated) { |
||
1136 | /* update info log */ |
||
1137 | if (shProg->InfoLog) { |
||
1138 | ralloc_free(shProg->InfoLog); |
||
1139 | } |
||
1140 | shProg->InfoLog = ralloc_strdup(shProg, errMsg); |
||
1141 | } |
||
1142 | } |
||
1143 | |||
1144 | |||
1145 | |||
1146 | void GLAPIENTRY |
||
1147 | _mesa_AttachObjectARB(GLhandleARB program, GLhandleARB shader) |
||
1148 | { |
||
1149 | GET_CURRENT_CONTEXT(ctx); |
||
1150 | attach_shader(ctx, program, shader); |
||
1151 | } |
||
1152 | |||
1153 | |||
1154 | void GLAPIENTRY |
||
1155 | _mesa_AttachShader(GLuint program, GLuint shader) |
||
1156 | { |
||
1157 | GET_CURRENT_CONTEXT(ctx); |
||
1158 | attach_shader(ctx, program, shader); |
||
1159 | } |
||
1160 | |||
1161 | |||
1162 | void GLAPIENTRY |
||
1163 | _mesa_BindAttribLocationARB(GLhandleARB program, GLuint index, |
||
1164 | const GLcharARB *name) |
||
1165 | { |
||
1166 | GET_CURRENT_CONTEXT(ctx); |
||
1167 | bind_attrib_location(ctx, program, index, name); |
||
1168 | } |
||
1169 | |||
1170 | |||
1171 | /* GL_EXT_gpu_shader4, GL3 */ |
||
1172 | void GLAPIENTRY |
||
1173 | _mesa_BindFragDataLocation(GLuint program, GLuint colorNumber, |
||
1174 | const GLchar *name) |
||
1175 | { |
||
1176 | GET_CURRENT_CONTEXT(ctx); |
||
1177 | bind_frag_data_location(ctx, program, colorNumber, name); |
||
1178 | } |
||
1179 | |||
1180 | |||
1181 | void GLAPIENTRY |
||
1182 | _mesa_CompileShaderARB(GLhandleARB shaderObj) |
||
1183 | { |
||
1184 | GET_CURRENT_CONTEXT(ctx); |
||
1185 | compile_shader(ctx, shaderObj); |
||
1186 | } |
||
1187 | |||
1188 | |||
1189 | GLuint GLAPIENTRY |
||
1190 | _mesa_CreateShader(GLenum type) |
||
1191 | { |
||
1192 | GET_CURRENT_CONTEXT(ctx); |
||
1193 | return create_shader(ctx, type); |
||
1194 | } |
||
1195 | |||
1196 | |||
1197 | GLhandleARB GLAPIENTRY |
||
1198 | _mesa_CreateShaderObjectARB(GLenum type) |
||
1199 | { |
||
1200 | GET_CURRENT_CONTEXT(ctx); |
||
1201 | return create_shader(ctx, type); |
||
1202 | } |
||
1203 | |||
1204 | |||
1205 | GLuint GLAPIENTRY |
||
1206 | _mesa_CreateProgram(void) |
||
1207 | { |
||
1208 | GET_CURRENT_CONTEXT(ctx); |
||
1209 | return create_shader_program(ctx); |
||
1210 | } |
||
1211 | |||
1212 | |||
1213 | GLhandleARB GLAPIENTRY |
||
1214 | _mesa_CreateProgramObjectARB(void) |
||
1215 | { |
||
1216 | GET_CURRENT_CONTEXT(ctx); |
||
1217 | return create_shader_program(ctx); |
||
1218 | } |
||
1219 | |||
1220 | |||
1221 | void GLAPIENTRY |
||
1222 | _mesa_DeleteObjectARB(GLhandleARB obj) |
||
1223 | { |
||
1224 | if (obj) { |
||
1225 | GET_CURRENT_CONTEXT(ctx); |
||
1226 | if (is_program(ctx, obj)) { |
||
1227 | delete_shader_program(ctx, obj); |
||
1228 | } |
||
1229 | else if (is_shader(ctx, obj)) { |
||
1230 | delete_shader(ctx, obj); |
||
1231 | } |
||
1232 | else { |
||
1233 | /* error? */ |
||
1234 | } |
||
1235 | } |
||
1236 | } |
||
1237 | |||
1238 | |||
1239 | void GLAPIENTRY |
||
1240 | _mesa_DeleteProgram(GLuint name) |
||
1241 | { |
||
1242 | if (name) { |
||
1243 | GET_CURRENT_CONTEXT(ctx); |
||
1244 | delete_shader_program(ctx, name); |
||
1245 | } |
||
1246 | } |
||
1247 | |||
1248 | |||
1249 | void GLAPIENTRY |
||
1250 | _mesa_DeleteShader(GLuint name) |
||
1251 | { |
||
1252 | if (name) { |
||
1253 | GET_CURRENT_CONTEXT(ctx); |
||
1254 | delete_shader(ctx, name); |
||
1255 | } |
||
1256 | } |
||
1257 | |||
1258 | |||
1259 | void GLAPIENTRY |
||
1260 | _mesa_DetachObjectARB(GLhandleARB program, GLhandleARB shader) |
||
1261 | { |
||
1262 | GET_CURRENT_CONTEXT(ctx); |
||
1263 | detach_shader(ctx, program, shader); |
||
1264 | } |
||
1265 | |||
1266 | |||
1267 | void GLAPIENTRY |
||
1268 | _mesa_DetachShader(GLuint program, GLuint shader) |
||
1269 | { |
||
1270 | GET_CURRENT_CONTEXT(ctx); |
||
1271 | detach_shader(ctx, program, shader); |
||
1272 | } |
||
1273 | |||
1274 | |||
1275 | void GLAPIENTRY |
||
1276 | _mesa_GetActiveAttribARB(GLhandleARB program, GLuint index, |
||
1277 | GLsizei maxLength, GLsizei * length, GLint * size, |
||
1278 | GLenum * type, GLcharARB * name) |
||
1279 | { |
||
1280 | GET_CURRENT_CONTEXT(ctx); |
||
1281 | get_active_attrib(ctx, program, index, maxLength, length, size, type, name); |
||
1282 | } |
||
1283 | |||
1284 | |||
1285 | void GLAPIENTRY |
||
1286 | _mesa_GetAttachedObjectsARB(GLhandleARB container, GLsizei maxCount, |
||
1287 | GLsizei * count, GLhandleARB * obj) |
||
1288 | { |
||
1289 | GET_CURRENT_CONTEXT(ctx); |
||
1290 | get_attached_shaders(ctx, container, maxCount, count, obj); |
||
1291 | } |
||
1292 | |||
1293 | |||
1294 | void GLAPIENTRY |
||
1295 | _mesa_GetAttachedShaders(GLuint program, GLsizei maxCount, |
||
1296 | GLsizei *count, GLuint *obj) |
||
1297 | { |
||
1298 | GET_CURRENT_CONTEXT(ctx); |
||
1299 | get_attached_shaders(ctx, program, maxCount, count, obj); |
||
1300 | } |
||
1301 | |||
1302 | |||
1303 | GLint GLAPIENTRY |
||
1304 | _mesa_GetAttribLocationARB(GLhandleARB program, const GLcharARB * name) |
||
1305 | { |
||
1306 | GET_CURRENT_CONTEXT(ctx); |
||
1307 | return get_attrib_location(ctx, program, name); |
||
1308 | } |
||
1309 | |||
1310 | |||
1311 | /* GL_EXT_gpu_shader4, GL3 */ |
||
1312 | GLint GLAPIENTRY |
||
1313 | _mesa_GetFragDataLocation(GLuint program, const GLchar *name) |
||
1314 | { |
||
1315 | GET_CURRENT_CONTEXT(ctx); |
||
1316 | return get_frag_data_location(ctx, program, name); |
||
1317 | } |
||
1318 | |||
1319 | |||
1320 | |||
1321 | void GLAPIENTRY |
||
1322 | _mesa_GetInfoLogARB(GLhandleARB object, GLsizei maxLength, GLsizei * length, |
||
1323 | GLcharARB * infoLog) |
||
1324 | { |
||
1325 | GET_CURRENT_CONTEXT(ctx); |
||
1326 | if (is_program(ctx, object)) { |
||
1327 | get_program_info_log(ctx, object, maxLength, length, infoLog); |
||
1328 | } |
||
1329 | else if (is_shader(ctx, object)) { |
||
1330 | get_shader_info_log(ctx, object, maxLength, length, infoLog); |
||
1331 | } |
||
1332 | else { |
||
1333 | _mesa_error(ctx, GL_INVALID_OPERATION, "glGetInfoLogARB"); |
||
1334 | } |
||
1335 | } |
||
1336 | |||
1337 | |||
1338 | void GLAPIENTRY |
||
1339 | _mesa_GetObjectParameterivARB(GLhandleARB object, GLenum pname, GLint *params) |
||
1340 | { |
||
1341 | GET_CURRENT_CONTEXT(ctx); |
||
1342 | /* Implement in terms of GetProgramiv, GetShaderiv */ |
||
1343 | if (is_program(ctx, object)) { |
||
1344 | if (pname == GL_OBJECT_TYPE_ARB) { |
||
1345 | *params = GL_PROGRAM_OBJECT_ARB; |
||
1346 | } |
||
1347 | else { |
||
1348 | get_programiv(ctx, object, pname, params); |
||
1349 | } |
||
1350 | } |
||
1351 | else if (is_shader(ctx, object)) { |
||
1352 | if (pname == GL_OBJECT_TYPE_ARB) { |
||
1353 | *params = GL_SHADER_OBJECT_ARB; |
||
1354 | } |
||
1355 | else { |
||
1356 | get_shaderiv(ctx, object, pname, params); |
||
1357 | } |
||
1358 | } |
||
1359 | else { |
||
1360 | _mesa_error(ctx, GL_INVALID_VALUE, "glGetObjectParameterivARB"); |
||
1361 | } |
||
1362 | } |
||
1363 | |||
1364 | |||
1365 | void GLAPIENTRY |
||
1366 | _mesa_GetObjectParameterfvARB(GLhandleARB object, GLenum pname, |
||
1367 | GLfloat *params) |
||
1368 | { |
||
1369 | GLint iparams[1]; /* XXX is one element enough? */ |
||
1370 | _mesa_GetObjectParameterivARB(object, pname, iparams); |
||
1371 | params[0] = (GLfloat) iparams[0]; |
||
1372 | } |
||
1373 | |||
1374 | |||
1375 | void GLAPIENTRY |
||
1376 | _mesa_GetProgramiv(GLuint program, GLenum pname, GLint *params) |
||
1377 | { |
||
1378 | GET_CURRENT_CONTEXT(ctx); |
||
1379 | get_programiv(ctx, program, pname, params); |
||
1380 | } |
||
1381 | |||
1382 | |||
1383 | void GLAPIENTRY |
||
1384 | _mesa_GetShaderiv(GLuint shader, GLenum pname, GLint *params) |
||
1385 | { |
||
1386 | GET_CURRENT_CONTEXT(ctx); |
||
1387 | get_shaderiv(ctx, shader, pname, params); |
||
1388 | } |
||
1389 | |||
1390 | |||
1391 | void GLAPIENTRY |
||
1392 | _mesa_GetProgramInfoLog(GLuint program, GLsizei bufSize, |
||
1393 | GLsizei *length, GLchar *infoLog) |
||
1394 | { |
||
1395 | GET_CURRENT_CONTEXT(ctx); |
||
1396 | get_program_info_log(ctx, program, bufSize, length, infoLog); |
||
1397 | } |
||
1398 | |||
1399 | |||
1400 | void GLAPIENTRY |
||
1401 | _mesa_GetShaderInfoLog(GLuint shader, GLsizei bufSize, |
||
1402 | GLsizei *length, GLchar *infoLog) |
||
1403 | { |
||
1404 | GET_CURRENT_CONTEXT(ctx); |
||
1405 | get_shader_info_log(ctx, shader, bufSize, length, infoLog); |
||
1406 | } |
||
1407 | |||
1408 | |||
1409 | void GLAPIENTRY |
||
1410 | _mesa_GetShaderSourceARB(GLhandleARB shader, GLsizei maxLength, |
||
1411 | GLsizei *length, GLcharARB *sourceOut) |
||
1412 | { |
||
1413 | GET_CURRENT_CONTEXT(ctx); |
||
1414 | get_shader_source(ctx, shader, maxLength, length, sourceOut); |
||
1415 | } |
||
1416 | |||
1417 | |||
1418 | GLhandleARB GLAPIENTRY |
||
1419 | _mesa_GetHandleARB(GLenum pname) |
||
1420 | { |
||
1421 | GET_CURRENT_CONTEXT(ctx); |
||
1422 | return get_handle(ctx, pname); |
||
1423 | } |
||
1424 | |||
1425 | |||
1426 | GLboolean GLAPIENTRY |
||
1427 | _mesa_IsProgram(GLuint name) |
||
1428 | { |
||
1429 | GET_CURRENT_CONTEXT(ctx); |
||
1430 | return is_program(ctx, name); |
||
1431 | } |
||
1432 | |||
1433 | |||
1434 | GLboolean GLAPIENTRY |
||
1435 | _mesa_IsShader(GLuint name) |
||
1436 | { |
||
1437 | GET_CURRENT_CONTEXT(ctx); |
||
1438 | return is_shader(ctx, name); |
||
1439 | } |
||
1440 | |||
1441 | |||
1442 | void GLAPIENTRY |
||
1443 | _mesa_LinkProgramARB(GLhandleARB programObj) |
||
1444 | { |
||
1445 | GET_CURRENT_CONTEXT(ctx); |
||
1446 | link_program(ctx, programObj); |
||
1447 | } |
||
1448 | |||
1449 | |||
1450 | |||
1451 | /** |
||
1452 | * Read shader source code from a file. |
||
1453 | * Useful for debugging to override an app's shader. |
||
1454 | */ |
||
1455 | static GLcharARB * |
||
1456 | read_shader(const char *fname) |
||
1457 | { |
||
1458 | const int max = 50*1000; |
||
1459 | FILE *f = fopen(fname, "r"); |
||
1460 | GLcharARB *buffer, *shader; |
||
1461 | int len; |
||
1462 | |||
1463 | if (!f) { |
||
1464 | return NULL; |
||
1465 | } |
||
1466 | |||
1467 | buffer = (char *) malloc(max); |
||
1468 | len = fread(buffer, 1, max, f); |
||
1469 | buffer[len] = 0; |
||
1470 | |||
1471 | fclose(f); |
||
1472 | |||
1473 | shader = _mesa_strdup(buffer); |
||
1474 | free(buffer); |
||
1475 | |||
1476 | return shader; |
||
1477 | } |
||
1478 | |||
1479 | |||
1480 | /** |
||
1481 | * Called via glShaderSource() and glShaderSourceARB() API functions. |
||
1482 | * Basically, concatenate the source code strings into one long string |
||
1483 | * and pass it to _mesa_shader_source(). |
||
1484 | */ |
||
1485 | void GLAPIENTRY |
||
1486 | _mesa_ShaderSourceARB(GLhandleARB shaderObj, GLsizei count, |
||
1487 | const GLcharARB ** string, const GLint * length) |
||
1488 | { |
||
1489 | GET_CURRENT_CONTEXT(ctx); |
||
1490 | GLint *offsets; |
||
1491 | GLsizei i, totalLength; |
||
1492 | GLcharARB *source; |
||
1493 | GLuint checksum; |
||
1494 | |||
1495 | if (!shaderObj || string == NULL) { |
||
1496 | _mesa_error(ctx, GL_INVALID_VALUE, "glShaderSourceARB"); |
||
1497 | return; |
||
1498 | } |
||
1499 | |||
1500 | /* |
||
1501 | * This array holds offsets of where the appropriate string ends, thus the |
||
1502 | * last element will be set to the total length of the source code. |
||
1503 | */ |
||
1504 | offsets = (GLint *) malloc(count * sizeof(GLint)); |
||
1505 | if (offsets == NULL) { |
||
1506 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); |
||
1507 | return; |
||
1508 | } |
||
1509 | |||
1510 | for (i = 0; i < count; i++) { |
||
1511 | if (string[i] == NULL) { |
||
1512 | free((GLvoid *) offsets); |
||
1513 | _mesa_error(ctx, GL_INVALID_OPERATION, "glShaderSourceARB(null string)"); |
||
1514 | return; |
||
1515 | } |
||
1516 | if (length == NULL || length[i] < 0) |
||
1517 | offsets[i] = strlen(string[i]); |
||
1518 | else |
||
1519 | offsets[i] = length[i]; |
||
1520 | /* accumulate string lengths */ |
||
1521 | if (i > 0) |
||
1522 | offsets[i] += offsets[i - 1]; |
||
1523 | } |
||
1524 | |||
1525 | /* Total length of source string is sum off all strings plus two. |
||
1526 | * One extra byte for terminating zero, another extra byte to silence |
||
1527 | * valgrind warnings in the parser/grammer code. |
||
1528 | */ |
||
1529 | totalLength = offsets[count - 1] + 2; |
||
1530 | source = (GLcharARB *) malloc(totalLength * sizeof(GLcharARB)); |
||
1531 | if (source == NULL) { |
||
1532 | free((GLvoid *) offsets); |
||
1533 | _mesa_error(ctx, GL_OUT_OF_MEMORY, "glShaderSourceARB"); |
||
1534 | return; |
||
1535 | } |
||
1536 | |||
1537 | for (i = 0; i < count; i++) { |
||
1538 | GLint start = (i > 0) ? offsets[i - 1] : 0; |
||
1539 | memcpy(source + start, string[i], |
||
1540 | (offsets[i] - start) * sizeof(GLcharARB)); |
||
1541 | } |
||
1542 | source[totalLength - 1] = '\0'; |
||
1543 | source[totalLength - 2] = '\0'; |
||
1544 | |||
1545 | if (SHADER_SUBST) { |
||
1546 | /* Compute the shader's source code checksum then try to open a file |
||
1547 | * named newshader_ |
||
1548 | * original shader source code. For debugging. |
||
1549 | */ |
||
1550 | char filename[100]; |
||
1551 | GLcharARB *newSource; |
||
1552 | |||
1553 | checksum = _mesa_str_checksum(source); |
||
1554 | |||
1555 | _mesa_snprintf(filename, sizeof(filename), "newshader_%d", checksum); |
||
1556 | |||
1557 | newSource = read_shader(filename); |
||
1558 | if (newSource) { |
||
1559 | fprintf(stderr, "Mesa: Replacing shader %u chksum=%d with %s\n", |
||
1560 | shaderObj, checksum, filename); |
||
1561 | free(source); |
||
1562 | source = newSource; |
||
1563 | } |
||
1564 | } |
||
1565 | |||
1566 | shader_source(ctx, shaderObj, source); |
||
1567 | |||
1568 | if (SHADER_SUBST) { |
||
1569 | struct gl_shader *sh = _mesa_lookup_shader(ctx, shaderObj); |
||
1570 | if (sh) |
||
1571 | sh->SourceChecksum = checksum; /* save original checksum */ |
||
1572 | } |
||
1573 | |||
1574 | free(offsets); |
||
1575 | } |
||
1576 | |||
1577 | |||
1578 | void GLAPIENTRY |
||
1579 | _mesa_UseProgramObjectARB(GLhandleARB program) |
||
1580 | { |
||
1581 | GET_CURRENT_CONTEXT(ctx); |
||
1582 | struct gl_shader_program *shProg; |
||
1583 | struct gl_transform_feedback_object *obj = |
||
1584 | ctx->TransformFeedback.CurrentObject; |
||
1585 | |||
1586 | if (obj->Active) { |
||
1587 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
1588 | "glUseProgram(transform feedback active)"); |
||
1589 | return; |
||
1590 | } |
||
1591 | |||
1592 | if (program) { |
||
1593 | shProg = _mesa_lookup_shader_program_err(ctx, program, "glUseProgram"); |
||
1594 | if (!shProg) { |
||
1595 | return; |
||
1596 | } |
||
1597 | if (!shProg->LinkStatus) { |
||
1598 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
1599 | "glUseProgram(program %u not linked)", program); |
||
1600 | return; |
||
1601 | } |
||
1602 | |||
1603 | /* debug code */ |
||
1604 | if (ctx->Shader.Flags & GLSL_USE_PROG) { |
||
1605 | print_shader_info(shProg); |
||
1606 | } |
||
1607 | } |
||
1608 | else { |
||
1609 | shProg = NULL; |
||
1610 | } |
||
1611 | |||
1612 | _mesa_use_program(ctx, shProg); |
||
1613 | } |
||
1614 | |||
1615 | |||
1616 | void GLAPIENTRY |
||
1617 | _mesa_ValidateProgramARB(GLhandleARB program) |
||
1618 | { |
||
1619 | GET_CURRENT_CONTEXT(ctx); |
||
1620 | validate_program(ctx, program); |
||
1621 | } |
||
1622 | |||
1623 | #ifdef FEATURE_ES2 |
||
1624 | |||
1625 | void GLAPIENTRY |
||
1626 | _mesa_GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, |
||
1627 | GLint* range, GLint* precision) |
||
1628 | { |
||
1629 | const struct gl_program_constants *limits; |
||
1630 | const struct gl_precision *p; |
||
1631 | GET_CURRENT_CONTEXT(ctx); |
||
1632 | |||
1633 | switch (shadertype) { |
||
1634 | case GL_VERTEX_SHADER: |
||
1635 | limits = &ctx->Const.VertexProgram; |
||
1636 | break; |
||
1637 | case GL_FRAGMENT_SHADER: |
||
1638 | limits = &ctx->Const.FragmentProgram; |
||
1639 | break; |
||
1640 | default: |
||
1641 | _mesa_error(ctx, GL_INVALID_ENUM, |
||
1642 | "glGetShaderPrecisionFormat(shadertype)"); |
||
1643 | return; |
||
1644 | } |
||
1645 | |||
1646 | switch (precisiontype) { |
||
1647 | case GL_LOW_FLOAT: |
||
1648 | p = &limits->LowFloat; |
||
1649 | break; |
||
1650 | case GL_MEDIUM_FLOAT: |
||
1651 | p = &limits->MediumFloat; |
||
1652 | break; |
||
1653 | case GL_HIGH_FLOAT: |
||
1654 | p = &limits->HighFloat; |
||
1655 | break; |
||
1656 | case GL_LOW_INT: |
||
1657 | p = &limits->LowInt; |
||
1658 | break; |
||
1659 | case GL_MEDIUM_INT: |
||
1660 | p = &limits->MediumInt; |
||
1661 | break; |
||
1662 | case GL_HIGH_INT: |
||
1663 | p = &limits->HighInt; |
||
1664 | break; |
||
1665 | default: |
||
1666 | _mesa_error(ctx, GL_INVALID_ENUM, |
||
1667 | "glGetShaderPrecisionFormat(precisiontype)"); |
||
1668 | return; |
||
1669 | } |
||
1670 | |||
1671 | range[0] = p->RangeMin; |
||
1672 | range[1] = p->RangeMax; |
||
1673 | precision[0] = p->Precision; |
||
1674 | } |
||
1675 | |||
1676 | |||
1677 | void GLAPIENTRY |
||
1678 | _mesa_ReleaseShaderCompiler(void) |
||
1679 | { |
||
1902 | serge | 1680 | _mesa_destroy_shader_compiler_caches(); |
1901 | serge | 1681 | } |
1682 | |||
1683 | |||
1684 | void GLAPIENTRY |
||
1685 | _mesa_ShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, |
||
1686 | const void* binary, GLint length) |
||
1687 | { |
||
1688 | GET_CURRENT_CONTEXT(ctx); |
||
1689 | (void) n; |
||
1690 | (void) shaders; |
||
1691 | (void) binaryformat; |
||
1692 | (void) binary; |
||
1693 | (void) length; |
||
1694 | _mesa_error(ctx, GL_INVALID_OPERATION, __FUNCTION__); |
||
1695 | } |
||
1696 | |||
1697 | #endif /* FEATURE_ES2 */ |
||
1698 | |||
1699 | |||
1700 | #if FEATURE_ARB_geometry_shader4 |
||
1701 | |||
1702 | void GLAPIENTRY |
||
1703 | _mesa_ProgramParameteriARB(GLuint program, GLenum pname, |
||
1704 | GLint value) |
||
1705 | { |
||
1706 | struct gl_shader_program *shProg; |
||
1707 | GET_CURRENT_CONTEXT(ctx); |
||
1708 | |||
1709 | ASSERT_OUTSIDE_BEGIN_END(ctx); |
||
1710 | |||
1711 | shProg = _mesa_lookup_shader_program_err(ctx, program, |
||
1712 | "glProgramParameteri"); |
||
1713 | if (!shProg) |
||
1714 | return; |
||
1715 | |||
1716 | switch (pname) { |
||
1717 | case GL_GEOMETRY_VERTICES_OUT_ARB: |
||
1718 | if (value < 1 || |
||
1719 | (unsigned) value > ctx->Const.GeometryProgram.MaxGeometryOutputVertices) { |
||
1720 | _mesa_error(ctx, GL_INVALID_VALUE, |
||
1721 | "glProgramParameteri(GL_GEOMETRY_VERTICES_OUT_ARB=%d", |
||
1722 | value); |
||
1723 | return; |
||
1724 | } |
||
1725 | shProg->Geom.VerticesOut = value; |
||
1726 | break; |
||
1727 | case GL_GEOMETRY_INPUT_TYPE_ARB: |
||
1728 | switch (value) { |
||
1729 | case GL_POINTS: |
||
1730 | case GL_LINES: |
||
1731 | case GL_LINES_ADJACENCY_ARB: |
||
1732 | case GL_TRIANGLES: |
||
1733 | case GL_TRIANGLES_ADJACENCY_ARB: |
||
1734 | shProg->Geom.InputType = value; |
||
1735 | break; |
||
1736 | default: |
||
1737 | _mesa_error(ctx, GL_INVALID_VALUE, |
||
1738 | "glProgramParameteri(geometry input type = %s", |
||
1739 | _mesa_lookup_enum_by_nr(value)); |
||
1740 | return; |
||
1741 | } |
||
1742 | break; |
||
1743 | case GL_GEOMETRY_OUTPUT_TYPE_ARB: |
||
1744 | switch (value) { |
||
1745 | case GL_POINTS: |
||
1746 | case GL_LINE_STRIP: |
||
1747 | case GL_TRIANGLE_STRIP: |
||
1748 | shProg->Geom.OutputType = value; |
||
1749 | break; |
||
1750 | default: |
||
1751 | _mesa_error(ctx, GL_INVALID_VALUE, |
||
1752 | "glProgramParameteri(geometry output type = %s", |
||
1753 | _mesa_lookup_enum_by_nr(value)); |
||
1754 | return; |
||
1755 | } |
||
1756 | break; |
||
1757 | default: |
||
1758 | _mesa_error(ctx, GL_INVALID_ENUM, "glProgramParameteriARB(pname=%s)", |
||
1759 | _mesa_lookup_enum_by_nr(pname)); |
||
1760 | break; |
||
1761 | } |
||
1762 | } |
||
1763 | |||
1764 | #endif |
||
1765 | |||
1766 | void |
||
1767 | _mesa_use_shader_program(struct gl_context *ctx, GLenum type, |
||
1768 | struct gl_shader_program *shProg) |
||
1769 | { |
||
1770 | use_shader_program(ctx, type, shProg); |
||
1771 | |||
1772 | if (ctx->Driver.UseProgram) |
||
1773 | ctx->Driver.UseProgram(ctx, shProg); |
||
1774 | } |
||
1775 | |||
1776 | void GLAPIENTRY |
||
1777 | _mesa_UseShaderProgramEXT(GLenum type, GLuint program) |
||
1778 | { |
||
1779 | GET_CURRENT_CONTEXT(ctx); |
||
1780 | struct gl_shader_program *shProg = NULL; |
||
1781 | |||
1782 | if (!validate_shader_target(ctx, type)) { |
||
1783 | _mesa_error(ctx, GL_INVALID_ENUM, "glUseShaderProgramEXT(type)"); |
||
1784 | return; |
||
1785 | } |
||
1786 | |||
1787 | if (ctx->TransformFeedback.CurrentObject->Active) { |
||
1788 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
1789 | "glUseShaderProgramEXT(transform feedback is active)"); |
||
1790 | return; |
||
1791 | } |
||
1792 | |||
1793 | if (program) { |
||
1794 | shProg = _mesa_lookup_shader_program_err(ctx, program, |
||
1795 | "glUseShaderProgramEXT"); |
||
1796 | if (shProg == NULL) |
||
1797 | return; |
||
1798 | |||
1799 | if (!shProg->LinkStatus) { |
||
1800 | _mesa_error(ctx, GL_INVALID_OPERATION, |
||
1801 | "glUseShaderProgramEXT(program not linked)"); |
||
1802 | return; |
||
1803 | } |
||
1804 | } |
||
1805 | |||
1806 | _mesa_use_shader_program(ctx, type, shProg); |
||
1807 | } |
||
1808 | |||
1809 | void GLAPIENTRY |
||
1810 | _mesa_ActiveProgramEXT(GLuint program) |
||
1811 | { |
||
1812 | GET_CURRENT_CONTEXT(ctx); |
||
1813 | struct gl_shader_program *shProg = (program != 0) |
||
1814 | ? _mesa_lookup_shader_program_err(ctx, program, "glActiveProgramEXT") |
||
1815 | : NULL; |
||
1816 | |||
1817 | _mesa_active_program(ctx, shProg, "glActiveProgramEXT"); |
||
1818 | return; |
||
1819 | } |
||
1820 | |||
1821 | GLuint GLAPIENTRY |
||
1822 | _mesa_CreateShaderProgramEXT(GLenum type, const GLchar *string) |
||
1823 | { |
||
1824 | GET_CURRENT_CONTEXT(ctx); |
||
1825 | const GLuint shader = create_shader(ctx, type); |
||
1826 | GLuint program = 0; |
||
1827 | |||
1828 | if (shader) { |
||
1829 | shader_source(ctx, shader, _mesa_strdup(string)); |
||
1830 | compile_shader(ctx, shader); |
||
1831 | |||
1832 | program = create_shader_program(ctx); |
||
1833 | if (program) { |
||
1834 | struct gl_shader_program *shProg; |
||
1835 | struct gl_shader *sh; |
||
1836 | GLint compiled = GL_FALSE; |
||
1837 | |||
1838 | shProg = _mesa_lookup_shader_program(ctx, program); |
||
1839 | sh = _mesa_lookup_shader(ctx, shader); |
||
1840 | |||
1841 | get_shaderiv(ctx, shader, GL_COMPILE_STATUS, &compiled); |
||
1842 | if (compiled) { |
||
1843 | attach_shader(ctx, program, shader); |
||
1844 | link_program(ctx, program); |
||
1845 | detach_shader(ctx, program, shader); |
||
1846 | |||
1847 | #if 0 |
||
1848 | /* Possibly... */ |
||
1849 | if (active-user-defined-varyings-in-linked-program) { |
||
1850 | append-error-to-info-log; |
||
1851 | shProg->LinkStatus = GL_FALSE; |
||
1852 | } |
||
1853 | #endif |
||
1854 | } |
||
1855 | |||
1856 | ralloc_strcat(&shProg->InfoLog, sh->InfoLog); |
||
1857 | } |
||
1858 | |||
1859 | delete_shader(ctx, shader); |
||
1860 | } |
||
1861 | |||
1862 | return program; |
||
1863 | } |
||
1864 | |||
1865 | /** |
||
1866 | * Plug in shader-related functions into API dispatch table. |
||
1867 | */ |
||
1868 | void |
||
1869 | _mesa_init_shader_dispatch(struct _glapi_table *exec) |
||
1870 | { |
||
1871 | #if FEATURE_GL |
||
1872 | /* GL_ARB_vertex/fragment_shader */ |
||
1873 | SET_DeleteObjectARB(exec, _mesa_DeleteObjectARB); |
||
1874 | SET_GetHandleARB(exec, _mesa_GetHandleARB); |
||
1875 | SET_DetachObjectARB(exec, _mesa_DetachObjectARB); |
||
1876 | SET_CreateShaderObjectARB(exec, _mesa_CreateShaderObjectARB); |
||
1877 | SET_ShaderSourceARB(exec, _mesa_ShaderSourceARB); |
||
1878 | SET_CompileShaderARB(exec, _mesa_CompileShaderARB); |
||
1879 | SET_CreateProgramObjectARB(exec, _mesa_CreateProgramObjectARB); |
||
1880 | SET_AttachObjectARB(exec, _mesa_AttachObjectARB); |
||
1881 | SET_LinkProgramARB(exec, _mesa_LinkProgramARB); |
||
1882 | SET_UseProgramObjectARB(exec, _mesa_UseProgramObjectARB); |
||
1883 | SET_ValidateProgramARB(exec, _mesa_ValidateProgramARB); |
||
1884 | SET_GetObjectParameterfvARB(exec, _mesa_GetObjectParameterfvARB); |
||
1885 | SET_GetObjectParameterivARB(exec, _mesa_GetObjectParameterivARB); |
||
1886 | SET_GetInfoLogARB(exec, _mesa_GetInfoLogARB); |
||
1887 | SET_GetAttachedObjectsARB(exec, _mesa_GetAttachedObjectsARB); |
||
1888 | SET_GetShaderSourceARB(exec, _mesa_GetShaderSourceARB); |
||
1889 | |||
1890 | /* OpenGL 2.0 */ |
||
1891 | SET_AttachShader(exec, _mesa_AttachShader); |
||
1892 | SET_CreateProgram(exec, _mesa_CreateProgram); |
||
1893 | SET_CreateShader(exec, _mesa_CreateShader); |
||
1894 | SET_DeleteProgram(exec, _mesa_DeleteProgram); |
||
1895 | SET_DeleteShader(exec, _mesa_DeleteShader); |
||
1896 | SET_DetachShader(exec, _mesa_DetachShader); |
||
1897 | SET_GetAttachedShaders(exec, _mesa_GetAttachedShaders); |
||
1898 | SET_GetProgramiv(exec, _mesa_GetProgramiv); |
||
1899 | SET_GetProgramInfoLog(exec, _mesa_GetProgramInfoLog); |
||
1900 | SET_GetShaderiv(exec, _mesa_GetShaderiv); |
||
1901 | SET_GetShaderInfoLog(exec, _mesa_GetShaderInfoLog); |
||
1902 | SET_IsProgram(exec, _mesa_IsProgram); |
||
1903 | SET_IsShader(exec, _mesa_IsShader); |
||
1904 | |||
1905 | #if FEATURE_ARB_vertex_shader |
||
1906 | SET_BindAttribLocationARB(exec, _mesa_BindAttribLocationARB); |
||
1907 | SET_GetActiveAttribARB(exec, _mesa_GetActiveAttribARB); |
||
1908 | SET_GetAttribLocationARB(exec, _mesa_GetAttribLocationARB); |
||
1909 | #endif |
||
1910 | |||
1911 | #if FEATURE_ARB_geometry_shader4 |
||
1912 | SET_ProgramParameteriARB(exec, _mesa_ProgramParameteriARB); |
||
1913 | #endif |
||
1914 | |||
1915 | SET_UseShaderProgramEXT(exec, _mesa_UseShaderProgramEXT); |
||
1916 | SET_ActiveProgramEXT(exec, _mesa_ActiveProgramEXT); |
||
1917 | SET_CreateShaderProgramEXT(exec, _mesa_CreateShaderProgramEXT); |
||
1918 | |||
1919 | /* GL_EXT_gpu_shader4 / GL 3.0 */ |
||
1920 | SET_BindFragDataLocationEXT(exec, _mesa_BindFragDataLocation); |
||
1921 | SET_GetFragDataLocationEXT(exec, _mesa_GetFragDataLocation); |
||
1922 | |||
1923 | /* GL_ARB_ES2_compatibility */ |
||
1924 | SET_ReleaseShaderCompiler(exec, _mesa_ReleaseShaderCompiler); |
||
1925 | SET_GetShaderPrecisionFormat(exec, _mesa_GetShaderPrecisionFormat); |
||
1926 | |||
1927 | #endif /* FEATURE_GL */ |
||
1928 | }>>>>><>>>>>>>>>>>>>>>> |
||
1929 |