hw/xwin/glx: Rewrite WGL wrappers after Xserver conversion to direct GL dispatch
v1: Rewrite by Marc Haesen of the WGL wrapper function generation script to use Khronos group XML. v2: Remove -dispatchheader option, since dispatch.h doesn't exist anymore, use the private glapi interface to construct the GL dispatch table for the native WGL thunks. v3: Rewrite to generate shims for the OpenGL 1.2.1 (GL 1.2 + GL_ARB_imaging +GL_ARB_multitexture + GL_ARB_texture_compression(?)) functions the server links directly with rather than libGL. These shims dispatch to either the mesa GL DLL, or a thunking DLL containing cdecl-to-stcall wrapper functions for the native GL DLL. Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk> Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
parent
cb48877a3c
commit
9a4d7572fe
14
configure.ac
14
configure.ac
|
@ -2109,7 +2109,7 @@ if test "x$XWIN" = xyes; then
|
|||
esac
|
||||
|
||||
XWIN_LIBS="$FB_LIB $MI_LIB $FIXES_LIB $XEXT_LIB $RANDR_LIB $RENDER_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $DAMAGE_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $OS_LIB"
|
||||
XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS $GLX_SYS_LIBS"
|
||||
XWIN_SYS_LIBS="$XWIN_SYS_LIBS $XWINMODULES_LIBS"
|
||||
AC_SUBST(XWIN_LIBS)
|
||||
AC_SUBST(XWIN_SERVER_NAME)
|
||||
AC_SUBST(XWIN_SYS_LIBS)
|
||||
|
@ -2125,10 +2125,16 @@ if test "x$XWIN" = xyes; then
|
|||
|
||||
dnl XWin with AIGLX requires OpenGL spec files in order to generate wrapper code for native GL functions
|
||||
if [test "x$XWIN" = xyes && test "x$AIGLX" = xyes] ; then
|
||||
AC_CHECK_PROG(PYTHON, python, python)
|
||||
if test -z "$PYTHON"; then
|
||||
AC_MSG_ERROR([python not found])
|
||||
AC_CHECK_PROG(PYTHON3, python3, python3)
|
||||
if test -z "$PYTHON3"; then
|
||||
AC_MSG_ERROR([python3 not found])
|
||||
fi
|
||||
AC_MSG_CHECKING(for python module lxml)
|
||||
$PYTHON3 -c "import lxml;"
|
||||
if test $? -ne 0 ; then
|
||||
AC_MSG_ERROR([not found])
|
||||
fi
|
||||
AC_MSG_RESULT(yes)
|
||||
if test "x$KHRONOS_SPEC_DIR" = "xauto" ; then
|
||||
PKG_CHECK_MODULES([KHRONOS_OPENGL_REGISTRY], [khronos-opengl-registry])
|
||||
KHRONOS_SPEC_DIR=`pkg-config khronos-opengl-registry --variable=specdir`
|
||||
|
|
|
@ -157,7 +157,7 @@ XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la
|
|||
|
||||
XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS)
|
||||
XWin_LDADD = $(MULTIWINDOW_LIBS) $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_GLX_LINK_FLAGS) $(XWIN_LIBS) $(MAIN_LIB) $(XSERVER_LIBS) $(XSERVER_SYS_LIBS) $(XWIN_SYS_LIBS)
|
||||
XWin_LDFLAGS = -mwindows -static
|
||||
XWin_LDFLAGS = -mwindows -static -Wl,--disable-stdcall-fixup
|
||||
|
||||
.rc.o:
|
||||
$(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include
|
||||
|
|
|
@ -1,14 +1,18 @@
|
|||
noinst_LTLIBRARIES = libXwinGLX.la
|
||||
lib_LTLIBRARIES = libnativeGLthunk.la
|
||||
|
||||
libXwinGLX_la_SOURCES = \
|
||||
winpriv.c \
|
||||
winpriv.h \
|
||||
glwindows.h \
|
||||
glwrap.c \
|
||||
glshim.c \
|
||||
indirect.c \
|
||||
wgl_ext_api.c \
|
||||
wgl_ext_api.h
|
||||
|
||||
libnativeGLthunk_la_SOURCES = \
|
||||
glthunk.c
|
||||
|
||||
if XWIN_MULTIWINDOW
|
||||
DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW
|
||||
endif
|
||||
|
@ -30,16 +34,32 @@ AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \
|
|||
-I$(top_srcdir) \
|
||||
-I$(top_srcdir)/hw/xwin/
|
||||
|
||||
libnativeGLthunk_la_CFLAGS = $(AM_CFLAGS) -Wno-unused-function -Wno-missing-prototypes -Wno-missing-declarations
|
||||
libnativeGLthunk_la_LDFLAGS = -shared -no-undefined -avoid-version -lopengl32 -export-symbols generated_gl_thunks.def
|
||||
EXTRA_libnativeGLthunk_la_DEPENDENCIES = generated_gl_thunks.def
|
||||
|
||||
if XWIN_GLX_WINDOWS
|
||||
|
||||
generated_gl_wrappers.c: gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/gl.spec $(KHRONOS_SPEC_DIR)/gl.tm
|
||||
$(AM_V_GEN)$(PYTHON) $(srcdir)/gen_gl_wrappers.py --spec=$(KHRONOS_SPEC_DIR)/gl.spec --typemap=$(KHRONOS_SPEC_DIR)/gl.tm --dispatch-header=$(top_srcdir)/glx/dispatch.h --staticwrappers >generated_gl_wrappers.c
|
||||
|
||||
generated_wgl_wrappers.c: gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/wglext.spec $(KHRONOS_SPEC_DIR)/wgl.tm
|
||||
$(AM_V_GEN)$(PYTHON) $(srcdir)/gen_gl_wrappers.py --spec=$(KHRONOS_SPEC_DIR)/wglext.spec --typemap=$(KHRONOS_SPEC_DIR)/wgl.tm --prefix=wgl --preresolve >generated_wgl_wrappers.c
|
||||
if DEBUG
|
||||
GENGLWRAPPERSOPTS=""
|
||||
else
|
||||
GENGLWRAPPERSOPTS="-nodebug"
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = generated_gl_wrappers.c generated_wgl_wrappers.c
|
||||
generated_wgl_wrappers.c: $(srcdir)/gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/wgl.xml $(KHRONOS_SPEC_DIR)/reg.py
|
||||
$(AM_V_GEN)PYTHONPATH=$(KHRONOS_SPEC_DIR) $(PYTHON3) $(srcdir)/gen_gl_wrappers.py -registry $(KHRONOS_SPEC_DIR)/wgl.xml -prefix wgl -wrapper -preresolve $(GENGLWRAPPERSOPTS) -outfile $@
|
||||
|
||||
generated_gl_shim.c: $(srcdir)/gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/gl.xml $(KHRONOS_SPEC_DIR)/reg.py
|
||||
$(AM_V_GEN)PYTHONPATH=$(KHRONOS_SPEC_DIR) $(PYTHON3) $(srcdir)/gen_gl_wrappers.py -registry $(KHRONOS_SPEC_DIR)/gl.xml -shim $(GENGLWRAPPERSOPTS) -outfile $@
|
||||
|
||||
generated_gl_thunks.c: $(srcdir)/gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/gl.xml $(KHRONOS_SPEC_DIR)/reg.py
|
||||
$(AM_V_GEN)PYTHONPATH=$(KHRONOS_SPEC_DIR) $(PYTHON3) $(srcdir)/gen_gl_wrappers.py -registry $(KHRONOS_SPEC_DIR)/gl.xml -thunk $(GENGLWRAPPERSOPTS) -outfile $@
|
||||
|
||||
generated_gl_thunks.def: $(srcdir)/gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/gl.xml $(KHRONOS_SPEC_DIR)/reg.py
|
||||
$(AM_V_GEN)PYTHONPATH=$(KHRONOS_SPEC_DIR) $(PYTHON3) $(srcdir)/gen_gl_wrappers.py -registry $(KHRONOS_SPEC_DIR)/gl.xml -thunkdefs $(GENGLWRAPPERSOPTS) -outfile $@
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = generated_gl_shim.c generated_gl_thunks.c generated_gl_thunks.def generated_wgl_wrappers.c
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
EXTRA_DIST = gen_gl_wrappers.py
|
||||
|
|
|
@ -1,325 +1,485 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Comedy python script to generate cdecl to stdcall wrappers for GL functions
|
||||
# python script to generate cdecl to stdcall wrappers for GL functions
|
||||
# adapted from genheaders.py
|
||||
#
|
||||
# This is designed to operate on OpenGL spec files from
|
||||
# http://www.opengl.org/registry/api/
|
||||
#
|
||||
#
|
||||
# Copyright (c) Jon TURNEY 2009
|
||||
# Copyright (c) 2013 The Khronos Group 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:
|
||||
# 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 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 ABOVE LISTED COPYRIGHT HOLDER(S) 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.
|
||||
#
|
||||
# Except as contained in this notice, the name(s) of the above copyright
|
||||
# holders shall not be used in advertising or otherwise to promote the sale,
|
||||
# use or other dealings in this Software without prior written authorization.
|
||||
# The above copyright notice and this permission notice shall be included
|
||||
# in all copies or substantial portions of the Materials.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import sys
|
||||
import re
|
||||
import getopt
|
||||
import sys, time, pdb, string, cProfile
|
||||
from reg import *
|
||||
|
||||
dispatchheader = ''
|
||||
prefix = 'gl'
|
||||
preresolve = False
|
||||
staticwrappers = False
|
||||
# Default input / log files
|
||||
errFilename = None
|
||||
diagFilename = 'diag.txt'
|
||||
regFilename = 'gl.xml'
|
||||
outFilename = 'gen_gl_wrappers.c'
|
||||
|
||||
opts, args = getopt.getopt(sys.argv[1:], "", ['spec=', 'typemap=', 'dispatch-header=', 'prefix=', 'preresolve', 'staticwrappers' ])
|
||||
protect=True
|
||||
prefix="gl"
|
||||
preresolve=False
|
||||
wrapper=False
|
||||
shim=False
|
||||
thunk=False
|
||||
thunkdefs=False
|
||||
staticwrappers=False
|
||||
nodebug=False
|
||||
|
||||
for o,a in opts:
|
||||
if o == '--typemap' :
|
||||
typemapfile = a
|
||||
elif o == '--dispatch-header' :
|
||||
dispatchheader = a
|
||||
elif o == '--spec' :
|
||||
specfile = a
|
||||
elif o == '--prefix' :
|
||||
prefix = a
|
||||
elif o == '--preresolve' :
|
||||
preresolve = True
|
||||
elif o == '--staticwrappers' :
|
||||
staticwrappers = True
|
||||
#exclude base WGL API
|
||||
WinGDI={key: 1 for key in [
|
||||
"wglCopyContext"
|
||||
,"wglCreateContext"
|
||||
,"wglCreateLayerContext"
|
||||
,"wglDeleteContext"
|
||||
,"wglGetCurrentContext"
|
||||
,"wglGetCurrentDC"
|
||||
,"wglGetProcAddress"
|
||||
,"wglMakeCurrent"
|
||||
,"wglShareLists"
|
||||
,"wglUseFontBitmapsA"
|
||||
,"wglUseFontBitmapsW"
|
||||
,"wglUseFontBitmaps"
|
||||
,"SwapBuffers"
|
||||
,"wglUseFontOutlinesA"
|
||||
,"wglUseFontOutlinesW"
|
||||
,"wglUseFontOutlines"
|
||||
,"wglDescribeLayerPlane"
|
||||
,"wglSetLayerPaletteEntries"
|
||||
,"wglGetLayerPaletteEntries"
|
||||
,"wglRealizeLayerPalette"
|
||||
,"wglSwapLayerBuffers"
|
||||
,"wglSwapMultipleBuffers"
|
||||
,"ChoosePixelFormat"
|
||||
,"DescribePixelFormat"
|
||||
,"GetEnhMetaFilePixelFormat"
|
||||
,"GetPixelFormat"
|
||||
,"SetPixelFormat"
|
||||
]}
|
||||
|
||||
#
|
||||
# look for all the SET_ macros in dispatch.h, this is the set of functions
|
||||
# we need to generate
|
||||
#
|
||||
if __name__ == '__main__':
|
||||
i = 1
|
||||
while (i < len(sys.argv)):
|
||||
arg = sys.argv[i]
|
||||
i = i + 1
|
||||
if (arg == '-noprotect'):
|
||||
print('Disabling inclusion protection in output headers', file=sys.stderr)
|
||||
protect = False
|
||||
elif (arg == '-registry'):
|
||||
regFilename = sys.argv[i]
|
||||
i = i+1
|
||||
print('Using registry', regFilename, file=sys.stderr)
|
||||
elif (arg == '-outfile'):
|
||||
outFilename = sys.argv[i]
|
||||
i = i+1
|
||||
elif (arg == '-preresolve'):
|
||||
preresolve=True
|
||||
elif (arg == '-wrapper'):
|
||||
wrapper=True
|
||||
elif (arg == '-shim'):
|
||||
shim=True
|
||||
elif (arg == '-thunk'):
|
||||
thunk=True
|
||||
elif (arg == '-thunkdefs'):
|
||||
thunkdefs=True
|
||||
elif (arg == '-staticwrappers'):
|
||||
staticwrappers=True
|
||||
elif (arg == '-prefix'):
|
||||
prefix = sys.argv[i]
|
||||
i = i+1
|
||||
elif (arg == '-nodebug'):
|
||||
nodebug = True
|
||||
elif (arg[0:1] == '-'):
|
||||
print('Unrecognized argument:', arg, file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
dispatch = {}
|
||||
print('Generating', outFilename, file=sys.stderr)
|
||||
|
||||
if dispatchheader :
|
||||
fh = open(dispatchheader)
|
||||
dispatchh = fh.readlines()
|
||||
# Load & parse registry
|
||||
reg = Registry()
|
||||
tree = etree.parse(regFilename)
|
||||
reg.loadElementTree(tree)
|
||||
|
||||
dispatch_regex = re.compile(r'^SET_(\S*)\(')
|
||||
allVersions = '.*'
|
||||
|
||||
for line in dispatchh :
|
||||
line = line.strip()
|
||||
m1 = dispatch_regex.search(line)
|
||||
genOpts = CGeneratorOptions(
|
||||
apiname = prefix,
|
||||
profile = 'compatibility',
|
||||
versions = allVersions,
|
||||
emitversions = allVersions,
|
||||
defaultExtensions = prefix, # Default extensions for GL
|
||||
protectFile = protect,
|
||||
protectFeature = protect,
|
||||
protectProto = protect,
|
||||
)
|
||||
|
||||
if m1 :
|
||||
dispatch[m1.group(1)] = 1
|
||||
# create error/warning & diagnostic files
|
||||
if (errFilename):
|
||||
errWarn = open(errFilename,'w')
|
||||
else:
|
||||
errWarn = sys.stderr
|
||||
diag = open(diagFilename, 'w')
|
||||
|
||||
del dispatch['by_offset']
|
||||
class PreResolveOutputGenerator(OutputGenerator):
|
||||
def __init__(self,
|
||||
errFile = sys.stderr,
|
||||
warnFile = sys.stderr,
|
||||
diagFile = sys.stdout):
|
||||
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
|
||||
self.wrappers={}
|
||||
def beginFile(self, genOpts):
|
||||
self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
|
||||
def endFile(self):
|
||||
self.outFile.write('\nvoid ' + prefix + 'ResolveExtensionProcs(void)\n{\n')
|
||||
for funcname in self.wrappers.keys():
|
||||
self.outFile.write( ' PRERESOLVE(PFN' + funcname.upper() + 'PROC, "' + funcname + '");\n')
|
||||
self.outFile.write('}\n\n')
|
||||
def beginFeature(self, interface, emit):
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
def endFeature(self):
|
||||
OutputGenerator.endFeature(self)
|
||||
def genType(self, typeinfo, name):
|
||||
OutputGenerator.genType(self, typeinfo, name)
|
||||
def genEnum(self, enuminfo, name):
|
||||
OutputGenerator.genEnum(self, enuminfo, name)
|
||||
def genCmd(self, cmd, name):
|
||||
OutputGenerator.genCmd(self, cmd, name)
|
||||
|
||||
#
|
||||
# read the typemap .tm file
|
||||
#
|
||||
if name in WinGDI:
|
||||
return
|
||||
|
||||
typemap = {}
|
||||
self.outFile.write('RESOLVE_DECL(PFN' + name.upper() + 'PROC);\n')
|
||||
self.wrappers[name]=1
|
||||
|
||||
fh = open(typemapfile)
|
||||
tm = fh.readlines()
|
||||
class WrapperOutputGenerator(OutputGenerator):
|
||||
def __init__(self,
|
||||
errFile = sys.stderr,
|
||||
warnFile = sys.stderr,
|
||||
diagFile = sys.stdout):
|
||||
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
|
||||
def beginFile(self, genOpts):
|
||||
self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
|
||||
def endFile(self):
|
||||
pass
|
||||
def beginFeature(self, interface, emit):
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1')
|
||||
def endFeature(self):
|
||||
OutputGenerator.endFeature(self)
|
||||
def genType(self, typeinfo, name):
|
||||
OutputGenerator.genType(self, typeinfo, name)
|
||||
def genEnum(self, enuminfo, name):
|
||||
OutputGenerator.genEnum(self, enuminfo, name)
|
||||
def genCmd(self, cmd, name):
|
||||
OutputGenerator.genCmd(self, cmd, name)
|
||||
|
||||
typemap_regex = re.compile(r'#define\sSET_(\S*)\(')
|
||||
if name in WinGDI:
|
||||
return
|
||||
|
||||
for line in tm :
|
||||
# ignore everything after a '#' as a comment
|
||||
hash = line.find('#')
|
||||
if hash != -1 :
|
||||
line = line[:hash-1]
|
||||
|
||||
# ignore blank lines
|
||||
if line.startswith('#') or len(line) == 0 :
|
||||
continue
|
||||
|
||||
l = line.split(',')
|
||||
typemap[l[0]] = l[3].strip()
|
||||
|
||||
# interestingly, * is not a C type
|
||||
if typemap['void'] == '*' :
|
||||
typemap['void'] = 'void'
|
||||
|
||||
#
|
||||
# crudely parse the .spec file
|
||||
#
|
||||
|
||||
r1 = re.compile(r'\t(\S*)\s+(\S*.*)')
|
||||
r2 = re.compile(r'(.*)\((.*)\)')
|
||||
r3 = re.compile(r'glWindowPos.*MESA')
|
||||
r4 = re.compile(r'gl.*Program(s|)NV')
|
||||
r5 = re.compile(r'glGetVertexAttribfvNV')
|
||||
|
||||
wrappers = {}
|
||||
|
||||
fh = open(specfile)
|
||||
glspec = fh.readlines()
|
||||
param_count = 0
|
||||
|
||||
for line in glspec :
|
||||
line = line.rstrip()
|
||||
|
||||
# ignore everything after a '#' as a comment
|
||||
hash = line.find('#')
|
||||
if hash != -1 :
|
||||
line = line[:hash-1]
|
||||
|
||||
# ignore blank lines
|
||||
if line.startswith('#') or len(line) == 0 :
|
||||
continue
|
||||
|
||||
# lines containing ':' aren't intersting to us
|
||||
if line.count(':') != 0 :
|
||||
continue
|
||||
|
||||
# attributes of each function follow the name, indented by a tab
|
||||
if not line.startswith('\t') :
|
||||
m1 = r2.search(line)
|
||||
if m1 :
|
||||
function = m1.group(1)
|
||||
arglist_use = m1.group(2)
|
||||
wrappers[function] = {}
|
||||
|
||||
# ensure formal parameter names don't collide with reserved names or shadow global declarations
|
||||
arglist_use = ',' .join([i.rstrip() + '_' for i in arglist_use.split(",")])
|
||||
|
||||
wrappers[function]['arglist_use'] = arglist_use
|
||||
param_count = 0
|
||||
else :
|
||||
m1 = r1.search(line)
|
||||
if m1 :
|
||||
attribute = m1.group(1)
|
||||
value = m1.group(2)
|
||||
|
||||
# make param attributes unique and ordered
|
||||
if attribute == 'param' :
|
||||
attribute = 'param' + '%02d' % param_count
|
||||
param_count += 1
|
||||
|
||||
wrappers[function][attribute] = value
|
||||
|
||||
#
|
||||
# now emit code
|
||||
#
|
||||
|
||||
print '/* Automatically generated by ' + sys.argv[0] + ' DO NOT EDIT */'
|
||||
print '/* from ' + specfile + ' and typemap ' + typemapfile + ' */'
|
||||
print ''
|
||||
|
||||
#
|
||||
# if required, emit code for non-lazy function resolving
|
||||
#
|
||||
|
||||
if preresolve :
|
||||
for w in sorted(wrappers.keys()) :
|
||||
funcname = prefix + w
|
||||
print 'RESOLVE_DECL(PFN' + funcname.upper() + 'PROC);'
|
||||
|
||||
print ''
|
||||
print 'void ' + prefix + 'ResolveExtensionProcs(void)'
|
||||
print '{'
|
||||
|
||||
for w in sorted(wrappers.keys()) :
|
||||
funcname = prefix + w
|
||||
print ' PRERESOLVE(PFN' + funcname.upper() + 'PROC, "' + funcname + '");'
|
||||
|
||||
print '}\n'
|
||||
|
||||
#
|
||||
# now emit the wrappers
|
||||
# for GL 1.0 and 1.1 functions, generate stdcall wrappers which call the function directly
|
||||
# for GL 1.2+ functions, generate wrappers which use wglGetProcAddress()
|
||||
#
|
||||
|
||||
for w in sorted(wrappers.keys()) :
|
||||
|
||||
funcname = prefix + w
|
||||
returntype = wrappers[w]['return']
|
||||
if returntype != 'void' :
|
||||
returntype = typemap[returntype]
|
||||
|
||||
# Avoid generating wrappers which aren't referenced by the dispatch table
|
||||
if dispatchheader and not dispatch.has_key(w) :
|
||||
print '/* No wrapper for ' + funcname + ', not in dispatch table */'
|
||||
continue
|
||||
|
||||
# manufacture arglist
|
||||
# if no param attributes were found, it should be 'void'
|
||||
al = []
|
||||
for k in sorted(wrappers[w].keys()) :
|
||||
if k.startswith('param') :
|
||||
l = wrappers[w][k].split()
|
||||
|
||||
# ensure formal parameter names don't collide with reserved names or shadow global declarations
|
||||
l[0] = l[0] + '_'
|
||||
|
||||
if l[2] == 'in' :
|
||||
if l[3] == 'array' :
|
||||
arg = 'const ' + typemap[l[1]] + ' *' + l[0]
|
||||
else :
|
||||
arg = typemap[l[1]] + ' ' + l[0]
|
||||
elif l[2] == 'out' :
|
||||
arg = typemap[l[1]] + ' *' + l[0]
|
||||
|
||||
al.append(arg)
|
||||
|
||||
if len(al) == 0 :
|
||||
arglist = 'void'
|
||||
proto=noneStr(cmd.elem.find('proto'))
|
||||
rettype=noneStr(proto.text)
|
||||
if rettype.lower()!="void ":
|
||||
plist = ([t for t in proto.itertext()])
|
||||
rettype = ''.join(plist[:-1])
|
||||
rettype=rettype.strip()
|
||||
if staticwrappers: self.outFile.write("static ")
|
||||
self.outFile.write("%s %sWrapper("%(rettype, name))
|
||||
params = cmd.elem.findall('param')
|
||||
plist=[]
|
||||
for param in params:
|
||||
paramlist = ([t for t in param.itertext()])
|
||||
paramtype = ''.join(paramlist[:-1])
|
||||
paramname = paramlist[-1]
|
||||
plist.append((paramtype, paramname))
|
||||
Comma=""
|
||||
if len(plist):
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s%s_"%(Comma, ptype, pname))
|
||||
Comma=", "
|
||||
else:
|
||||
arglist = ', '.join(al)
|
||||
self.outFile.write("void")
|
||||
|
||||
if wrappers[w]['category'].startswith('VERSION_1_0') or wrappers[w]['category'].startswith('VERSION_1_1') :
|
||||
if staticwrappers :
|
||||
print 'static',
|
||||
print returntype + ' ' + funcname + 'Wrapper(' + arglist + ')'
|
||||
print '{'
|
||||
print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");'
|
||||
print ' glWinDirectProcCalls++;'
|
||||
if returntype.lower() == 'void' :
|
||||
print ' ' + funcname + '(',
|
||||
else :
|
||||
print ' /* returntype was ' + returntype.lower() + '*/'
|
||||
print ' return ' + funcname + '(',
|
||||
self.outFile.write(")\n{\n")
|
||||
|
||||
if arglist != 'void' :
|
||||
print wrappers[w]['arglist_use'],
|
||||
# for GL 1.0 and 1.1 functions, generate stdcall wrappers which call the function directly
|
||||
if self.OldVersion:
|
||||
if not nodebug:
|
||||
self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
|
||||
self.outFile.write(" glWinDirectProcCalls++;\n")
|
||||
self.outFile.write("\n")
|
||||
|
||||
print ');'
|
||||
print "}\n"
|
||||
if rettype.lower()=="void":
|
||||
self.outFile.write(" %s( "%(name))
|
||||
else:
|
||||
self.outFile.write(" return %s( "%(name))
|
||||
|
||||
Comma=""
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s_"%(Comma, pname))
|
||||
Comma=", "
|
||||
|
||||
# for GL 1.2+ functions, generate stdcall wrappers which use wglGetProcAddress()
|
||||
else:
|
||||
if staticwrappers :
|
||||
print 'static',
|
||||
print returntype + ' ' + funcname + 'Wrapper(' + arglist + ')'
|
||||
print '{'
|
||||
if rettype.lower()=="void":
|
||||
self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
|
||||
|
||||
stringname = funcname
|
||||
if not nodebug:
|
||||
self.outFile.write("\n")
|
||||
self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
|
||||
self.outFile.write("\n")
|
||||
|
||||
#
|
||||
# special case: Windows OpenGL implementations are far more likely to have GL_ARB_window_pos than GL_MESA_window_pos,
|
||||
# so arrange for the wrapper to use the ARB strings to find functions...
|
||||
#
|
||||
self.outFile.write(" RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
|
||||
else:
|
||||
self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", FALSE);\n'%(name.upper(), name))
|
||||
|
||||
m2 = r3.search(funcname)
|
||||
if m2 :
|
||||
stringname = stringname.replace('MESA','ARB')
|
||||
if not nodebug:
|
||||
self.outFile.write("\n")
|
||||
self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
|
||||
self.outFile.write("\n")
|
||||
|
||||
#
|
||||
# special case: likewise, implementations are more likely to have GL_ARB_vertex_program than GL_NV_vertex_program,
|
||||
# especially if they are not NV implementations, so arrange for the wrapper to use ARB strings to find functions
|
||||
#
|
||||
self.outFile.write(" return RESOLVED_PROC(PFN%sPROC)("%(name.upper()))
|
||||
|
||||
m3 = r4.search(funcname)
|
||||
if m3 :
|
||||
stringname = stringname.replace('NV','ARB')
|
||||
m4 = r5.search(funcname)
|
||||
if m4 :
|
||||
stringname = stringname.replace('NV','ARB')
|
||||
Comma=""
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s_"%(Comma, pname))
|
||||
Comma=", "
|
||||
self.outFile.write(" );\n}\n\n")
|
||||
|
||||
pfntypename = 'PFN' + funcname.upper() + 'PROC'
|
||||
class ThunkOutputGenerator(OutputGenerator):
|
||||
def __init__(self,
|
||||
errFile = sys.stderr,
|
||||
warnFile = sys.stderr,
|
||||
diagFile = sys.stdout):
|
||||
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
|
||||
def beginFile(self, genOpts):
|
||||
self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
|
||||
def endFile(self):
|
||||
pass
|
||||
def beginFeature(self, interface, emit):
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1')
|
||||
def endFeature(self):
|
||||
OutputGenerator.endFeature(self)
|
||||
def genType(self, typeinfo, name):
|
||||
OutputGenerator.genType(self, typeinfo, name)
|
||||
def genEnum(self, enuminfo, name):
|
||||
OutputGenerator.genEnum(self, enuminfo, name)
|
||||
def genCmd(self, cmd, name):
|
||||
OutputGenerator.genCmd(self, cmd, name)
|
||||
|
||||
if returntype.lower() == 'void' :
|
||||
print ' RESOLVE(' + pfntypename + ', "' + stringname + '");'
|
||||
print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");'
|
||||
print ' RESOLVED_PROC(' + pfntypename + ')(',
|
||||
else :
|
||||
print ' RESOLVE_RET(' + pfntypename + ', "' + stringname + '", FALSE);'
|
||||
print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");'
|
||||
print ' return RESOLVED_PROC(' + pfntypename + ')(',
|
||||
proto=noneStr(cmd.elem.find('proto'))
|
||||
rettype=noneStr(proto.text)
|
||||
if rettype.lower()!="void ":
|
||||
plist = ([t for t in proto.itertext()])
|
||||
rettype = ''.join(plist[:-1])
|
||||
rettype=rettype.strip()
|
||||
self.outFile.write("%s %sWrapper("%(rettype, name))
|
||||
params = cmd.elem.findall('param')
|
||||
plist=[]
|
||||
for param in params:
|
||||
paramlist = ([t for t in param.itertext()])
|
||||
paramtype = ''.join(paramlist[:-1])
|
||||
paramname = paramlist[-1]
|
||||
plist.append((paramtype, paramname))
|
||||
Comma=""
|
||||
if len(plist):
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s%s_"%(Comma, ptype, pname))
|
||||
Comma=", "
|
||||
else:
|
||||
self.outFile.write("void")
|
||||
|
||||
if arglist != 'void' :
|
||||
print wrappers[w]['arglist_use'],
|
||||
self.outFile.write(")\n{\n")
|
||||
|
||||
print ');'
|
||||
print "}\n"
|
||||
# for GL 1.0 and 1.1 functions, generate stdcall thunk wrappers which call the function directly
|
||||
if self.OldVersion:
|
||||
if rettype.lower()=="void":
|
||||
self.outFile.write(" %s( "%(name))
|
||||
else:
|
||||
self.outFile.write(" return %s( "%(name))
|
||||
|
||||
Comma=""
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s_"%(Comma, pname))
|
||||
Comma=", "
|
||||
|
||||
# for GL 1.2+ functions, generate wrappers which use wglGetProcAddress()
|
||||
else:
|
||||
if rettype.lower()=="void":
|
||||
self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
|
||||
self.outFile.write(" RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
|
||||
else:
|
||||
self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", FALSE);\n'%(name.upper(), name))
|
||||
self.outFile.write(" return RESOLVED_PROC(PFN%sPROC)("%(name.upper()))
|
||||
|
||||
Comma=""
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s_"%(Comma, pname))
|
||||
Comma=", "
|
||||
self.outFile.write(" );\n}\n\n")
|
||||
|
||||
class ThunkDefsOutputGenerator(OutputGenerator):
|
||||
def __init__(self,
|
||||
errFile = sys.stderr,
|
||||
warnFile = sys.stderr,
|
||||
diagFile = sys.stdout):
|
||||
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
|
||||
def beginFile(self, genOpts):
|
||||
self.outFile.write("EXPORTS\n"); # this must be the first line for libtool to realize this is a .def file
|
||||
self.outFile.write('; Automatically generated from %s - DO NOT EDIT\n\n'%regFilename)
|
||||
def endFile(self):
|
||||
pass
|
||||
def beginFeature(self, interface, emit):
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
def endFeature(self):
|
||||
OutputGenerator.endFeature(self)
|
||||
def genType(self, typeinfo, name):
|
||||
OutputGenerator.genType(self, typeinfo, name)
|
||||
def genEnum(self, enuminfo, name):
|
||||
OutputGenerator.genEnum(self, enuminfo, name)
|
||||
def genCmd(self, cmd, name):
|
||||
OutputGenerator.genCmd(self, cmd, name)
|
||||
|
||||
# export the wrapper function with the name of the function it wraps
|
||||
self.outFile.write("%s = %sWrapper\n"%(name, name))
|
||||
|
||||
class ShimOutputGenerator(OutputGenerator):
|
||||
def __init__(self,
|
||||
errFile = sys.stderr,
|
||||
warnFile = sys.stderr,
|
||||
diagFile = sys.stdout):
|
||||
OutputGenerator.__init__(self, errFile, warnFile, diagFile)
|
||||
def beginFile(self, genOpts):
|
||||
self.outFile.write('/* Automatically generated from %s - DO NOT EDIT */\n\n'%regFilename)
|
||||
def endFile(self):
|
||||
pass
|
||||
def beginFeature(self, interface, emit):
|
||||
OutputGenerator.beginFeature(self, interface, emit)
|
||||
self.OldVersion = self.featureName.startswith('GL_VERSION_1_0') or self.featureName.startswith('GL_VERSION_1_1') or self.featureName.startswith('GL_VERSION_1_2') or self.featureName.startswith('GL_ARB_imaging') or self.featureName.startswith('GL_ARB_multitexture') or self.featureName.startswith('GL_ARB_texture_compression')
|
||||
def endFeature(self):
|
||||
OutputGenerator.endFeature(self)
|
||||
def genType(self, typeinfo, name):
|
||||
OutputGenerator.genType(self, typeinfo, name)
|
||||
def genEnum(self, enuminfo, name):
|
||||
OutputGenerator.genEnum(self, enuminfo, name)
|
||||
def genCmd(self, cmd, name):
|
||||
OutputGenerator.genCmd(self, cmd, name)
|
||||
|
||||
if not self.OldVersion:
|
||||
return
|
||||
|
||||
# for GL functions which are in the ABI, generate a shim which calls the function via GetProcAddress
|
||||
proto=noneStr(cmd.elem.find('proto'))
|
||||
rettype=noneStr(proto.text)
|
||||
if rettype.lower()!="void ":
|
||||
plist = ([t for t in proto.itertext()])
|
||||
rettype = ''.join(plist[:-1])
|
||||
rettype=rettype.strip()
|
||||
self.outFile.write("%s %s("%(rettype, name))
|
||||
params = cmd.elem.findall('param')
|
||||
plist=[]
|
||||
for param in params:
|
||||
paramlist = ([t for t in param.itertext()])
|
||||
paramtype = ''.join(paramlist[:-1])
|
||||
paramname = paramlist[-1]
|
||||
plist.append((paramtype, paramname))
|
||||
Comma=""
|
||||
if len(plist):
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s%s_"%(Comma, ptype, pname))
|
||||
Comma=", "
|
||||
else:
|
||||
self.outFile.write("void")
|
||||
|
||||
self.outFile.write(")\n{\n")
|
||||
|
||||
self.outFile.write(' typedef %s (* PFN%sPROC)(' % (rettype, name.upper()))
|
||||
|
||||
if len(plist):
|
||||
Comma=""
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s %s %s_"%(Comma, ptype, pname))
|
||||
Comma=", "
|
||||
else:
|
||||
self.outFile.write("void")
|
||||
|
||||
self.outFile.write(');\n')
|
||||
|
||||
if rettype.lower()=="void":
|
||||
self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
|
||||
self.outFile.write(' RESOLVED_PROC(')
|
||||
else:
|
||||
self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", 0);\n'%(name.upper(), name))
|
||||
self.outFile.write(' return RESOLVED_PROC(')
|
||||
|
||||
Comma=""
|
||||
for ptype, pname in plist:
|
||||
self.outFile.write("%s%s_"%(Comma, pname))
|
||||
Comma=", "
|
||||
|
||||
self.outFile.write(" );\n}\n\n")
|
||||
|
||||
def genHeaders():
|
||||
outFile = open(outFilename,"w")
|
||||
|
||||
if preresolve:
|
||||
gen = PreResolveOutputGenerator(errFile=errWarn,
|
||||
warnFile=errWarn,
|
||||
diagFile=diag)
|
||||
gen.outFile=outFile
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
if wrapper:
|
||||
gen = WrapperOutputGenerator(errFile=errWarn,
|
||||
warnFile=errWarn,
|
||||
diagFile=diag)
|
||||
gen.outFile=outFile
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
if shim:
|
||||
gen = ShimOutputGenerator(errFile=errWarn,
|
||||
warnFile=errWarn,
|
||||
diagFile=diag)
|
||||
gen.outFile=outFile
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
if thunk:
|
||||
gen = ThunkOutputGenerator(errFile=errWarn,
|
||||
warnFile=errWarn,
|
||||
diagFile=diag)
|
||||
gen.outFile=outFile
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
|
||||
# generate function to setup the dispatch table, which sets each
|
||||
# dispatch table entry to point to it's wrapper function
|
||||
# (assuming we were able to make one)
|
||||
if thunkdefs:
|
||||
gen = ThunkDefsOutputGenerator(errFile=errWarn,
|
||||
warnFile=errWarn,
|
||||
diagFile=diag)
|
||||
gen.outFile=outFile
|
||||
reg.setGenerator(gen)
|
||||
reg.apiGen(genOpts)
|
||||
|
||||
if dispatchheader :
|
||||
print 'void glWinSetupDispatchTable(void)'
|
||||
print '{'
|
||||
print ' static struct _glapi_table *disp = NULL;'
|
||||
print ''
|
||||
print ' if (!disp)'
|
||||
print ' {'
|
||||
print ' disp = calloc(sizeof(void *), _glapi_get_dispatch_table_size());'
|
||||
print ' assert(disp);'
|
||||
outFile.close()
|
||||
|
||||
for d in sorted(dispatch.keys()) :
|
||||
if wrappers.has_key(d) :
|
||||
print ' SET_'+ d + '(disp, (void *)' + prefix + d + 'Wrapper);'
|
||||
else :
|
||||
print '#warning No wrapper for ' + prefix + d + ' !'
|
||||
|
||||
print ' }'
|
||||
print ''
|
||||
print ' _glapi_set_dispatch(disp);'
|
||||
print '}'
|
||||
genHeaders()
|
||||
|
|
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* File: glshim.c
|
||||
* Purpose: GL shim which redirects to a specified DLL
|
||||
*
|
||||
* Copyright (c) Jon TURNEY 2013
|
||||
*
|
||||
* 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 ABOVE LISTED COPYRIGHT HOLDER(S) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
A GL shim which redirects to a specified DLL
|
||||
|
||||
XWin is statically linked with this, rather than the system libGL, so that
|
||||
GL calls can be directed to mesa cygGL-1.dll, or cygnativeGLthunk.dll
|
||||
(which contains cdecl-to-stdcall thunks to the native openGL32.dll)
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XWIN_CONFIG_H
|
||||
#include <xwin-config.h>
|
||||
#endif
|
||||
|
||||
#define GL_GLEXT_LEGACY
|
||||
#include <GL/gl.h>
|
||||
#undef GL_ARB_imaging
|
||||
#undef GL_VERSION_1_3
|
||||
#include <GL/glext.h>
|
||||
|
||||
#include <X11/Xwindows.h>
|
||||
#include <os.h>
|
||||
#include "glwindows.h"
|
||||
#include <glx/glxserver.h>
|
||||
|
||||
static HMODULE hMod = NULL;
|
||||
|
||||
/*
|
||||
Implement the __glGetProcAddress function by just using GetProcAddress() on the selected DLL
|
||||
*/
|
||||
void *glXGetProcAddressARB(const char *symbol)
|
||||
{
|
||||
void *proc;
|
||||
|
||||
/* Default to the mesa GL implementation if one hasn't been selected yet */
|
||||
if (!hMod)
|
||||
glWinSelectImplementation(0);
|
||||
|
||||
proc = GetProcAddress(hMod, symbol);
|
||||
|
||||
if (glxWinDebugSettings.enableGLcallTrace)
|
||||
ErrorF("glXGetProcAddressARB: Resolved '%s' in %p to %p\n", symbol, hMod, proc);
|
||||
|
||||
return proc;
|
||||
}
|
||||
|
||||
/*
|
||||
Select a GL implementation DLL
|
||||
*/
|
||||
int glWinSelectImplementation(int native)
|
||||
{
|
||||
const char *dllname;
|
||||
|
||||
if (native) {
|
||||
dllname = "cygnativeGLthunk.dll";
|
||||
}
|
||||
else {
|
||||
dllname = "cygGL-1.dll";
|
||||
}
|
||||
|
||||
hMod = LoadLibraryEx(dllname, NULL, 0);
|
||||
if (hMod == NULL) {
|
||||
ErrorF("glWinSelectGLimplementation: Could not load '%s'\n", dllname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ErrorF("glWinSelectGLimplementation: Loaded '%s'\n", dllname);
|
||||
|
||||
/* Connect __glGetProcAddress() to our implementation of glXGetProcAddressARB() above */
|
||||
__glXsetGetProcAddress((glx_gpa_proc)glXGetProcAddressARB);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define RESOLVE_RET(proctype, symbol, retval) \
|
||||
proctype proc = (proctype)glXGetProcAddressARB(symbol); \
|
||||
if (proc == NULL) return retval;
|
||||
|
||||
#define RESOLVE(proctype, symbol) RESOLVE_RET(proctype, symbol,)
|
||||
#define RESOLVED_PROC proc
|
||||
|
||||
/* Include generated shims for direct linkage to GL functions which are in the ABI */
|
||||
#include "generated_gl_shim.c"
|
||||
|
||||
/*
|
||||
Special wrapper for glAddSwapHintRectWIN for copySubBuffers
|
||||
|
||||
Only used with native GL if the GL_WIN_swap_hint extension is present, so we enable
|
||||
GLX_MESA_copy_sub_buffer
|
||||
*/
|
||||
typedef void (__stdcall * PFNGLADDSWAPHINTRECTWIN) (GLint x, GLint y,
|
||||
GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
void
|
||||
glAddSwapHintRectWINWrapper(GLint x, GLint y, GLsizei width,
|
||||
GLsizei height)
|
||||
{
|
||||
RESOLVE(PFNGLADDSWAPHINTRECTWIN, "glAddSwapHintRectWIN");
|
||||
RESOLVED_PROC(x, y, width, height);
|
||||
}
|
|
@ -1,13 +1,8 @@
|
|||
/*
|
||||
* File: glwrap.c
|
||||
* Purpose: Wrapper functions for Win32 OpenGL functions
|
||||
*
|
||||
* Authors: Alexander Gottwald
|
||||
* Jon TURNEY
|
||||
*
|
||||
* Copyright (c) Jon TURNEY 2009
|
||||
* Copyright (c) Alexander Gottwald 2004
|
||||
* File: glthunk.c
|
||||
* Purpose: cdecl thunk wrapper library for Win32 stdcall OpenGL library
|
||||
*
|
||||
* Copyright (c) Jon TURNEY 2009,2013
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -37,34 +32,12 @@
|
|||
#endif
|
||||
|
||||
#include <X11/Xwindows.h>
|
||||
|
||||
#define GL_GLEXT_LEGACY
|
||||
#include <GL/gl.h>
|
||||
#undef GL_ARB_imaging
|
||||
#undef GL_VERSION_1_3
|
||||
#include <GL/glext.h>
|
||||
#include <glx/glxserver.h>
|
||||
#include <glx/glxext.h>
|
||||
#include <glx/glapi.h>
|
||||
#include <glx/dispatch.h>
|
||||
#include <glwindows.h>
|
||||
|
||||
static unsigned int glWinIndirectProcCalls = 0;
|
||||
static unsigned int glWinDirectProcCalls = 0;
|
||||
|
||||
void
|
||||
glWinCallDelta(void)
|
||||
{
|
||||
static unsigned int glWinIndirectProcCallsLast = 0;
|
||||
static unsigned int glWinDirectProcCallsLast = 0;
|
||||
|
||||
if ((glWinIndirectProcCalls != glWinIndirectProcCallsLast) ||
|
||||
(glWinDirectProcCalls != glWinDirectProcCallsLast)) {
|
||||
if (glxWinDebugSettings.enableTrace) {
|
||||
ErrorF("after %d direct and %d indirect GL calls\n",
|
||||
glWinDirectProcCalls - glWinDirectProcCallsLast,
|
||||
glWinIndirectProcCalls - glWinIndirectProcCallsLast);
|
||||
}
|
||||
glWinDirectProcCallsLast = glWinDirectProcCalls;
|
||||
glWinIndirectProcCallsLast = glWinIndirectProcCalls;
|
||||
}
|
||||
}
|
||||
|
||||
static PROC
|
||||
glWinResolveHelper(PROC * cache, const char *symbol)
|
||||
|
@ -75,11 +48,9 @@ glWinResolveHelper(PROC * cache, const char *symbol)
|
|||
if ((*cache) == NULL) {
|
||||
proc = wglGetProcAddress(symbol);
|
||||
if (proc == NULL) {
|
||||
ErrorF("glwrap: Can't resolve \"%s\"\n", symbol);
|
||||
(*cache) = (PROC) - 1;
|
||||
}
|
||||
else {
|
||||
ErrorF("glwrap: Resolved \"%s\"\n", symbol);
|
||||
(*cache) = proc;
|
||||
}
|
||||
}
|
||||
|
@ -99,10 +70,8 @@ glWinResolveHelper(PROC * cache, const char *symbol)
|
|||
static PROC cache = NULL; \
|
||||
__stdcall proctype proc = (proctype)glWinResolveHelper(&cache, symbol); \
|
||||
if (proc == NULL) { \
|
||||
__glXErrorCallBack(0); \
|
||||
return retval; \
|
||||
} \
|
||||
glWinIndirectProcCalls++;
|
||||
}
|
||||
|
||||
#define RESOLVE(proctype, symbol) RESOLVE_RET(proctype, symbol,)
|
||||
|
||||
|
@ -113,34 +82,6 @@ glWinResolveHelper(PROC * cache, const char *symbol)
|
|||
|
||||
OpenGL 1.2 and upward is treated as extensions, function address must
|
||||
found using wglGetProcAddress(), but also stdcall so still need wrappers...
|
||||
|
||||
Include generated dispatch table setup function
|
||||
*/
|
||||
|
||||
#include "generated_gl_wrappers.c"
|
||||
|
||||
/*
|
||||
Special non-static wrapper for glGetString for debug output
|
||||
*/
|
||||
|
||||
const GLubyte *
|
||||
glGetStringWrapperNonstatic(GLenum name)
|
||||
{
|
||||
return glGetString(name);
|
||||
}
|
||||
|
||||
/*
|
||||
Special non-static wrapper for glAddSwapHintRectWIN for copySubBuffers
|
||||
*/
|
||||
|
||||
typedef void (__stdcall * PFNGLADDSWAPHINTRECTWIN) (GLint x, GLint y,
|
||||
GLsizei width,
|
||||
GLsizei height);
|
||||
|
||||
void
|
||||
glAddSwapHintRectWINWrapperNonstatic(GLint x, GLint y, GLsizei width,
|
||||
GLsizei height)
|
||||
{
|
||||
RESOLVE(PFNGLADDSWAPHINTRECTWIN, "glAddSwapHintRectWIN");
|
||||
proc(x, y, width, height);
|
||||
}
|
||||
#include "generated_gl_thunks.c"
|
|
@ -42,12 +42,9 @@ typedef struct {
|
|||
|
||||
extern glxWinDebugSettingsRec glxWinDebugSettings;
|
||||
|
||||
void glWinCallDelta(void);
|
||||
void glxWinPushNativeProvider(void);
|
||||
const GLubyte *glGetStringWrapperNonstatic(GLenum name);
|
||||
void glAddSwapHintRectWINWrapperNonstatic(GLint x, GLint y, GLsizei width,
|
||||
GLsizei height);
|
||||
void glWinSetupDispatchTable(void);
|
||||
void glAddSwapHintRectWINWrapper(GLint x, GLint y, GLsizei width, GLsizei height);
|
||||
int glWinSelectImplementation(int native);
|
||||
|
||||
#if 1
|
||||
#define GLWIN_TRACE_MSG(msg, args...) if (glxWinDebugSettings.enableTrace) ErrorF(msg " [%s:%d]\n" , ##args , __FUNCTION__, __LINE__ )
|
||||
|
|
|
@ -550,7 +550,9 @@ glxWinScreenProbe(ScreenPtr pScreen)
|
|||
if (NULL == screen)
|
||||
return NULL;
|
||||
|
||||
/* Dump out some useful information about the native renderer */
|
||||
// Select the native GL implementation (WGL)
|
||||
if (glWinSelectImplementation(1))
|
||||
return NULL;
|
||||
|
||||
// create window class
|
||||
#define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest"
|
||||
|
@ -597,11 +599,12 @@ glxWinScreenProbe(ScreenPtr pScreen)
|
|||
// (but we need to have a current context for them to be resolvable)
|
||||
wglResolveExtensionProcs();
|
||||
|
||||
ErrorF("GL_VERSION: %s\n", glGetStringWrapperNonstatic(GL_VERSION));
|
||||
ErrorF("GL_VENDOR: %s\n", glGetStringWrapperNonstatic(GL_VENDOR));
|
||||
gl_renderer = (const char *) glGetStringWrapperNonstatic(GL_RENDERER);
|
||||
/* Dump out some useful information about the native renderer */
|
||||
ErrorF("GL_VERSION: %s\n", glGetString(GL_VERSION));
|
||||
ErrorF("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
|
||||
gl_renderer = (const char *) glGetString(GL_RENDERER);
|
||||
ErrorF("GL_RENDERER: %s\n", gl_renderer);
|
||||
gl_extensions = (const char *) glGetStringWrapperNonstatic(GL_EXTENSIONS);
|
||||
gl_extensions = (const char *) glGetString(GL_EXTENSIONS);
|
||||
wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
|
||||
if (!wgl_extensions)
|
||||
wgl_extensions = "";
|
||||
|
@ -615,7 +618,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
|
|||
free(screen);
|
||||
LogMessage(X_ERROR,
|
||||
"AIGLX: Won't use generic native renderer as it is not accelerated\n");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Can you see the problem here? The extensions string is DC specific
|
||||
|
@ -726,7 +729,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
|
|||
free(screen);
|
||||
LogMessage(X_ERROR,
|
||||
"AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n");
|
||||
return NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* These will be set by __glXScreenInit */
|
||||
|
@ -789,6 +792,13 @@ glxWinScreenProbe(ScreenPtr pScreen)
|
|||
pScreen->CopyWindow = glxWinCopyWindow;
|
||||
|
||||
return &screen->base;
|
||||
|
||||
error:
|
||||
// Something went wrong and we can't use the native GL implementation
|
||||
// so make sure the mesa GL implementation is selected instead
|
||||
glWinSelectImplementation(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
@ -910,7 +920,7 @@ static void
|
|||
glxWinDrawableCopySubBuffer(__GLXdrawable * drawable,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
glAddSwapHintRectWINWrapperNonstatic(x, y, w, h);
|
||||
glAddSwapHintRectWINWrapper(x, y, w, h);
|
||||
glxWinDrawableSwapBuffers(NULL, drawable);
|
||||
}
|
||||
|
||||
|
@ -1458,7 +1468,6 @@ glxWinContextMakeCurrent(__GLXcontext * base)
|
|||
|
||||
GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc,
|
||||
gc->ctx);
|
||||
glWinCallDelta();
|
||||
|
||||
/* Keep a note of the last active context in the drawable */
|
||||
drawPriv = gc->base.drawPriv;
|
||||
|
@ -1528,7 +1537,6 @@ glxWinContextLoseCurrent(__GLXcontext * base)
|
|||
|
||||
GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc,
|
||||
gc->ctx);
|
||||
glWinCallDelta();
|
||||
|
||||
/*
|
||||
An error seems to be reported if we try to make no context current
|
||||
|
@ -1623,8 +1631,6 @@ glxWinCreateContext(__GLXscreen * screen,
|
|||
context->ctx = NULL;
|
||||
context->shareContext = shareContext;
|
||||
|
||||
glWinSetupDispatchTable();
|
||||
|
||||
GLWIN_DEBUG_MSG("GLXcontext %p created", context);
|
||||
|
||||
return &(context->base);
|
||||
|
|
Loading…
Reference in New Issue