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:
Jon TURNEY 2012-09-27 18:59:45 +01:00
parent cb48877a3c
commit 9a4d7572fe
8 changed files with 636 additions and 382 deletions

View File

@ -2109,7 +2109,7 @@ if test "x$XWIN" = xyes; then
esac 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_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_LIBS)
AC_SUBST(XWIN_SERVER_NAME) AC_SUBST(XWIN_SERVER_NAME)
AC_SUBST(XWIN_SYS_LIBS) 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 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 if [test "x$XWIN" = xyes && test "x$AIGLX" = xyes] ; then
AC_CHECK_PROG(PYTHON, python, python) AC_CHECK_PROG(PYTHON3, python3, python3)
if test -z "$PYTHON"; then if test -z "$PYTHON3"; then
AC_MSG_ERROR([python not found]) AC_MSG_ERROR([python3 not found])
fi 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 if test "x$KHRONOS_SPEC_DIR" = "xauto" ; then
PKG_CHECK_MODULES([KHRONOS_OPENGL_REGISTRY], [khronos-opengl-registry]) PKG_CHECK_MODULES([KHRONOS_OPENGL_REGISTRY], [khronos-opengl-registry])
KHRONOS_SPEC_DIR=`pkg-config khronos-opengl-registry --variable=specdir` KHRONOS_SPEC_DIR=`pkg-config khronos-opengl-registry --variable=specdir`

View File

@ -157,7 +157,7 @@ XWIN_LIBS += $(top_builddir)/pseudoramiX/libPseudoramiX.la
XWin_DEPENDENCIES = $(MULTIWINDOWEXTWM_LIBS) $(XWIN_GLX_LIBS) $(XWIN_LIBS) $(XSERVER_LIBS) 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_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: .rc.o:
$(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include $(AM_V_GEN)$(WINDRES) --use-temp-file -i $< --input-format=rc -o $@ -O coff -I $(top_builddir)/include

View File

@ -1,14 +1,18 @@
noinst_LTLIBRARIES = libXwinGLX.la noinst_LTLIBRARIES = libXwinGLX.la
lib_LTLIBRARIES = libnativeGLthunk.la
libXwinGLX_la_SOURCES = \ libXwinGLX_la_SOURCES = \
winpriv.c \ winpriv.c \
winpriv.h \ winpriv.h \
glwindows.h \ glwindows.h \
glwrap.c \ glshim.c \
indirect.c \ indirect.c \
wgl_ext_api.c \ wgl_ext_api.c \
wgl_ext_api.h wgl_ext_api.h
libnativeGLthunk_la_SOURCES = \
glthunk.c
if XWIN_MULTIWINDOW if XWIN_MULTIWINDOW
DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW DEFS_MULTIWINDOW = -DXWIN_MULTIWINDOW
endif endif
@ -30,16 +34,32 @@ AM_CFLAGS = -DHAVE_XWIN_CONFIG_H $(DIX_CFLAGS) \
-I$(top_srcdir) \ -I$(top_srcdir) \
-I$(top_srcdir)/hw/xwin/ -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 if XWIN_GLX_WINDOWS
generated_gl_wrappers.c: gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/gl.spec $(KHRONOS_SPEC_DIR)/gl.tm if DEBUG
$(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 GENGLWRAPPERSOPTS=""
else
generated_wgl_wrappers.c: gen_gl_wrappers.py $(KHRONOS_SPEC_DIR)/wglext.spec $(KHRONOS_SPEC_DIR)/wgl.tm GENGLWRAPPERSOPTS="-nodebug"
$(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
endif 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) CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = gen_gl_wrappers.py EXTRA_DIST = gen_gl_wrappers.py

View File

@ -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 # Copyright (c) 2013 The Khronos Group Inc.
# http://www.opengl.org/registry/api/
#
#
# Copyright (c) Jon TURNEY 2009
# #
# Permission is hereby granted, free of charge, to any person obtaining a # Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"), # copy of this software and/or associated documentation files (the
# to deal in the Software without restriction, including without limitation # "Materials"), to deal in the Materials without restriction, including
# the rights to use, copy, modify, merge, publish, distribute, sublicense, # without limitation the rights to use, copy, modify, merge, publish,
# and/or sell copies of the Software, and to permit persons to whom the # distribute, sublicense, and/or sell copies of the Materials, and to
# Software is furnished to do so, subject to the following conditions: # 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 # The above copyright notice and this permission notice shall be included
# all copies or substantial portions of the Software. # in all copies or substantial portions of the Materials.
#
# 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 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 sys, time, pdb, string, cProfile
import re from reg import *
import getopt
dispatchheader = '' # Default input / log files
prefix = 'gl' errFilename = None
preresolve = False diagFilename = 'diag.txt'
staticwrappers = False 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: #exclude base WGL API
if o == '--typemap' : WinGDI={key: 1 for key in [
typemapfile = a "wglCopyContext"
elif o == '--dispatch-header' : ,"wglCreateContext"
dispatchheader = a ,"wglCreateLayerContext"
elif o == '--spec' : ,"wglDeleteContext"
specfile = a ,"wglGetCurrentContext"
elif o == '--prefix' : ,"wglGetCurrentDC"
prefix = a ,"wglGetProcAddress"
elif o == '--preresolve' : ,"wglMakeCurrent"
preresolve = True ,"wglShareLists"
elif o == '--staticwrappers' : ,"wglUseFontBitmapsA"
staticwrappers = True ,"wglUseFontBitmapsW"
,"wglUseFontBitmaps"
,"SwapBuffers"
,"wglUseFontOutlinesA"
,"wglUseFontOutlinesW"
,"wglUseFontOutlines"
,"wglDescribeLayerPlane"
,"wglSetLayerPaletteEntries"
,"wglGetLayerPaletteEntries"
,"wglRealizeLayerPalette"
,"wglSwapLayerBuffers"
,"wglSwapMultipleBuffers"
,"ChoosePixelFormat"
,"DescribePixelFormat"
,"GetEnhMetaFilePixelFormat"
,"GetPixelFormat"
,"SetPixelFormat"
]}
# if __name__ == '__main__':
# look for all the SET_ macros in dispatch.h, this is the set of functions i = 1
# we need to generate 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 : # Load & parse registry
fh = open(dispatchheader) reg = Registry()
dispatchh = fh.readlines() tree = etree.parse(regFilename)
reg.loadElementTree(tree)
dispatch_regex = re.compile(r'^SET_(\S*)\(') allVersions = '.*'
for line in dispatchh : genOpts = CGeneratorOptions(
line = line.strip() apiname = prefix,
m1 = dispatch_regex.search(line) profile = 'compatibility',
versions = allVersions,
emitversions = allVersions,
defaultExtensions = prefix, # Default extensions for GL
protectFile = protect,
protectFeature = protect,
protectProto = protect,
)
if m1 : # create error/warning & diagnostic files
dispatch[m1.group(1)] = 1 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)
# if name in WinGDI:
# read the typemap .tm file return
#
typemap = {} self.outFile.write('RESOLVE_DECL(PFN' + name.upper() + 'PROC);\n')
self.wrappers[name]=1
fh = open(typemapfile) class WrapperOutputGenerator(OutputGenerator):
tm = fh.readlines() 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 : proto=noneStr(cmd.elem.find('proto'))
# ignore everything after a '#' as a comment rettype=noneStr(proto.text)
hash = line.find('#') if rettype.lower()!="void ":
if hash != -1 : plist = ([t for t in proto.itertext()])
line = line[:hash-1] rettype = ''.join(plist[:-1])
rettype=rettype.strip()
# ignore blank lines if staticwrappers: self.outFile.write("static ")
if line.startswith('#') or len(line) == 0 : self.outFile.write("%s %sWrapper("%(rettype, name))
continue params = cmd.elem.findall('param')
plist=[]
l = line.split(',') for param in params:
typemap[l[0]] = l[3].strip() paramlist = ([t for t in param.itertext()])
paramtype = ''.join(paramlist[:-1])
# interestingly, * is not a C type paramname = paramlist[-1]
if typemap['void'] == '*' : plist.append((paramtype, paramname))
typemap['void'] = 'void' Comma=""
if len(plist):
# for ptype, pname in plist:
# crudely parse the .spec file self.outFile.write("%s%s%s_"%(Comma, ptype, pname))
# Comma=", "
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'
else: else:
arglist = ', '.join(al) self.outFile.write("void")
if wrappers[w]['category'].startswith('VERSION_1_0') or wrappers[w]['category'].startswith('VERSION_1_1') : self.outFile.write(")\n{\n")
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 + '(',
if arglist != 'void' : # for GL 1.0 and 1.1 functions, generate stdcall wrappers which call the function directly
print wrappers[w]['arglist_use'], 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 ');' if rettype.lower()=="void":
print "}\n" 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: else:
if staticwrappers : if rettype.lower()=="void":
print 'static', self.outFile.write(' RESOLVE(PFN%sPROC, "%s");\n'%(name.upper(), name))
print returntype + ' ' + funcname + 'Wrapper(' + arglist + ')'
print '{'
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")
# self.outFile.write(" RESOLVED_PROC(PFN%sPROC)( """%(name.upper()))
# special case: Windows OpenGL implementations are far more likely to have GL_ARB_window_pos than GL_MESA_window_pos, else:
# so arrange for the wrapper to use the ARB strings to find functions... self.outFile.write(' RESOLVE_RET(PFN%sPROC, "%s", FALSE);\n'%(name.upper(), name))
#
m2 = r3.search(funcname) if not nodebug:
if m2 : self.outFile.write("\n")
stringname = stringname.replace('MESA','ARB') self.outFile.write(' if (glxWinDebugSettings.enable%scallTrace) ErrorF("%s\\n");\n'%(prefix.upper(), name))
self.outFile.write("\n")
# self.outFile.write(" return RESOLVED_PROC(PFN%sPROC)("%(name.upper()))
# 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
#
m3 = r4.search(funcname) Comma=""
if m3 : for ptype, pname in plist:
stringname = stringname.replace('NV','ARB') self.outFile.write("%s%s_"%(Comma, pname))
m4 = r5.search(funcname) Comma=", "
if m4 : self.outFile.write(" );\n}\n\n")
stringname = stringname.replace('NV','ARB')
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' : proto=noneStr(cmd.elem.find('proto'))
print ' RESOLVE(' + pfntypename + ', "' + stringname + '");' rettype=noneStr(proto.text)
print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");' if rettype.lower()!="void ":
print ' RESOLVED_PROC(' + pfntypename + ')(', plist = ([t for t in proto.itertext()])
else : rettype = ''.join(plist[:-1])
print ' RESOLVE_RET(' + pfntypename + ', "' + stringname + '", FALSE);' rettype=rettype.strip()
print ' if (glxWinDebugSettings.enable' + prefix.upper() + 'callTrace) ErrorF("'+ funcname + '\\n");' self.outFile.write("%s %sWrapper("%(rettype, name))
print ' return RESOLVED_PROC(' + pfntypename + ')(', 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' : self.outFile.write(")\n{\n")
print wrappers[w]['arglist_use'],
print ');' # for GL 1.0 and 1.1 functions, generate stdcall thunk wrappers which call the function directly
print "}\n" 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 if thunkdefs:
# dispatch table entry to point to it's wrapper function gen = ThunkDefsOutputGenerator(errFile=errWarn,
# (assuming we were able to make one) warnFile=errWarn,
diagFile=diag)
gen.outFile=outFile
reg.setGenerator(gen)
reg.apiGen(genOpts)
if dispatchheader : outFile.close()
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);'
for d in sorted(dispatch.keys()) : genHeaders()
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 '}'

124
hw/xwin/glx/glshim.c Normal file
View File

@ -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);
}

View File

@ -1,13 +1,8 @@
/* /*
* File: glwrap.c * File: glthunk.c
* Purpose: Wrapper functions for Win32 OpenGL functions * Purpose: cdecl thunk wrapper library for Win32 stdcall OpenGL library
*
* Authors: Alexander Gottwald
* Jon TURNEY
*
* Copyright (c) Jon TURNEY 2009
* Copyright (c) Alexander Gottwald 2004
* *
* Copyright (c) Jon TURNEY 2009,2013
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
@ -37,34 +32,12 @@
#endif #endif
#include <X11/Xwindows.h> #include <X11/Xwindows.h>
#define GL_GLEXT_LEGACY
#include <GL/gl.h> #include <GL/gl.h>
#undef GL_ARB_imaging
#undef GL_VERSION_1_3
#include <GL/glext.h> #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 static PROC
glWinResolveHelper(PROC * cache, const char *symbol) glWinResolveHelper(PROC * cache, const char *symbol)
@ -75,11 +48,9 @@ glWinResolveHelper(PROC * cache, const char *symbol)
if ((*cache) == NULL) { if ((*cache) == NULL) {
proc = wglGetProcAddress(symbol); proc = wglGetProcAddress(symbol);
if (proc == NULL) { if (proc == NULL) {
ErrorF("glwrap: Can't resolve \"%s\"\n", symbol);
(*cache) = (PROC) - 1; (*cache) = (PROC) - 1;
} }
else { else {
ErrorF("glwrap: Resolved \"%s\"\n", symbol);
(*cache) = proc; (*cache) = proc;
} }
} }
@ -99,10 +70,8 @@ glWinResolveHelper(PROC * cache, const char *symbol)
static PROC cache = NULL; \ static PROC cache = NULL; \
__stdcall proctype proc = (proctype)glWinResolveHelper(&cache, symbol); \ __stdcall proctype proc = (proctype)glWinResolveHelper(&cache, symbol); \
if (proc == NULL) { \ if (proc == NULL) { \
__glXErrorCallBack(0); \
return retval; \ return retval; \
} \ }
glWinIndirectProcCalls++;
#define RESOLVE(proctype, symbol) RESOLVE_RET(proctype, symbol,) #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 OpenGL 1.2 and upward is treated as extensions, function address must
found using wglGetProcAddress(), but also stdcall so still need wrappers... found using wglGetProcAddress(), but also stdcall so still need wrappers...
Include generated dispatch table setup function
*/ */
#include "generated_gl_wrappers.c" #include "generated_gl_thunks.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);
}

View File

@ -42,12 +42,9 @@ typedef struct {
extern glxWinDebugSettingsRec glxWinDebugSettings; extern glxWinDebugSettingsRec glxWinDebugSettings;
void glWinCallDelta(void);
void glxWinPushNativeProvider(void); void glxWinPushNativeProvider(void);
const GLubyte *glGetStringWrapperNonstatic(GLenum name); void glAddSwapHintRectWINWrapper(GLint x, GLint y, GLsizei width, GLsizei height);
void glAddSwapHintRectWINWrapperNonstatic(GLint x, GLint y, GLsizei width, int glWinSelectImplementation(int native);
GLsizei height);
void glWinSetupDispatchTable(void);
#if 1 #if 1
#define GLWIN_TRACE_MSG(msg, args...) if (glxWinDebugSettings.enableTrace) ErrorF(msg " [%s:%d]\n" , ##args , __FUNCTION__, __LINE__ ) #define GLWIN_TRACE_MSG(msg, args...) if (glxWinDebugSettings.enableTrace) ErrorF(msg " [%s:%d]\n" , ##args , __FUNCTION__, __LINE__ )

View File

@ -550,7 +550,9 @@ glxWinScreenProbe(ScreenPtr pScreen)
if (NULL == screen) if (NULL == screen)
return NULL; 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 // create window class
#define WIN_GL_TEST_WINDOW_CLASS "XWinGLTest" #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) // (but we need to have a current context for them to be resolvable)
wglResolveExtensionProcs(); wglResolveExtensionProcs();
ErrorF("GL_VERSION: %s\n", glGetStringWrapperNonstatic(GL_VERSION)); /* Dump out some useful information about the native renderer */
ErrorF("GL_VENDOR: %s\n", glGetStringWrapperNonstatic(GL_VENDOR)); ErrorF("GL_VERSION: %s\n", glGetString(GL_VERSION));
gl_renderer = (const char *) glGetStringWrapperNonstatic(GL_RENDERER); ErrorF("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
gl_renderer = (const char *) glGetString(GL_RENDERER);
ErrorF("GL_RENDERER: %s\n", 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); wgl_extensions = wglGetExtensionsStringARBWrapper(hdc);
if (!wgl_extensions) if (!wgl_extensions)
wgl_extensions = ""; wgl_extensions = "";
@ -615,7 +618,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
free(screen); free(screen);
LogMessage(X_ERROR, LogMessage(X_ERROR,
"AIGLX: Won't use generic native renderer as it is not accelerated\n"); "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 // Can you see the problem here? The extensions string is DC specific
@ -726,7 +729,7 @@ glxWinScreenProbe(ScreenPtr pScreen)
free(screen); free(screen);
LogMessage(X_ERROR, LogMessage(X_ERROR,
"AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n"); "AIGLX: No fbConfigs could be made from native OpenGL pixel formats\n");
return NULL; goto error;
} }
/* These will be set by __glXScreenInit */ /* These will be set by __glXScreenInit */
@ -789,6 +792,13 @@ glxWinScreenProbe(ScreenPtr pScreen)
pScreen->CopyWindow = glxWinCopyWindow; pScreen->CopyWindow = glxWinCopyWindow;
return &screen->base; 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, glxWinDrawableCopySubBuffer(__GLXdrawable * drawable,
int x, int y, int w, int h) int x, int y, int w, int h)
{ {
glAddSwapHintRectWINWrapperNonstatic(x, y, w, h); glAddSwapHintRectWINWrapper(x, y, w, h);
glxWinDrawableSwapBuffers(NULL, drawable); glxWinDrawableSwapBuffers(NULL, drawable);
} }
@ -1458,7 +1468,6 @@ glxWinContextMakeCurrent(__GLXcontext * base)
GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc, GLWIN_TRACE_MSG("glxWinContextMakeCurrent context %p (native ctx %p)", gc,
gc->ctx); gc->ctx);
glWinCallDelta();
/* Keep a note of the last active context in the drawable */ /* Keep a note of the last active context in the drawable */
drawPriv = gc->base.drawPriv; drawPriv = gc->base.drawPriv;
@ -1528,7 +1537,6 @@ glxWinContextLoseCurrent(__GLXcontext * base)
GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc, GLWIN_TRACE_MSG("glxWinContextLoseCurrent context %p (native ctx %p)", gc,
gc->ctx); gc->ctx);
glWinCallDelta();
/* /*
An error seems to be reported if we try to make no context current 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->ctx = NULL;
context->shareContext = shareContext; context->shareContext = shareContext;
glWinSetupDispatchTable();
GLWIN_DEBUG_MSG("GLXcontext %p created", context); GLWIN_DEBUG_MSG("GLXcontext %p created", context);
return &(context->base); return &(context->base);