Mesa (master): mesa: make error handling for glGetActiveUniform glthread-safe
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Sat Nov 21 21:21:13 UTC 2020
Module: Mesa
Branch: master
Commit: 5f820b38d41a3bea956fd79ec6930fea860b50d9
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=5f820b38d41a3bea956fd79ec6930fea860b50d9
Author: Marek Olšák <marek.olsak at amd.com>
Date: Sat Oct 3 16:03:07 2020 -0400
mesa: make error handling for glGetActiveUniform glthread-safe
glGetActiveUniform will be called from the app thread directly.
This is safe if a few conditions are met.
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7053>
---
src/mesa/main/glthread.c | 21 +++++++++++++++++++
src/mesa/main/glthread.h | 10 +++++++++
src/mesa/main/program_resource.c | 3 ++-
src/mesa/main/shader_query.cpp | 43 ++++++++++++++++++++++----------------
src/mesa/main/shaderapi.c | 4 ++--
src/mesa/main/shaderapi.h | 6 ++++--
src/mesa/main/shaderobj.c | 20 +++++++++++++-----
src/mesa/main/shaderobj.h | 4 ++++
src/mesa/main/transformfeedback.c | 4 ++--
src/mesa/main/uniform_query.cpp | 44 +++++++++++++++++++++++++++++----------
src/mesa/main/uniforms.c | 27 ++++++++++++------------
src/mesa/main/uniforms.h | 4 ++++
12 files changed, 136 insertions(+), 54 deletions(-)
diff --git a/src/mesa/main/glthread.c b/src/mesa/main/glthread.c
index eb8eb30cabc..0c0895b27b7 100644
--- a/src/mesa/main/glthread.c
+++ b/src/mesa/main/glthread.c
@@ -293,3 +293,24 @@ _mesa_glthread_finish_before(struct gl_context *ctx, const char *func)
/* Uncomment this if you want to know where glthread syncs. */
/*printf("fallback to sync: %s\n", func);*/
}
+
+void
+_mesa_error_glthread_safe(struct gl_context *ctx, GLenum error, bool glthread,
+ const char *format, ...)
+{
+ if (glthread) {
+ _mesa_marshal_InternalSetError(error);
+ } else {
+ char s[MAX_DEBUG_MESSAGE_LENGTH];
+ va_list args;
+
+ va_start(args, format);
+ ASSERTED size_t len = vsnprintf(s, MAX_DEBUG_MESSAGE_LENGTH, format, args);
+ va_end(args);
+
+ /* Whoever calls _mesa_error should use shorter strings. */
+ assert(len < MAX_DEBUG_MESSAGE_LENGTH);
+
+ _mesa_error(ctx, error, "%s", s);
+ }
+}
diff --git a/src/mesa/main/glthread.h b/src/mesa/main/glthread.h
index 8a98a151b3a..0f489fb7638 100644
--- a/src/mesa/main/glthread.h
+++ b/src/mesa/main/glthread.h
@@ -53,6 +53,10 @@
#include "compiler/shader_enums.h"
#include "main/config.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
struct gl_context;
struct gl_buffer_object;
struct _mesa_HashTable;
@@ -193,6 +197,8 @@ void _mesa_glthread_upload(struct gl_context *ctx, const void *data,
struct gl_buffer_object **out_buffer,
uint8_t **out_ptr);
void _mesa_glthread_reset_vao(struct glthread_vao *vao);
+void _mesa_error_glthread_safe(struct gl_context *ctx, GLenum error,
+ bool glthread, const char *format, ...);
void _mesa_glthread_BindBuffer(struct gl_context *ctx, GLenum target,
GLuint buffer);
@@ -250,4 +256,8 @@ void _mesa_glthread_ClientAttribDefault(struct gl_context *ctx, GLbitfield mask)
void _mesa_glthread_InterleavedArrays(struct gl_context *ctx, GLenum format,
GLsizei stride, const GLvoid *pointer);
+#ifdef __cplusplus
+}
+#endif
+
#endif /* _GLTHREAD_H*/
diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c
index c85988d21ff..fda59c561b3 100644
--- a/src/mesa/main/program_resource.c
+++ b/src/mesa/main/program_resource.c
@@ -360,7 +360,8 @@ _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
}
_mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
- length, name, "glGetProgramResourceName");
+ length, name, false,
+ "glGetProgramResourceName");
}
void GLAPIENTRY
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp
index 9a16a28d393..99c23bae976 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -166,11 +166,11 @@ _mesa_GetActiveAttrib(GLuint program, GLuint desired_index,
if (size)
_mesa_program_resource_prop(shProg, res, desired_index, GL_ARRAY_SIZE,
- size, "glGetActiveAttrib");
+ size, false, "glGetActiveAttrib");
if (type)
_mesa_program_resource_prop(shProg, res, desired_index, GL_TYPE,
- (GLint *) type, "glGetActiveAttrib");
+ (GLint *) type, false, "glGetActiveAttrib");
}
GLint GLAPIENTRY
@@ -967,7 +967,8 @@ bool
_mesa_get_program_resource_name(struct gl_shader_program *shProg,
GLenum programInterface, GLuint index,
GLsizei bufSize, GLsizei *length,
- GLchar *name, const char *caller)
+ GLchar *name, bool glthread,
+ const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
@@ -980,12 +981,14 @@ _mesa_get_program_resource_name(struct gl_shader_program *shProg,
* <programInterface>.
*/
if (!res) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
+ _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
+ "%s(index %u)", caller, index);
return false;
}
if (bufSize < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
+ _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
+ "%s(bufSize %d)", caller, bufSize);
return false;
}
@@ -1188,7 +1191,7 @@ is_resource_referenced(struct gl_shader_program *shProg,
static unsigned
get_buffer_property(struct gl_shader_program *shProg,
struct gl_program_resource *res, const GLenum prop,
- GLint *val, const char *caller)
+ GLint *val, bool glthread, const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
if (res->Type != GL_UNIFORM_BLOCK &&
@@ -1335,9 +1338,10 @@ get_buffer_property(struct gl_shader_program *shProg,
assert(!"support for property type not implemented");
invalid_operation:
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
- _mesa_enum_to_string(res->Type),
- _mesa_enum_to_string(prop));
+ _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
+ "%s(%s prop %s)", caller,
+ _mesa_enum_to_string(res->Type),
+ _mesa_enum_to_string(prop));
return 0;
}
@@ -1345,7 +1349,8 @@ invalid_operation:
unsigned
_mesa_program_resource_prop(struct gl_shader_program *shProg,
struct gl_program_resource *res, GLuint index,
- const GLenum prop, GLint *val, const char *caller)
+ const GLenum prop, GLint *val, bool glthread,
+ const char *caller)
{
GET_CURRENT_CONTEXT(ctx);
@@ -1450,7 +1455,7 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
case GL_BUFFER_DATA_SIZE:
case GL_NUM_ACTIVE_VARIABLES:
case GL_ACTIVE_VARIABLES:
- return get_buffer_property(shProg, res, prop, val, caller);
+ return get_buffer_property(shProg, res, prop, val, glthread, caller);
case GL_REFERENCED_BY_COMPUTE_SHADER:
if (!_mesa_has_compute_shaders(ctx))
goto invalid_enum;
@@ -1587,15 +1592,17 @@ _mesa_program_resource_prop(struct gl_shader_program *shProg,
#undef VALIDATE_TYPE_2
invalid_enum:
- _mesa_error(ctx, GL_INVALID_ENUM, "%s(%s prop %s)", caller,
- _mesa_enum_to_string(res->Type),
- _mesa_enum_to_string(prop));
+ _mesa_error_glthread_safe(ctx, GL_INVALID_ENUM, glthread,
+ "%s(%s prop %s)", caller,
+ _mesa_enum_to_string(res->Type),
+ _mesa_enum_to_string(prop));
return 0;
invalid_operation:
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s prop %s)", caller,
- _mesa_enum_to_string(res->Type),
- _mesa_enum_to_string(prop));
+ _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
+ "%s(%s prop %s)", caller,
+ _mesa_enum_to_string(res->Type),
+ _mesa_enum_to_string(prop));
return 0;
}
@@ -1625,7 +1632,7 @@ _mesa_get_program_resourceiv(struct gl_shader_program *shProg,
for (int i = 0; i < propCount && i < bufSize; i++, val++, prop++) {
int props_written =
_mesa_program_resource_prop(shProg, res, index, *prop, val,
- "glGetProgramResourceiv");
+ false, "glGetProgramResourceiv");
/* Error happened. */
if (props_written == 0)
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 6c6c1e25c57..dd0900d8b34 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -2936,7 +2936,7 @@ _mesa_GetActiveSubroutineUniformName(GLuint program, GLenum shadertype,
/* get program resource name */
_mesa_get_program_resource_name(shProg, resource_type,
index, bufsize,
- length, name, api_name);
+ length, name, false, api_name);
}
@@ -2968,7 +2968,7 @@ _mesa_GetActiveSubroutineName(GLuint program, GLenum shadertype,
resource_type = _mesa_shader_stage_to_subroutine(stage);
_mesa_get_program_resource_name(shProg, resource_type,
index, bufsize,
- length, name, api_name);
+ length, name, false, api_name);
}
GLvoid GLAPIENTRY
diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index bba737868ef..10ef268f8fd 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -307,7 +307,8 @@ extern bool
_mesa_get_program_resource_name(struct gl_shader_program *shProg,
GLenum programInterface, GLuint index,
GLsizei bufSize, GLsizei *length,
- GLchar *name, const char *caller);
+ GLchar *name, bool glthread,
+ const char *caller);
extern unsigned
_mesa_program_resource_name_len(struct gl_program_resource *res);
@@ -323,7 +324,8 @@ _mesa_program_resource_location_index(struct gl_shader_program *shProg,
extern unsigned
_mesa_program_resource_prop(struct gl_shader_program *shProg,
struct gl_program_resource *res, GLuint index,
- const GLenum prop, GLint *val, const char *caller);
+ const GLenum prop, GLint *val, bool glthread,
+ const char *caller);
extern void
_mesa_get_program_resourceiv(struct gl_shader_program *shProg,
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 9a4225d608a..ded74d1ec45 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -443,22 +443,24 @@ _mesa_lookup_shader_program(struct gl_context *ctx, GLuint name)
* As above, but record an error if program is not found.
*/
struct gl_shader_program *
-_mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
- const char *caller)
+_mesa_lookup_shader_program_err_glthread(struct gl_context *ctx, GLuint name,
+ bool glthread, const char *caller)
{
if (!name) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
+ _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread, "%s", caller);
return NULL;
}
else {
struct gl_shader_program *shProg = (struct gl_shader_program *)
_mesa_HashLookup(ctx->Shared->ShaderObjects, name);
if (!shProg) {
- _mesa_error(ctx, GL_INVALID_VALUE, "%s", caller);
+ _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
+ "%s", caller);
return NULL;
}
if (shProg->Type != GL_SHADER_PROGRAM_MESA) {
- _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller);
+ _mesa_error_glthread_safe(ctx, GL_INVALID_OPERATION, glthread,
+ "%s", caller);
return NULL;
}
return shProg;
@@ -466,6 +468,14 @@ _mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
}
+struct gl_shader_program *
+_mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
+ const char *caller)
+{
+ return _mesa_lookup_shader_program_err_glthread(ctx, name, false, caller);
+}
+
+
void
_mesa_init_shader_object_functions(struct dd_function_table *driver)
{
diff --git a/src/mesa/main/shaderobj.h b/src/mesa/main/shaderobj.h
index bb1b300e87c..8c9cb8bc921 100644
--- a/src/mesa/main/shaderobj.h
+++ b/src/mesa/main/shaderobj.h
@@ -97,6 +97,10 @@ _mesa_delete_linked_shader(struct gl_context *ctx,
extern struct gl_shader_program *
_mesa_lookup_shader_program(struct gl_context *ctx, GLuint name);
+extern struct gl_shader_program *
+_mesa_lookup_shader_program_err_glthread(struct gl_context *ctx, GLuint name,
+ bool glthread, const char *caller);
+
extern struct gl_shader_program *
_mesa_lookup_shader_program_err(struct gl_context *ctx, GLuint name,
const char *caller);
diff --git a/src/mesa/main/transformfeedback.c b/src/mesa/main/transformfeedback.c
index 696e07cdbe3..47494177cf4 100644
--- a/src/mesa/main/transformfeedback.c
+++ b/src/mesa/main/transformfeedback.c
@@ -1026,11 +1026,11 @@ _mesa_GetTransformFeedbackVarying(GLuint program, GLuint index,
if (type)
_mesa_program_resource_prop((struct gl_shader_program *) shProg,
res, index, GL_TYPE, (GLint*) type,
- "glGetTransformFeedbackVarying");
+ false, "glGetTransformFeedbackVarying");
if (size)
_mesa_program_resource_prop((struct gl_shader_program *) shProg,
res, index, GL_ARRAY_SIZE, (GLint*) size,
- "glGetTransformFeedbackVarying");
+ false, "glGetTransformFeedbackVarying");
}
diff --git a/src/mesa/main/uniform_query.cpp b/src/mesa/main/uniform_query.cpp
index 2b1fc8668f4..9be7e048a76 100644
--- a/src/mesa/main/uniform_query.cpp
+++ b/src/mesa/main/uniform_query.cpp
@@ -39,21 +39,32 @@
#include "util/bitscan.h"
-extern "C" void GLAPIENTRY
-_mesa_GetActiveUniform(GLuint program, GLuint index,
- GLsizei maxLength, GLsizei *length, GLint *size,
- GLenum *type, GLcharARB *nameOut)
+/* This is one of the few glGet that can be called from the app thread safely.
+ * Only these conditions must be met:
+ * - There are no unfinished glLinkProgram and glDeleteProgram calls
+ * for the program object. This assures that the program object is immutable.
+ * - glthread=true for GL errors to be passed to the driver thread safely
+ *
+ * Program objects can be looked up from any thread because they are part
+ * of the multi-context shared state.
+ */
+extern "C" void
+_mesa_GetActiveUniform_impl(GLuint program, GLuint index,
+ GLsizei maxLength, GLsizei *length, GLint *size,
+ GLenum *type, GLcharARB *nameOut, bool glthread)
{
GET_CURRENT_CONTEXT(ctx);
struct gl_shader_program *shProg;
struct gl_program_resource *res;
if (maxLength < 0) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(maxLength < 0)");
+ _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
+ "glGetActiveUniform(maxLength < 0)");
return;
}
- shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniform");
+ shProg = _mesa_lookup_shader_program_err_glthread(ctx, program, glthread,
+ "glGetActiveUniform");
if (!shProg)
return;
@@ -61,21 +72,32 @@ _mesa_GetActiveUniform(GLuint program, GLuint index,
GL_UNIFORM, index);
if (!res) {
- _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
+ _mesa_error_glthread_safe(ctx, GL_INVALID_VALUE, glthread,
+ "glGetActiveUniform(index)");
return;
}
if (nameOut)
_mesa_get_program_resource_name(shProg, GL_UNIFORM, index, maxLength,
- length, nameOut, "glGetActiveUniform");
+ length, nameOut, glthread,
+ "glGetActiveUniform");
if (type)
_mesa_program_resource_prop((struct gl_shader_program *) shProg,
res, index, GL_TYPE, (GLint*) type,
- "glGetActiveUniform");
+ glthread, "glGetActiveUniform");
if (size)
_mesa_program_resource_prop((struct gl_shader_program *) shProg,
res, index, GL_ARRAY_SIZE, (GLint*) size,
- "glGetActiveUniform");
+ glthread, "glGetActiveUniform");
+}
+
+extern "C" void GLAPIENTRY
+_mesa_GetActiveUniform(GLuint program, GLuint index,
+ GLsizei maxLength, GLsizei *length, GLint *size,
+ GLenum *type, GLcharARB *nameOut)
+{
+ _mesa_GetActiveUniform_impl(program, index, maxLength, length, size,
+ type, nameOut, false);
}
static GLenum
@@ -151,7 +173,7 @@ _mesa_GetActiveUniformsiv(GLuint program,
uniformIndices[i]);
if (!_mesa_program_resource_prop(shProg, res, uniformIndices[i],
res_prop, ¶ms[i],
- "glGetActiveUniformsiv"))
+ false, "glGetActiveUniformsiv"))
break;
}
}
diff --git a/src/mesa/main/uniforms.c b/src/mesa/main/uniforms.c
index ba87d3900af..277e914b1d6 100644
--- a/src/mesa/main/uniforms.c
+++ b/src/mesa/main/uniforms.c
@@ -1240,65 +1240,65 @@ mesa_bufferiv(struct gl_shader_program *shProg, GLenum type,
case GL_UNIFORM_BLOCK_BINDING:
case GL_ATOMIC_COUNTER_BUFFER_BINDING:
_mesa_program_resource_prop(shProg, res, index, GL_BUFFER_BINDING,
- params, caller);
+ params, false, caller);
return;
case GL_UNIFORM_BLOCK_DATA_SIZE:
case GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE:
_mesa_program_resource_prop(shProg, res, index, GL_BUFFER_DATA_SIZE,
- params, caller);
+ params, false, caller);
return;
case GL_UNIFORM_BLOCK_NAME_LENGTH:
_mesa_program_resource_prop(shProg, res, index, GL_NAME_LENGTH,
- params, caller);
+ params, false, caller);
return;
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS:
_mesa_program_resource_prop(shProg, res, index, GL_NUM_ACTIVE_VARIABLES,
- params, caller);
+ params, false, caller);
return;
case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
case GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES:
_mesa_program_resource_prop(shProg, res, index, GL_ACTIVE_VARIABLES,
- params, caller);
+ params, false, caller);
return;
case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER:
_mesa_program_resource_prop(shProg, res, index,
GL_REFERENCED_BY_VERTEX_SHADER, params,
- caller);
+ false, caller);
return;
case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER:
case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER:
_mesa_program_resource_prop(shProg, res, index,
GL_REFERENCED_BY_TESS_CONTROL_SHADER, params,
- caller);
+ false, caller);
return;
case GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER:
case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER:
_mesa_program_resource_prop(shProg, res, index,
GL_REFERENCED_BY_TESS_EVALUATION_SHADER, params,
- caller);
+ false, caller);
return;
case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER:
_mesa_program_resource_prop(shProg, res, index,
GL_REFERENCED_BY_GEOMETRY_SHADER, params,
- caller);
+ false, caller);
return;
case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER:
_mesa_program_resource_prop(shProg, res, index,
GL_REFERENCED_BY_FRAGMENT_SHADER, params,
- caller);
+ false, caller);
return;
case GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER:
case GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER:
_mesa_program_resource_prop(shProg, res, index,
GL_REFERENCED_BY_COMPUTE_SHADER, params,
- caller);
+ false, caller);
return;
default:
_mesa_error(ctx, GL_INVALID_ENUM,
@@ -1362,7 +1362,7 @@ _mesa_GetActiveUniformBlockName(GLuint program,
if (uniformBlockName)
_mesa_get_program_resource_name(shProg, GL_UNIFORM_BLOCK,
uniformBlockIndex, bufSize, length,
- uniformBlockName,
+ uniformBlockName, false,
"glGetActiveUniformBlockName");
}
@@ -1392,7 +1392,8 @@ _mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
return;
_mesa_get_program_resource_name(shProg, GL_UNIFORM, uniformIndex, bufSize,
- length, uniformName, "glGetActiveUniformName");
+ length, uniformName, false,
+ "glGetActiveUniformName");
}
void GLAPIENTRY
diff --git a/src/mesa/main/uniforms.h b/src/mesa/main/uniforms.h
index 819cf90ba41..70d13b82577 100644
--- a/src/mesa/main/uniforms.h
+++ b/src/mesa/main/uniforms.h
@@ -271,6 +271,10 @@ void GLAPIENTRY
_mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
GLsizei bufSize, GLsizei *length,
GLchar *uniformName);
+void
+_mesa_GetActiveUniform_impl(GLuint, GLuint, GLsizei, GLsizei *,
+ GLint *, GLenum *, GLcharARB *,
+ bool glthread);
void GLAPIENTRY
_mesa_GetActiveUniform(GLuint, GLuint, GLsizei, GLsizei *,
GLint *, GLenum *, GLcharARB *);
More information about the mesa-commit
mailing list