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