Re-implement libGL such that ELF symbol filtering is optional

Unfortunately, glibc has a bug where dlopening a shared library with
DT_FILTER or DT_AUXILIARY ELF headers can cause the application to
segfault (see https://sourceware.org/bugzilla/show_bug.cgi?id=16272).
Hence, for now, we can't rely on ELF symbol filtering to implement the
libGL compatibility library for libGLdispatch and libGLX.  This change
re-implements libGL such that this is no longer necessary, by building
in the glapi static dispatch stubs and implementing thin wrapper
functions around GLX entrypoints.

- Rename getCachedProcAddress() to __glXGetCachedProcAddress() and give
  this public visibility.  This is used by the libGL wrapper library to
  retrieve GLX entrypoints at load time.

- Link libGLX with the -Bsymbolic flag so __glXGetCachedProcAddress()
  avoids referencing functions in the libGL wrapper library when libGL
  and libGLX are both loaded.

- Replace the hand-coded no-op definitions in libglxnoopdefs.h with
  a spec file, glx_funcs.spec, and a simple Perl script, gen_stubs.pl,
  which parses the file and generates no-op functions as well as
  pass-through functions that are used by libGL.

- Restructure GLdispatch/vnd-glapi/mapi/entry.c such that the pure C
  fallback code is in its own header, entry_pure_c.h.  In each of the
  entry_*.h headers, separate code not related to implementing the
  static dispatch stubs into an "#if !defined(STATIC_DISPATCH_ONLY)"
  block.

- Give u_current (which is #defined as _glapi_Current or
  _glapi_tls_Current depending on the thread storage model used) public
  visibility so it can be referenced from outside of libGLdispatch.so.

- When building libGL, include GLdispatch/vnd-glapi/mapi/entry.c in the
  sources, and define STATIC_DISPATCH_ONLY so that only the static
  entrypoints are compiled.  Remove the -Wl,--auxiliary flags from
  Makefile.am.

Bonus: fix "make distcheck" by adding GLdispatchABI.h to noinst_HEADERS.

Signed-off-by: Brian Nguyen <brnguyen@nvidia.com>
This commit is contained in:
Brian Nguyen 2013-12-03 12:06:47 -08:00 committed by brnguyen
parent 39d839d14f
commit 09126a72d5
18 changed files with 790 additions and 436 deletions

View file

@ -26,6 +26,7 @@ AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
AC_CHECK_PROGS([PYTHON2], [python2 python])
AC_CHECK_PROGS([PERL], [perl])
dnl
dnl Arch/platform-specific settings. Copied from mesa

View file

@ -27,23 +27,48 @@
lib_LTLIBRARIES = libGL.la
libGL_la_SOURCES = \
GL.c \
glapitemp.h
TOP = $(top_srcdir)
MAPI = $(top_srcdir)/$(MAPI_PREFIX)
GLAPI = $(MAPI)/glapi
BUILT_SOURCES = glapitemp.h
noinst_HEADERS = \
glapitemp.h \
libgl.h \
glapi_mapi_tmp.h
libGL_la_SOURCES = \
libgl.c \
$(MAPI)/entry.c \
g_libglglxwrapper.c
BUILT_SOURCES = glapitemp.h glapi_mapi_tmp.h g_libglglxwrapper.c
CLEANFILES = $(BUILT_SOURCES)
TOP = $(top_srcdir)
GLAPI = $(top_srcdir)/$(MAPI_PREFIX)/glapi
include $(GLAPI)/gen/glapi_gen.mk
glapi_mapi_tmp.h : $(GLAPI)/gen/gl_and_es_API.xml $(glapi_gen_mapi_deps)
$(call glapi_gen_mapi,$<,vnd-glapi)
glapitemp.h : $(GLAPI)/gen/gl_and_es_API.xml $(glapi_gen_mapi_deps)
$(call glapi_gen_mapi,$<,noop-gl)
GLX_GEN_STUBS = $(top_srcdir)/src/GLX/gen_stubs.pl
GLX_FUNCS_SPEC = $(top_srcdir)/src/GLX/glx_funcs.spec
g_libglglxwrapper.c : $(GLX_GEN_STUBS) $(GLX_FUNCS_SPEC)
$(AM_V_GEN)$(PERL) $(GLX_GEN_STUBS) "glwrap" $(GLX_FUNCS_SPEC) > $@
libGL_la_CFLAGS = \
-I$(top_srcdir)/include
libGL_la_LDFLAGS = -shared -Wl,--auxiliary=libGLdispatch.so.0 -Wl,--auxiliary=libGLX.so.0 -version-info 1
libGL_la_LDFLAGS = -shared -version-info 1
libGL_la_LIBADD = ../GLX/libGLX.la ../GLdispatch/libGLdispatch.la
AM_CPPFLAGS = \
-I$(TOP)/src/GLdispatch/vnd-glapi/mapi \
-I$(TOP)/src/GLX \
-DMAPI_ABI_HEADER=\"$(builddir)/glapi_mapi_tmp.h\" \
-DSTATIC_DISPATCH_ONLY
libGL_la_LIBADD = ../GLX/libGLX.la
libGL_la_LIBADD += ../GLdispatch/libGLdispatch.la
libGL_la_LIBADD += -ldl

View file

@ -27,16 +27,19 @@
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include <dlfcn.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include "libgl.h"
#include "compiler.h"
#include "entry.h"
// Define GLX functions
#define GLXNOOP PUBLIC
#define NOOP_FUNC(func) glX ## func
#include "../GLX/libglxnoopdefs.h"
// Initialize GLX imports
void __attribute__((constructor)) __libGLInit(void)
{
// Fix up the static GL entrypoints, if necessary
entry_patch_public();
// Define OpenGL core functions
#define noop_warn(...)
#define MAPI_TMP_NOOP_FUNCTIONS
#include "glapitemp.h"
// Lookup function pointers from libGLX for the GLX entrypoints
__glXWrapperInit(__glXGetCachedProcAddress);
}

10
src/GL/libgl.h Normal file
View file

@ -0,0 +1,10 @@
#ifndef __libgl_h__
#define __libgl_h__
#include "libglxgl.h"
typedef __GLXextFuncPtr (*__GLXGetCachedProcAddressPtr)(const GLubyte *);
extern void __glXWrapperInit(__GLXGetCachedProcAddressPtr pGetProcAddress);
#endif

View file

@ -31,7 +31,7 @@ noinst_HEADERS = \
libglxcurrent.h \
libglxmapping.h \
libglxnoop.h \
libglxnoopdefs.h \
libglxgl.h \
libglxthread.h
lib_LTLIBRARIES = libGLX.la
@ -65,9 +65,16 @@ libGLX_la_LIBADD += $(X11GLVND_DIR)/libx11glvnd_client.la
libGLX_la_LIBADD += $(TRACE_DIR)/libtrace.la
libGLX_la_LIBADD += $(GLVND_PTHREAD_DIR)/libglvnd_pthread.la
libGLX_la_LDFLAGS = -shared
libGLX_la_LDFLAGS = -shared -Wl,-Bsymbolic
BUILT_SOURCES = g_libglxnoop.c
EXTRA_DIST = gen_stubs.pl glx_funcs.spec
g_libglxnoop.c : gen_stubs.pl glx_funcs.spec
$(AM_V_GEN)$(PERL) gen_stubs.pl "noop" glx_funcs.spec > $@
libGLX_la_SOURCES = \
libglx.c \
libglxmapping.c \
libglxnoop.c
g_libglxnoop.c

277
src/GLX/gen_stubs.pl Normal file
View file

@ -0,0 +1,277 @@
#!/usr/bin/env perl
########################################################################
# Copyright (c) 2013, NVIDIA CORPORATION.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and/or associated documentation files (the
# "Materials"), to deal in the Materials without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Materials, and to
# permit persons to whom the Materials are furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# unaltered in all copies or substantial portions of the Materials.
# Any additions, deletions, or changes to the original source files
# must be clearly indicated in accompanying documentation.
#
# If only executable code is distributed, then the accompanying
# documentation must state that "this software is based in part on the
# work of the Khronos Group."
#
# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
########################################################################
########################################################################
#
# gen_stubs.pl
#
# This parses glx_funcs.spec and generates noop functions for libGLX.so, as
# well as wrapper functions for libGL.so.
#
########################################################################
use strict;
die "syntax: gen_stubs.pl <mode> <specfile>" if @ARGV < 2;
my $mode = @ARGV[0];
my $specfile = @ARGV[1];
my $q = "(?:\\S+|\"[^\"]*\"|\'[^\']*\')"; # Possibly quoted string
sub add_function
{
my $function = shift;
my $functions = shift;
if ($function->{'name'}) {
push @$functions, { %$function };
}
undef %$function;
}
sub unquote
{
my $tmp = shift;
if (!$tmp) {
return undef;
}
$tmp =~ s/^(?|([^'"]\S+)|"([^"]*)"|'([^']*)')$/\1/;
$tmp;
}
sub get_param
{
my $params = shift;
my $typepat = shift;
my $valpat = shift;
foreach my $param (@$params) {
if (@$param[0] =~ /$typepat/ and
@$param[1] =~ /$valpat/) {
return $param;
}
}
return undef;
}
sub parse_spec
{
my $linenum = 0;
my @functions = ();
my %function = ();
open (SPEC, $specfile) or die "can't open spec file!\n";
while (<SPEC>)
{
$linenum++;
s/^\s+//; # Trim leading whitespace
s/^\s+$//; # Trim trailing whitespace
next if m/^\s*$/; # Ignore blank lines
next if m/^\s*#/; # Ignore comment lines
if (/^function\s+(.+)$/) {
add_function(\%function, \@functions);
$function{'name'} = unquote($1);
@{$function{'params'}} = ();
$function{'prefix'} = "glX";
} elsif (/^returns\s+($q)\s+($q)$/) {
$function{'returns'} = unquote($1);
$function{'default_retval'} = unquote($2);
} elsif (/^param\s+($q)\s+($q)$/) {
push @{$function{'params'}}, [unquote($1), unquote($2)];
} elsif (/^glx14ep$/) {
$function{'glx14ep'} = 1;
} else {
die "Unknown keyword on nonempty line";
}
}
add_function(\%function, \@functions);
@functions;
}
sub print_disclaimer
{
print "/*\n";
print " * THIS FILE IS AUTOMATICALLY GENERATED BY gen_noop.pl\n";
print " * DO NOT EDIT!!\n";
print " */\n";
}
sub get_param_proto_list
{
my $function = shift;
my @params = map (@$_[0] . ' ' . @$_[1],
@{$function->{"params"}});
if (!(scalar @params)) {
"void";
} else {
join (", ", @params);
}
}
sub get_param_pass_list
{
my $function = shift;
my @params = map (@$_[1], @{$function->{"params"}});
join (", ", @params);
}
sub name_len {
my $function = shift;
length($function->{"name"});
}
sub print_noop_funcs {
my $functions = shift;
my $noop_defs = "";
my $fill_struct = "";
# Compute maximum name length for padding
my $max_len = name_len(@$functions[0]);
foreach my $function (@$functions) {
if (length(name_len($function) > $max_len)) {
$max_len = name_len($function);
}
}
foreach my $function (@$functions) {
my $name = $function->{"name"};
my $struct_field = lcfirst($name);
my $param_proto_list = get_param_proto_list($function);
my $param_pass_list = get_param_pass_list($function);
my $rettype = $function->{"returns"};
my $retval = $function->{"default_retval"};
$noop_defs .= "GLXNOOP $rettype __glX${name}Noop($param_proto_list)\n";
$noop_defs .= "{\n";
if ($rettype ne "void") {
$noop_defs .= " return $retval;\n";
} else {
$noop_defs .= " return;\n";
}
$noop_defs .= "}\n";
$noop_defs .= "\n";
if ($function->{"glx14ep"}) {
$fill_struct .= sprintf("%8s %*s = %s,\n",
" ",
-$max_len, ".$struct_field",
"__glX${name}Noop");
}
}
print_disclaimer();
print "#include <X11/Xlib.h>\n";
print "#include <GL/glx.h>\n";
print "\n";
print "#include \"libglxabipriv.h\"\n";
print "#include \"libglxnoop.h\"\n";
print "\n";
print "#define GLXNOOP static __attribute__((unused))\n";
print "\n";
print $noop_defs;
print "\n";
print "const __GLXdispatchTableStatic __glXDispatchNoop = {\n";
print " .glx14ep = {\n";
print $fill_struct;
print " }\n";
print "};\n";
print "\n";
print "const __GLXdispatchTableStatic *__glXDispatchNoopPtr = &__glXDispatchNoop;\n";
}
sub print_gl_wrapper {
my $functions = shift;
my $fnptrs = "";
my $wrappers = "";
my $init_assign = "";
foreach my $function (@$functions) {
my $name = $function->{"name"};
my $param_proto_list = get_param_proto_list($function);
my $param_pass_list = get_param_pass_list($function);
my $rettype = $function->{"returns"};
my $retval = $function->{"default_retval"};
my $fnptrtype = "fn_${name}_ptr";
my $fnptrname = "__glXReal$name";
$fnptrs .= "typedef $rettype (*$fnptrtype)($param_proto_list);\n";
$fnptrs .= "static $fnptrtype $fnptrname;\n";
$fnptrs .= "\n";
$wrappers .= "PUBLIC $rettype glX${name}($param_proto_list)\n";
$wrappers .= "{\n";
if ($rettype ne "void") {
$wrappers .= " $rettype ret = $retval;\n";
}
$wrappers .= " if ($fnptrname) {\n";
if ($rettype ne "void") {
$wrappers .= " ret = (*$fnptrname)($param_pass_list);\n";
} else {
$wrappers .= " (*$fnptrname)($param_pass_list);\n";
}
$wrappers .= " }\n";
if ($rettype ne "void") {
$wrappers .= " return ret;\n";
}
$wrappers .= "}\n";
$wrappers .= "\n";
$init_assign .= " $fnptrname = ($fnptrtype)pGetProcAddress((const GLubyte *)\"glX$name\");\n";
}
print_disclaimer();
print "#include <X11/Xlib.h>\n";
print "#include <GL/glx.h>\n";
print "#include \"compiler.h\"\n";
print "#include \"libgl.h\"\n";
print "\n";
print $fnptrs;
print "\n";
print $wrappers;
print "\n";
print "void __glXWrapperInit(__GLXGetCachedProcAddressPtr pGetProcAddress)\n";
print "{\n";
print $init_assign;
print "}\n";
}
my @functions = parse_spec();
if ($mode eq "noop") {
print_noop_funcs(\@functions);
} elsif ($mode eq "glwrap") {
print_gl_wrapper(\@functions);
} else {
die "unknown mode $mode";
}

353
src/GLX/glx_funcs.spec Normal file
View file

@ -0,0 +1,353 @@
########################################################################
# Copyright (c) 2013, NVIDIA CORPORATION.
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and/or associated documentation files (the
# "Materials"), to deal in the Materials without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Materials, and to
# permit persons to whom the Materials are furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# unaltered in all copies or substantial portions of the Materials.
# Any additions, deletions, or changes to the original source files
# must be clearly indicated in accompanying documentation.
#
# If only executable code is distributed, then the accompanying
# documentation must state that "this software is based in part on the
# work of the Khronos Group."
#
# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
########################################################################
########################################################################
#
# glx_funcs.spec: parsed by gen_stubs.pl
#
# Spec file used to generate no-op GLX functions and libGL wrapper stubs.
#
# Each function prototype uses the following format:
#
# function "FunctionName"
# returns "return_type" "default_return_value"
# param "param_type1" "param_name1"
# param "param_type2" "param_name2"
# ...
#
# Defines a spec for function fooBar.
#
# The "returns" line defines the return type of the function. If the return type
# is void, the default_return_value field is ignored; otherwise, it is used to
# determine the return value if the dispatcher fails to redirect the function
# call to a vendor.
#
# Each "param" line defines a different argument in the function prototype.
#
# A "glx14ep" line indicates this function should be plugged into the static
# dispatch table.
#
# A (rough) BNF syntax for this spec file follows:
#
# <spec-file> :== <function-description>*
# <function-description> :== <function-line> <prop-lines> <end-of-function-description>
# <function-line> := "function" <blank> <text> <end-of-line>
# <prop-lines> :== ( <param-line> | <returns-line> | "glx14ep" )*
# <param-line> :== "param" <text> <text> <end-of-line>
# <returns-line> :== "returns" <text> <text> <end-of-line>
# <end-of-function-description> :== <blank-line>+ | <end-of-file>
#
########################################################################
function "ChooseVisual"
returns "XVisualInfo*" "NULL"
param "Display *" "dpy"
param "int" "screen"
param "int *" "attrib_list"
glx14ep
function "CopyContext"
returns "void" ""
param "Display *" "dpy"
param "GLXContext" "src"
param "GLXContext" "dst"
param "unsigned long" "mask"
glx14ep
function "CreateContext"
returns "GLXContext" "None"
param "Display *" "dpy"
param "XVisualInfo *" "vis"
param "GLXContext" "share_list"
param "Bool" "direct"
glx14ep
function "CreateGLXPixmap"
returns "GLXPixmap" "None"
param "Display *" "dpy"
param "XVisualInfo *" "vis"
param "Pixmap" "pixmap"
glx14ep
function "DestroyContext"
returns "void" ""
param "Display *" "dpy"
param "GLXContext" "ctx"
glx14ep
function "DestroyGLXPixmap"
returns "void" ""
param "Display *" "dpy"
param "GLXPixmap" "pix"
glx14ep
function "GetConfig"
returns "int" "GLX_BAD_SCREEN"
param "Display *" "dpy"
param "XVisualInfo *" "vis"
param "int" "attrib"
param "int *" "value"
glx14ep
function "IsDirect"
returns "Bool" "False"
param "Display *" "dpy"
param "GLXContext" "ctx"
glx14ep
function "MakeCurrent"
returns "Bool" "False"
param "Display *" "dpy"
param "GLXDrawable" "drawable"
param "GLXContext" "ctx"
glx14ep
function "SwapBuffers"
returns "void" ""
param "Display *" "dpy"
param "GLXDrawable" "drawable"
glx14ep
function "UseXFont"
returns "void" ""
param "Font" "font"
param "int" "first"
param "int" "count"
param "int" "list_base"
glx14ep
function "WaitGL"
returns "void" ""
glx14ep
function "WaitX"
returns "void" ""
glx14ep
function "QueryServerString"
returns "const char *" "NULL"
param "Display *" "dpy"
param "int" "screen"
param "int" "name"
glx14ep
function "GetClientString"
returns "const char *" "NULL"
param "Display *" "dpy"
param "int" "name"
glx14ep
function "QueryExtensionsString"
returns "const char *" "NULL"
param "Display *" "dpy"
param "int" "screen"
glx14ep
function "ChooseFBConfig"
returns "GLXFBConfig *" "NULL"
param "Display *" "dpy"
param "int" "screen"
param "const int *" "attrib_list"
param "int *" "nelements"
glx14ep
function "CreateNewContext"
returns "GLXContext" "None"
param "Display *" "dpy"
param "GLXFBConfig" "config"
param "int" "render_type"
param "GLXContext" "share_list"
param "Bool" "direct"
glx14ep
function "CreatePbuffer"
returns "GLXPbuffer" "None"
param "Display *" "dpy"
param "GLXFBConfig" "config"
param "const int *" "attrib_list"
glx14ep
function "CreatePixmap"
returns "GLXPixmap" "None"
param "Display *" "dpy"
param "GLXFBConfig" "config"
param "Pixmap" "pixmap"
param "const int *" "attrib_list"
glx14ep
function "CreateWindow"
returns "GLXWindow" "None"
param "Display *" "dpy"
param "GLXFBConfig" "config"
param "Window" "win"
param "const int *" "attrib_list"
glx14ep
function "DestroyPbuffer"
returns "void" ""
param "Display *" "dpy"
param "GLXPbuffer" "pbuf"
glx14ep
function "DestroyPixmap"
returns "void" ""
param "Display *" "dpy"
param "GLXPixmap" "pixmap"
glx14ep
function "DestroyWindow"
returns "void" ""
param "Display *" "dpy"
param "GLXWindow" "win"
glx14ep
function "GetFBConfigAttrib"
returns "int" "0"
param "Display *" "dpy"
param "GLXFBConfig" "config"
param "int" "attribute"
param "int *" "value"
glx14ep
function "GetFBConfigs"
returns "GLXFBConfig *" "NULL"
param "Display *" "dpy"
param "int" "screen"
param "int *" "nelements"
glx14ep
function "GetSelectedEvent"
returns "void" ""
param "Display *" "dpy"
param "GLXDrawable" "draw"
param "unsigned long *" "event_mask"
glx14ep
function "GetVisualFromFBConfig"
returns "XVisualInfo *" "NULL"
param "Display *" "dpy"
param "GLXFBConfig" "config"
glx14ep
function "MakeContextCurrent"
returns "Bool" "False"
param "Display *" "display"
param "GLXDrawable" "draw"
param "GLXDrawable" "read"
param "GLXContext" "ctx"
glx14ep
function "QueryContext"
returns "int" "0"
param "Display *" "dpy"
param "GLXContext" "ctx"
param "int" "attribute"
param "int *" "value"
glx14ep
function "QueryDrawable"
returns "void" ""
param "Display *" "dpy"
param "GLXDrawable" "draw"
param "int" "attribute"
param "unsigned int *" "value"
glx14ep
function "SelectEvent"
returns "void" ""
param "Display *" "dpy"
param "GLXDrawable" "draw"
param "unsigned long" "event_mask"
glx14ep
function "GetCurrentContext"
returns "GLXContext" "None"
function "GetCurrentDrawable"
returns "GLXDrawable" "None"
function "GetCurrentReadDrawable"
returns "GLXDrawable" "None"
function "GetProcAddress"
returns "__GLXextFuncPtr" "NULL"
param "const GLubyte *" "procName"
function "GetProcAddressARB"
returns "__GLXextFuncPtr" "NULL"
param "const GLubyte *" "procName"
function "QueryExtension"
returns "Bool" "False"
param "Display *" "dpy"
param "int *" "error_base"
param "int *" "event_base"
function "QueryVersion"
returns "Bool" "False"
param "Display *" "dpy"
param "int *" "major"
param "int *" "minor"

View file

@ -41,6 +41,7 @@
#include "trace.h"
#include "GL/glxproto.h"
#include "x11glvnd.h"
#include "libglxgl.h"
#include "lkdhash.h"
@ -1110,7 +1111,11 @@ void cacheInitializeOnce(void)
}
static __GLXextFuncPtr getCachedProcAddress(const GLubyte *procName)
/*
* This function is called externally by the libGL wrapper library to
* retrieve libGLX entrypoints.
*/
PUBLIC __GLXextFuncPtr __glXGetCachedProcAddress(const GLubyte *procName)
{
/*
* If this is the first time GetProcAddress has been called,
@ -1173,7 +1178,7 @@ PUBLIC __GLXextFuncPtr glXGetProcAddress(const GLubyte *procName)
* a previous GetProcAddress() call or by virtue of being a function
* exported by libGLX.
*/
addr = getCachedProcAddress(procName);
addr = __glXGetCachedProcAddress(procName);
if (addr) {
return addr;
}

12
src/GLX/libglxgl.h Normal file
View file

@ -0,0 +1,12 @@
#if !defined(__LIB_GLX_GL_H)
#define __LIB_GLX_GL_H
#include <GL/glx.h>
/*
* Glue header defining the ABI between libGLX and the libGL wrapper library.
*/
extern __GLXextFuncPtr __glXGetCachedProcAddress(const GLubyte *procName);
#endif // !defined(__LIB_GLX_GL_H)

View file

@ -1,78 +0,0 @@
/*
* Copyright (c) 2013, NVIDIA CORPORATION.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* unaltered in all copies or substantial portions of the Materials.
* Any additions, deletions, or changes to the original source files
* must be clearly indicated in accompanying documentation.
*
* If only executable code is distributed, then the accompanying
* documentation must state that "this software is based in part on the
* work of the Khronos Group."
*
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include <X11/Xlib.h>
#include <GL/glx.h>
#include "libglxabipriv.h"
#include "libglxnoop.h"
#define GLXNOOP static __attribute__((unused))
#define NOOP_FUNC(func) __glX ## func ## Noop
#include "libglxnoopdefs.h"
const __GLXdispatchTableStatic __glXDispatchNoop = {
.glx14ep = {
.chooseVisual = __glXChooseVisualNoop,
.copyContext = __glXCopyContextNoop,
.createContext = __glXCreateContextNoop,
.createGLXPixmap = __glXCreateGLXPixmapNoop,
.destroyContext = __glXDestroyContextNoop,
.destroyGLXPixmap = __glXDestroyGLXPixmapNoop,
.getConfig = __glXGetConfigNoop,
.isDirect = __glXIsDirectNoop,
.makeCurrent = __glXMakeCurrentNoop,
.swapBuffers = __glXSwapBuffersNoop,
.useXFont = __glXUseXFontNoop,
.waitGL = __glXWaitGLNoop,
.waitX = __glXWaitXNoop,
.queryServerString = __glXQueryServerStringNoop,
.getClientString = __glXGetClientStringNoop,
.queryExtensionsString = __glXQueryExtensionsStringNoop,
.chooseFBConfig = __glXChooseFBConfigNoop,
.createNewContext = __glXCreateNewContextNoop,
.createPbuffer = __glXCreatePbufferNoop,
.createPixmap = __glXCreatePixmapNoop,
.createWindow = __glXCreateWindowNoop,
.destroyPbuffer = __glXDestroyPbufferNoop,
.destroyPixmap = __glXDestroyPixmapNoop,
.destroyWindow = __glXDestroyWindowNoop,
.getFBConfigAttrib = __glXGetFBConfigAttribNoop,
.getFBConfigs = __glXGetFBConfigsNoop,
.getSelectedEvent = __glXGetSelectedEventNoop,
.getVisualFromFBConfig = __glXGetVisualFromFBConfigNoop,
.makeContextCurrent = __glXMakeContextCurrentNoop,
.queryContext = __glXQueryContextNoop,
.queryDrawable = __glXQueryDrawableNoop,
.selectEvent = __glXSelectEventNoop
}
};
const __GLXdispatchTableStatic *__glXDispatchNoopPtr = &__glXDispatchNoop;

View file

@ -1,292 +0,0 @@
/*
* Copyright (c) 2013, NVIDIA CORPORATION.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and/or associated documentation files (the
* "Materials"), to deal in the Materials without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Materials, and to
* permit persons to whom the Materials are furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be included
* unaltered in all copies or substantial portions of the Materials.
* Any additions, deletions, or changes to the original source files
* must be clearly indicated in accompanying documentation.
*
* If only executable code is distributed, then the accompanying
* documentation must state that "this software is based in part on the
* work of the Khronos Group."
*
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
#include <X11/Xlib.h>
#include <GL/glx.h>
/*
* Header with templates for generating noop functions. This is sourced by
* libglxnoop.c and the libGL filter library code.
*/
GLXNOOP XVisualInfo* NOOP_FUNC(ChooseVisual)(Display *dpy, int screen,
int *attrib_list)
{
return NULL;
}
GLXNOOP void NOOP_FUNC(CopyContext)(Display *dpy, GLXContext src,
GLXContext dst, unsigned long mask)
{
return;
}
GLXNOOP GLXContext NOOP_FUNC(CreateContext)(Display *dpy, XVisualInfo *vis,
GLXContext share_list, Bool direct)
{
return NULL;
}
GLXNOOP GLXPixmap NOOP_FUNC(CreateGLXPixmap)(Display *dpy,
XVisualInfo *vis,
Pixmap pixmap)
{
return None;
}
GLXNOOP void NOOP_FUNC(DestroyContext)(Display *dpy, GLXContext ctx)
{
return;
}
GLXNOOP void NOOP_FUNC(DestroyGLXPixmap)(Display *dpy, GLXPixmap pix)
{
return;
}
GLXNOOP int NOOP_FUNC(GetConfig)(Display *dpy, XVisualInfo *vis,
int attrib, int *value)
{
/*
* We get here if libglvnd couldn't find a valid vendor for vis->screen.
* Hence, "the screen of vis does not correspond to a screen".
*/
return GLX_BAD_SCREEN;
}
GLXNOOP Bool NOOP_FUNC(IsDirect)(Display *dpy, GLXContext ctx)
{
return False;
}
GLXNOOP Bool NOOP_FUNC(MakeCurrent)(Display *dpy, GLXDrawable drawable,
GLXContext ctx)
{
return False;
}
GLXNOOP void NOOP_FUNC(SwapBuffers)(Display *dpy, GLXDrawable drawable)
{
return;
}
GLXNOOP void NOOP_FUNC(UseXFont)(Font font, int first, int count, int list_base)
{
return;
}
GLXNOOP void NOOP_FUNC(WaitGL)(void)
{
return;
}
GLXNOOP void NOOP_FUNC(WaitX)(void)
{
return;
}
GLXNOOP const char* NOOP_FUNC(QueryServerString)(Display *dpy,
int screen, int name)
{
return NULL;
}
GLXNOOP const char *NOOP_FUNC(GetClientString)(Display *dpy, int name)
{
return NULL;
}
GLXNOOP const char* NOOP_FUNC(QueryExtensionsString)(Display *dpy, int screen)
{
return NULL;
}
GLXNOOP GLXFBConfig* NOOP_FUNC(ChooseFBConfig)(Display *dpy, int screen,
const int *attrib_list,
int *nelements)
{
return NULL;
}
GLXNOOP GLXContext NOOP_FUNC(CreateNewContext)(Display *dpy, GLXFBConfig config,
int render_type,
GLXContext share_list, Bool direct)
{
return NULL;
}
GLXNOOP GLXPbuffer NOOP_FUNC(CreatePbuffer)(Display *dpy, GLXFBConfig config,
const int *attrib_list)
{
return None;
}
GLXNOOP GLXPixmap NOOP_FUNC(CreatePixmap)(Display *dpy, GLXFBConfig config,
Pixmap pixmap, const int *attrib_list)
{
return None;
}
GLXNOOP GLXWindow NOOP_FUNC(CreateWindow)(Display *dpy, GLXFBConfig config,
Window win, const int *attrib_list)
{
return None;
}
GLXNOOP void NOOP_FUNC(DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf)
{
return;
}
GLXNOOP void NOOP_FUNC(DestroyPixmap)(Display *dpy, GLXPixmap pixmap)
{
return;
}
GLXNOOP void NOOP_FUNC(DestroyWindow)(Display *dpy, GLXWindow win)
{
return;
}
GLXNOOP int NOOP_FUNC(GetFBConfigAttrib)(Display *dpy, GLXFBConfig config,
int attribute, int *value)
{
return 0;
}
GLXNOOP GLXFBConfig* NOOP_FUNC(GetFBConfigs)(Display *dpy,
int screen, int *nelements)
{
return NULL;
}
GLXNOOP void NOOP_FUNC(GetSelectedEvent)(Display *dpy, GLXDrawable draw,
unsigned long *event_mask)
{
return;
}
GLXNOOP XVisualInfo* NOOP_FUNC(GetVisualFromFBConfig)(Display *dpy,
GLXFBConfig config)
{
return NULL;
}
GLXNOOP Bool NOOP_FUNC(MakeContextCurrent)(Display *dpy, GLXDrawable draw,
GLXDrawable read, GLXContext ctx)
{
return False;
}
GLXNOOP int NOOP_FUNC(QueryContext)(Display *dpy, GLXContext ctx,
int attribute, int *value)
{
return 0;
}
GLXNOOP void NOOP_FUNC(QueryDrawable)(Display *dpy, GLXDrawable draw,
int attribute, unsigned int *value)
{
return;
}
GLXNOOP void NOOP_FUNC(SelectEvent)(Display *dpy, GLXDrawable draw,
unsigned long event_mask)
{
return;
}
GLXNOOP GLXContext NOOP_FUNC(GetCurrentContext)(void)
{
return None;
}
GLXNOOP GLXDrawable NOOP_FUNC(GetCurrentDrawable)(void)
{
return None;
}
GLXNOOP GLXDrawable NOOP_FUNC(GetCurrentReadDrawable)(void)
{
return None;
}
GLXNOOP __GLXextFuncPtr NOOP_FUNC(GetProcAddress)(const GLubyte *procName)
{
return NULL;
}
GLXNOOP __GLXextFuncPtr NOOP_FUNC(GetProcAddressARB)(const GLubyte *procName)
{
return NULL;
}
GLXNOOP Bool NOOP_FUNC(QueryExtension)(Display *dpy,
int *error_base,
int *event_base)
{
return False;
}
GLXNOOP Bool NOOP_FUNC(QueryVersion)(Display *dpy,
int *major,
int *minor)
{
return False;
}

View file

@ -27,6 +27,7 @@
noinst_HEADERS = \
GLdispatch.h \
GLdispatchABI.h \
GLdispatchPrivate.h
lib_LTLIBRARIES = libGLdispatch.la

View file

@ -32,7 +32,6 @@
/* define macros for use by assembly dispatchers */
#define ENTRY_CURRENT_TABLE U_STRINGIFY(u_current)
/* in bridge mode, mapi is a user of glapi */
#define ENTRY_CURRENT_TABLE_GET U_STRINGIFY(u_current_get_internal)
#if defined(USE_X86_ASM) && defined(__GNUC__)
@ -44,44 +43,6 @@
#elif defined(USE_X86_64_ASM) && defined(__GNUC__) && defined(GLX_USE_TLS)
# include "entry_x86-64_tls.h"
#else
# include "entry_pure_c.h"
#endif
#include <stdlib.h>
static INLINE const struct mapi_table *
entry_current_get(void)
{
return u_current_get();
}
/* C version of the public entries */
#define MAPI_TMP_DEFINES
#define MAPI_TMP_PUBLIC_DECLARES
#define MAPI_TMP_PUBLIC_ENTRIES
#include "mapi_tmp.h"
void
entry_patch_public(void)
{
}
mapi_func
entry_get_public(int slot)
{
/* pubic_entries are defined by MAPI_TMP_PUBLIC_ENTRIES */
return public_entries[slot];
}
mapi_func
entry_generate(int slot)
{
return NULL;
}
void
entry_patch(mapi_func entry, int slot)
{
}
#endif /* asm */

View file

@ -0,0 +1,65 @@
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2010 LunarG Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
*/
#include <stdlib.h>
static INLINE const struct mapi_table *
entry_current_get(void)
{
return u_current_get();
}
/* C version of the public entries */
#define MAPI_TMP_DEFINES
#define MAPI_TMP_PUBLIC_DECLARES
#define MAPI_TMP_PUBLIC_ENTRIES
#include "mapi_tmp.h"
void
entry_patch_public(void)
{
}
#if !defined(STATIC_DISPATCH_ONLY)
mapi_func
entry_get_public(int slot)
{
/* pubic_entries are defined by MAPI_TMP_PUBLIC_ENTRIES */
return public_entries[slot];
}
mapi_func
entry_generate(int slot)
{
return NULL;
}
void
entry_patch(mapi_func entry, int slot)
{
}
#endif // !defined(STATIC_DISPATCH_ONLY)

View file

@ -61,6 +61,7 @@ entry_patch_public(void)
{
}
#if !defined(STATIC_DISPATCH_ONLY)
static char
x86_64_entry_start[];
@ -107,4 +108,4 @@ entry_generate(int slot)
return entry;
}
#endif // !defined(STATIC_DISPATCH_ONLY)

View file

@ -91,6 +91,7 @@ entry_patch_public(void)
#endif
}
#if !defined(STATIC_DISPATCH_ONLY)
mapi_func
entry_get_public(int slot)
{
@ -127,4 +128,5 @@ entry_generate(int slot)
return entry;
}
#endif // !defined(STATIC_DISPATCH_ONLY)

View file

@ -66,6 +66,7 @@ entry_patch_public(void)
{
}
#if !defined(STATIC_DISPATCH_ONLY)
mapi_func
entry_get_public(int slot)
{
@ -98,4 +99,4 @@ entry_generate(int slot)
return entry;
}
#endif // !defined(STATIC_DISPATCH_ONLY)

View file

@ -92,7 +92,7 @@
/*@{*/
#if defined(GLX_USE_TLS)
__thread void *u_current[U_CURRENT_NUM_ENTRIES]
PUBLIC __thread void *u_current[U_CURRENT_NUM_ENTRIES]
__attribute__((tls_model("initial-exec")))
= {
(void *) table_noop_array,
@ -101,7 +101,7 @@ __thread void *u_current[U_CURRENT_NUM_ENTRIES]
#else
void *u_current[U_CURRENT_NUM_ENTRIES]
PUBLIC void *u_current[U_CURRENT_NUM_ENTRIES]
= {
(void *) table_noop_array,
NULL