Fix calling new entrypoints from within glBegin()/glEnd().

macos/v1.5.9
Eric Anholt 11 years ago
parent 9ffa5d25c4
commit 0983996e49
  1. 107
      src/dispatch_common.c
  2. 5
      src/dispatch_common.h
  3. 23
      src/gen_dispatch.py
  4. 2
      test/Makefile.am

@ -117,6 +117,20 @@ struct api {
/** dlopen() return value for libGLESv2.so.2 */ /** dlopen() return value for libGLESv2.so.2 */
void *gles2_handle; void *gles2_handle;
/**
* This value gets incremented when any thread is in
* glBegin()/glEnd() called through epoxy.
*
* We're not guaranteed to be called through our wrapper, so the
* conservative paths also try to handle the failure cases they'll
* see if begin_count didn't reflect reality. It's also a bit of
* a bug that the conservative paths might return success because
* some other thread was in epoxy glBegin/glEnd while our thread
* is trying to resolve, but given that it's basically just for
* informative error messages, we shouldn't need to care.
*/
int begin_count;
}; };
static struct api api = { static struct api api = {
@ -159,18 +173,34 @@ PUBLIC bool
epoxy_is_desktop_gl(void) epoxy_is_desktop_gl(void)
{ {
const char *es_prefix = "OpenGL ES "; const char *es_prefix = "OpenGL ES ";
const char *version = (const char *)glGetString(GL_VERSION); const char *version;
if (api.begin_count)
return true;
version = (const char *)glGetString(GL_VERSION);
/* If we didn't get a version back, there are only two things that
* could have happened: either malloc failure (which basically
* doesn't exist), or we were called within a glBegin()/glEnd().
* Assume the second, which only exists for desktop GL.
*/
if (!version)
return true;
return strncmp(es_prefix, version, strlen(es_prefix)); return strncmp(es_prefix, version, strlen(es_prefix));
} }
PUBLIC int static int
epoxy_gl_version(void) epoxy_internal_gl_version(int error_version)
{ {
const char *version = (const char *)glGetString(GL_VERSION); const char *version = (const char *)glGetString(GL_VERSION);
GLint major, minor; GLint major, minor;
int scanf_count; int scanf_count;
if (!version)
return error_version;
/* skip to version number */ /* skip to version number */
while (!isdigit(*version) && *version != '\0') while (!isdigit(*version) && *version != '\0')
version++; version++;
@ -185,6 +215,21 @@ epoxy_gl_version(void)
return 10 * major + minor; return 10 * major + minor;
} }
PUBLIC int
epoxy_gl_version(void)
{
return epoxy_internal_gl_version(0);
}
PUBLIC int
epoxy_conservative_gl_version(void)
{
if (api.begin_count)
return 100;
return epoxy_internal_gl_version(100);
}
/** /**
* If we can determine the GLX version from the current context, then * If we can determine the GLX version from the current context, then
* return that, otherwise return a version that will just send us on * return that, otherwise return a version that will just send us on
@ -268,16 +313,21 @@ epoxy_extension_in_string(const char *extension_list, const char *ext)
return ptr != NULL; return ptr != NULL;
} }
PUBLIC bool static bool
epoxy_has_gl_extension(const char *ext) epoxy_internal_has_gl_extension(const char *ext, bool invalid_op_mode)
{ {
if (epoxy_gl_version() < 30) { if (epoxy_gl_version() < 30) {
return epoxy_extension_in_string((const char *)glGetString(GL_EXTENSIONS), const char *exts = (const char *)glGetString(GL_EXTENSIONS);
ext); if (!exts)
return invalid_op_mode;
return epoxy_extension_in_string(exts, ext);
} else { } else {
int num_extensions; int num_extensions;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
if (num_extensions == 0)
return invalid_op_mode;
for (int i = 0; i < num_extensions; i++) { for (int i = 0; i < num_extensions; i++) {
const char *gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i); const char *gl_ext = (const char *)glGetStringi(GL_EXTENSIONS, i);
if (strcmp(ext, gl_ext) == 0) if (strcmp(ext, gl_ext) == 0)
@ -288,6 +338,29 @@ epoxy_has_gl_extension(const char *ext)
} }
} }
/**
* Returns true if the given GL extension is supported in the current context.
*
* Note that this function can't be called from within glBegin()/glEnd().
*
* \sa epoxy_has_egl_extension()
* \sa epoxy_has_glx_extension()
*/
PUBLIC bool
epoxy_has_gl_extension(const char *ext)
{
return epoxy_internal_has_gl_extension(ext, false);
}
bool
epoxy_conservative_has_gl_extension(const char *ext)
{
if (api.begin_count)
return true;
return epoxy_internal_has_gl_extension(ext, true);
}
bool bool
epoxy_conservative_has_egl_extension(const char *ext) epoxy_conservative_has_egl_extension(const char *ext)
{ {
@ -424,3 +497,23 @@ epoxy_print_failure_reasons(const char *name,
for (i = 0; providers[i] != 0; i++) for (i = 0; providers[i] != 0; i++)
puts(provider_names[providers[i]]); puts(provider_names[providers[i]]);
} }
PUBLIC void
epoxy_glBegin(GLenum primtype)
{
pthread_mutex_lock(&api.mutex);
api.begin_count++;
pthread_mutex_unlock(&api.mutex);
epoxy_glBegin_unwrapped(primtype);
}
PUBLIC void
epoxy_glEnd(void)
{
epoxy_glEnd_unwrapped();
pthread_mutex_lock(&api.mutex);
api.begin_count--;
pthread_mutex_unlock(&api.mutex);
}

@ -41,6 +41,8 @@ void *epoxy_gles1_dlsym(const char *name);
void *epoxy_gles2_dlsym(const char *name); void *epoxy_gles2_dlsym(const char *name);
void *epoxy_get_proc_address(const char *name); void *epoxy_get_proc_address(const char *name);
int epoxy_conservative_gl_version(void);
bool epoxy_conservative_has_gl_extension(const char *name);
int epoxy_conservative_glx_version(void); int epoxy_conservative_glx_version(void);
bool epoxy_conservative_has_glx_extension(const char *name); bool epoxy_conservative_has_glx_extension(const char *name);
int epoxy_conservative_egl_version(void); int epoxy_conservative_egl_version(void);
@ -48,3 +50,6 @@ bool epoxy_conservative_has_egl_extension(const char *name);
void epoxy_print_failure_reasons(const char *name, void epoxy_print_failure_reasons(const char *name,
const char **provider_names, const char **provider_names,
const int *providers); const int *providers);
void epoxy_glBegin_unwrapped(GLenum primtype);
void epoxy_glEnd_unwrapped(void);

@ -130,6 +130,14 @@ class Generator(object):
# provided the name of the symbol to be requested. # provided the name of the symbol to be requested.
self.provider_loader = {} self.provider_loader = {}
# These are functions with hand-written wrapper code in
# dispatch_common.c. Their dispatch stubs will be replaced
# with non-public symbols with a "_unwrapped" suffix.
self.wrapped_functions = {
'glBegin',
'glEnd'
}
def all_text_until_element_name(self, element, element_name): def all_text_until_element_name(self, element, element_name):
text = '' text = ''
@ -265,7 +273,7 @@ class Generator(object):
loader = 'epoxy_gl_dlsym({0})' loader = 'epoxy_gl_dlsym({0})'
else: else:
loader = 'epoxy_get_proc_address({0})' loader = 'epoxy_get_proc_address({0})'
condition += ' && epoxy_gl_version() >= {0}'.format(version) condition += ' && epoxy_conservative_gl_version() >= {0}'.format(version)
elif api == 'gles2': elif api == 'gles2':
human_name = 'OpenGL ES {0}'.format(feature.get('number')) human_name = 'OpenGL ES {0}'.format(feature.get('number'))
condition = '!epoxy_is_desktop_gl() && epoxy_gl_version() >= {0}'.format(version) condition = '!epoxy_is_desktop_gl() && epoxy_gl_version() >= {0}'.format(version)
@ -319,7 +327,7 @@ class Generator(object):
self.process_require_statements(extension, condition, loader, human_name) self.process_require_statements(extension, condition, loader, human_name)
if 'gl' in apis: if 'gl' in apis:
human_name = 'GL extension \\"{0}\\"'.format(extname) human_name = 'GL extension \\"{0}\\"'.format(extname)
condition = 'epoxy_has_gl_extension("{0}")'.format(extname) condition = 'epoxy_conservative_has_gl_extension("{0}")'.format(extname)
loader = 'epoxy_get_proc_address({0})' loader = 'epoxy_get_proc_address({0})'
self.process_require_statements(extension, condition, loader, human_name) self.process_require_statements(extension, condition, loader, human_name)
@ -460,8 +468,15 @@ class Generator(object):
dispatch_table_entry = 'dispatch_table->p{0}'.format(alias_name) dispatch_table_entry = 'dispatch_table->p{0}'.format(alias_name)
self.outln('PUBLIC {0}'.format(func.ret_type)) if func.name in self.wrapped_functions:
self.outln('epoxy_{0}({1})'.format(func.name, func.args_decl)) function_name = func.name + '_unwrapped'
public = ''
else:
function_name = func.name
public = 'PUBLIC '
self.outln('{0}{1}'.format(public, func.ret_type))
self.outln('epoxy_{0}({1})'.format(function_name, func.args_decl))
self.outln('{') self.outln('{')
self.outln(' if (!{0})'.format(dispatch_table_entry)) self.outln(' if (!{0})'.format(dispatch_table_entry))
self.outln(' {0} = epoxy_{1}_resolver();'.format(dispatch_table_entry, self.outln(' {0} = epoxy_{1}_resolver();'.format(dispatch_table_entry,

@ -49,8 +49,6 @@ TESTS = \
headerguards \ headerguards \
$() $()
XFAIL_TESTS = glx_beginend
check_PROGRAMS = $(TESTS) check_PROGRAMS = $(TESTS)
egl_has_extension_nocontext_LDFLAGS = $(X11_LIBS) $(EPOXY) libegl_common.la egl_has_extension_nocontext_LDFLAGS = $(X11_LIBS) $(EPOXY) libegl_common.la

Loading…
Cancel
Save