From: Markus R. <rol...@us...> - 2005-12-19 19:13:45
|
Update of /cvsroot/simspark/simspark/spark/utility/glextgen/script In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24814/glextgen/script Added Files: glbackend.rb glextension.rb glextgen.rb glfrontend.rb glmunger.rb Log Message: - added spark utility library --- NEW FILE: glmunger.rb --- # GLMunger # # The munger does some processing on the extension hashes before they go to the # backend. # This fixes: # - adds GL_VERSION_1_4 if it's not there # - adds GL_VERSION_1_3 if it's not there # - adds GL_VERSION_1_2 if it's not there # - fix ARB_imaging (move most functions from GL_VERSION_1_2 to ARB_imaging) # See http://www.opengl.org/developers/documentation/OpenGL12.html for more explanation # - throws away extensions which are natively supported require 'script/glextension.rb' module GLExtGen class GLMunger attr_accessor :nativeSupport def initialize (newNativeSupport) @nativeSupport = newNativeSupport end def processGL (extensionHash) # fix GL_VERSION_1_4 if extensionHash["GL_VERSION_1_4"] == nil extensionHash["GL_VERSION_1_4"] = GLExtension.new("GL_VERSION_1_4") end # fix GL_VERSION_1_3 if extensionHash["GL_VERSION_1_3"] == nil extensionHash["GL_VERSION_1_3"] = GLExtension.new("GL_VERSION_1_3") end # fix GL_VERSION_1_2 if extensionHash["GL_VERSION_1_2"] == nil extensionHash["GL_VERSION_1_2"] = GLExtension.new("GL_VERSION_1_2") end # fix ARB_imaging gl12 = extensionHash["GL_VERSION_1_2"] arbImaging = extensionHash["GL_ARB_imaging"] if gl12 != nil && arbImaging != nil # we move all functions from gl12 to arbImaging arbImaging.functionList.concat(gl12.functionList) gl12.functionList.clear arbImaging.functionList.delete("glDrawRangeElements") arbImaging.functionList.delete("glTexImage3D") arbImaging.functionList.delete("glTexSubImage3D") arbImaging.functionList.delete("glCopyTexSubImage3D") gl12.functionList.push("glDrawRangeElements") gl12.functionList.push("glTexImage3D") gl12.functionList.push("glTexSubImage3D") gl12.functionList.push("glCopyTexSubImage3D") end if nativeSupport != nil nativeSupport.each { |extensionName| print "Processing " + extensionName + " -> " if extensionHash[extensionName] != nil if extensionName.index("VERSION") != nil print "Clearing Functions\n" # for a GL_VERSION definition, we just throw away the functions extensionHash[extensionName].functionList.clear else print "Removing\n" # throw away the extension, as it is double defined extensionHash.delete(extensionName) end else print "No Action\n" end } end end def processWGL (extensionHash) end def processGLX (extensionHash) end end end --- NEW FILE: glextension.rb --- # the GLExtension class is used just for convenience. It manages a list of # functions which are associated with a particular extension. # Note: Not all extension have functions!! module GLExtGen class GLExtension attr_accessor :functionList, :name def initialize (newName) @functionList = [] @name = newName end def addFunction (function) @functionList.push(function) @functionList.uniq end def removePrefix i = @name.index('_') if i == 2 # we have a GL_ extension, watch out for the pesky 3DFX extension if @name[3] != "3"[0] @name[3..-1] else @name[2..-1] end else # we have a WGL_ or GLX_ extension @name[0..(i-1)].downcase + @name[i..-1] end end end end --- NEW FILE: glbackend.rb --- # GLBackEnd -*- mode: ruby; ruby-indent-level: 4 -*- # # This backend generates CPP code require 'script/glextension.rb' require 'script/glfrontend.rb' module GLExtGen class GLBackEnd def initialize end # generate output def generate(frontEnd, glArray, wglArray, glXArray) print "\n" generateHFile(frontEnd, glArray, wglArray, glXArray) generateCPPFile(frontEnd, glArray, wglArray, glXArray) end def writeMembers(frontEnd, file, array) array.each { |item| file.print "#line 22 \"utility/glextgen/script/glbackend.rb\"\n" file.print " bool m", item[1].name, ";\n" } end def writeFunctions(frontEnd, file, array) array.each { |item| file.print "#line 29 \"utility/glextgen/script/glbackend.rb\"\n" file.print " bool Has_", item[1].name, "() const { return mExtensions.m", item[1].name, "; }\n" } end def writeExternFunctionPointers(frontEnd, file, array) array.each { |item| if item[1].functionList.size != 0 file.print "#line 37 \"utility/glextgen/script/glbackend.rb\"\n" file.print "#ifdef ", item[0], "\n" item[1].functionList.each { |function| file.print "extern ", frontEnd.procize(function), " ", function, ";\n" } file.print "#endif //", item[0], "\n\n" end } end def writeStructFunctionPointers(frontEnd, file, array) array.each { |item| if item[1].functionList.size != 0 file.print "#line 50 \"utility/glextgen/script/glbackend.rb\"\n" file.print "#ifdef ", item[0], "\n" item[1].functionList.each { |function| file.print " ", frontEnd.procize(function), " fun_", function, ";\n" } file.print "#endif //", item[0], "\n\n" end } end def writeStructExtensions(frontEnd, file, array) array.each { |item| file.print "#line 62 \"utility/glextgen/script/glbackend.rb\"\n" file.print " bool m", item[1].name, ";\n" } end def copyFile(destFile, srcName) File.open(srcName, "r") { |srcFile| srcFile.each_line { |srcLine| destFile.print srcLine } } end def winGuardOn "#if defined(_WIN32)\n" end def winGuardOff "#endif //_WIN32\n" end def generateHFile(frontEnd, glArray, wglArray, glXArray) print "Generating 'glextensionreg.h'\n" File.open("glextensionreg.h", "w") { |f| copyFile(f, "tocopy/header_begin.txt") f.print "#line 87 \"utility/glextgen/script/glbackend.rb\"\n" if $namespace != nil f.print "\nnamespace ", $namespace, " {\n" end ### here we write out a struct with all possible function pointers f.print "struct GLExtGenFunctionPointers\n{\n" writeStructFunctionPointers(frontEnd, f, glArray) f.print "#line 94 \"utility/glextgen/script/glbackend.rb\"\n" f.print " ", winGuardOn writeStructFunctionPointers(frontEnd, f, wglArray) f.print "#line 94 \"utility/glextgen/script/glbackend.rb\"\n" f.print " ", winGuardOff f.print "};\n" ### here we write out all possible extensions f.print "struct GLExtGenExtensions\n{\n" writeStructExtensions(frontEnd, f, glArray) f.print "#line 105 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOn writeStructExtensions(frontEnd, f, wglArray) f.print "#line 108 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff f.print "};\n" f.print "\n" f.print "class GLExtensionReg\n" f.print "{\n" f.print "private:\n" f.print winGuardOn f.print " HDC mHDC;\n" f.print winGuardOff ### write out extension definitions for gl f.print " GLExtGenExtensions mExtensions;\n\n" f.print "public:\n" ### loop through all extensions writeFunctions(frontEnd, f, glArray) f.print "#line 119 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOn writeFunctions(frontEnd, f, wglArray) f.print "#line 123 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff f.print " GLExtensionReg();\n" f.print " ~GLExtensionReg();\n" f.print " void Init(GLExtGenFunctionPointers *funPtr = 0, GLExtGenExtensions *ext = 0);\n" f.printf" bool QueryGLExtension(const char *name);\n" f.print winGuardOn f.printf" bool QueryWGLExtension(const char *name);\n" f.print " HDC GetHDC() const { return mHDC; }\n" f.print " void SetHDC(HDC hdc){ mHDC = hdc; }\n" f.print winGuardOff f.print "};\n\n" if $namespace != nil f.print "} // end ", $namespace, "\n\n" end ### write out extern function pointer definitions writeExternFunctionPointers(frontEnd, f, glArray) f.print "#line 141 \"utility/glextgen/script/glbackend.rb\"\n" ### write out extern function pointer definitions for wgl with define-guard f.print winGuardOn writeExternFunctionPointers(frontEnd, f, wglArray) f.print "#line 146 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff copyFile(f, "tocopy/header_end.txt") } end def writeFunctionPointers(frontEnd, file, array) array.each { |item| if item[1].functionList.size != 0 file.print "#line 166 \"utility/glextgen/script/glbackend.rb\"\n" file.print "#ifdef ", item[0], "\n" item[1].functionList.each { |function| file.print "#line 169 \"utility/glextgen/script/glbackend.rb\"\n" file.print frontEnd.procize(function), " fun_", function, " = NULL;\n" } file.print "#endif //", item[0], "\n\n" end } end def writeInitMembers(frontEnd, file, array) array.each { |item| file.print "#line 178 \"utility/glextgen/script/glbackend.rb\"\n" file.print " mExtensions.m", item[0], " = false;\n" } end def writeLoadFunctions(frontEnd, file, array) array.each { |item| if item[0].index("extensions_string") == nil file.print "#line 186 \"utility/glextgen/script/glbackend.rb\"\n" file.print "static bool Load_", item[0], "(GLExtensionReg *reg)\n{\n" file.print "#ifdef ", item[0], "\n" # query for the extension, unless we are a GL_VERSION if item[0].index("VERSION") == nil if item[0].index("WGL") == nil file.print " if(reg->QueryGLExtension(\"", item[0], "\") == 0)\n" else if item[0].index("WGL_NV_vertex_array_range") == nil file.print " if(reg->QueryWGLExtension(\"", item[0], "\") == 0)\n" else file.print " if(reg->QueryGLExtension(\"GL_NV_vertex_array_range\") == 0)\n" end end file.print " return false;\n" end item[1].functionList.each { |function| file.print " GET_PROC_ADDRESS(", frontEnd.procize(function), ", fun_", function, ");\n" } file.print " return true;\n#endif //", item[0], "\n return false;\n}\n\n" end } end def writeCallLoadFunctions(frontEnd, file, array) array.each { |item| if item[0].index("extensions_string") == nil file.print "#line 213 \"utility/glextgen/script/glbackend.rb\"\n" if item[0].index("VERSION") != nil file.print " if (mExtensions.m", item[0], ") Load_", item[0], "(this);\n" else file.print " mExtensions.m", item[0], " = Load_", item[0], "(this);\n" end end } end def writeCopyFunctionPointers(frontEnd, file, array) array.each { |item| if item[1].functionList.size != 0 file.print "#line 226 \"utility/glextgen/script/glbackend.rb\"\n" file.print "#ifdef ", item[0], "\n" item[1].functionList.each { |function| file.print " funPtr->fun_", function, " = ", function, ";\n" } file.print "#endif //", item[0], "\n\n" end } end def generateCPPFile(frontEnd, glArray, wglArray, glXArray) print "Generating 'glextensionreg.cpp'\n" File.open("glextensionreg.cpp", "w") { |f| f.print "#line 241 \"utility/glextgen/script/glbackend.rb\"\n" f.print "#include \"glextensionreg.h\"\n"; if $namespace != nil f.print "using namespace ", $namespace, ";\n\n" end copyFile(f, "tocopy/cpp_begin.txt") ### create global function pointers writeFunctionPointers(frontEnd, f, glArray) f.print "#line 251 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOn writeFunctionPointers(frontEnd, f, wglArray) f.print "#line 254 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff ### create load functions writeLoadFunctions(frontEnd, f, glArray) f.print "#line 259 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOn writeLoadFunctions(frontEnd, f, wglArray) f.print "#line 262 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff + "\n" f.print "GLExtensionReg::GLExtensionReg()\n" f.print "{\n" f.print " memset(&mExtensions, 0, sizeof(GLExtGenExtensions));\n" f.print winGuardOn f.print " mHDC = NULL;\n" f.print winGuardOff f.print "}\n\n" f.print "GLExtensionReg::~GLExtensionReg()\n" f.print "{\n" f.print "}\n\n" f.print "void GLExtensionReg::Init(GLExtGenFunctionPointers *funPtr, GLExtGenExtensions *ext)\n" f.print "{\n" f.print " char *s = (char*) glGetString(GL_VERSION);\n\n" f.print " if (!s)\n" f.print " return;\n" f.print " s = strstr(s, \"1.\");\n" f.print " if (s != NULL)\n" f.print " {\n" f.print " if (s[2] >= '4')\n" f.print " mExtensions.mGL_VERSION_1_4 = true;\n" f.print " if (s[2] >= '3')\n" f.print " mExtensions.mGL_VERSION_1_3 = true;\n" f.print " if (s[2] >= '2')\n" f.print " mExtensions.mGL_VERSION_1_2 = true;\n" f.print " }\n\n" ### call load functions writeCallLoadFunctions(frontEnd, f, glArray) f.print "#line 296 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOn # here we do some special case processing for the wgl extension stuff f.print " wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC) GetProcedure(\"wglGetExtensionsStringARB\");\n" f.print " wglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC) GetProcedure(\"wglGetExtensionsStringEXT\");\n" f.print " mExtensions.mWGL_ARB_extensions_string = wglGetExtensionsStringARB != NULL;\n" f.print " mExtensions.mWGL_EXT_extensions_string = wglGetExtensionsStringEXT != NULL;\n\n" writeCallLoadFunctions(frontEnd, f, wglArray) f.print "#line 304 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff + "\n" f.print " if (ext)\n" f.print " memcpy(ext, &mExtensions, sizeof(GLExtGenExtensions));\n\n" f.print " if (funPtr)\n" f.print " {\n" writeCopyFunctionPointers(frontEnd, f, glArray) f.print "#line 313 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOn writeCopyFunctionPointers(frontEnd, f, wglArray) f.print "#line 316 \"utility/glextgen/script/glbackend.rb\"\n" f.print winGuardOff + "\n" f.print " }\n" f.print "}\n\n" } end end end --- NEW FILE: glfrontend.rb --- # GLFrontEnd -*- mode: ruby; ruby-indent-level: 4 -*- # # The front end is responsible for parsing the glext-header files require 'script/glextension.rb' module GLExtGen class GLFrontEnd attr_accessor :files def initialize @files = [] end # insert a tuple of scan arguments def addFile (fileName, extensionExp, functionExp, extensionHash) files.concat([[fileName, Regexp.new(extensionExp), Regexp.new(functionExp), extensionHash]]) end # scan the files registered def scanAll files.each { |item| print "Digesting '" + item[0] + "'...\n" scan(item[0], item[1], item[2], item[3]) } end def scan (fileName, extensionExp, functionExp, extensionHash) predefinedExp = Regexp.new("(.*)APIENTRY gl(.*) \\((.*)"); currentExtension = nil File.open(fileName).each { |line| if line =~ /^(\s*)(\/+)(.*) (gl\w+)/ print "removing misleading line ", line elsif md = predefinedExp.match(line) print "predefined fct gl", md[2], ":\n" elsif md = extensionExp.match(line) extensionName = md[2] currentExtension = extensionHash[extensionName] # if we don't know the extension, we have to add it if currentExtension == nil currentExtension = GLExtension.new(extensionName) extensionHash[extensionName] = currentExtension end # at this point currentExtension has a valid # GLExtension object ... always! elsif md = functionExp.match(line) # add the function name to the current Extension functionName = md[2] if currentExtension != nil currentExtension.addFunction(functionName) end end } end def procize (functionName) "PFN"+functionName.upcase+"PROC" end end end --- NEW FILE: glextgen.rb --- # GLExtGen: # # GLExtGen is a Ruby script which is capable of extracting OpenGL extension # data from header files and generate files for inclusion in OpenGL projects. # # GLExtGen works using a front-end and a back-end. The front-end is responsible # for analyzing the header files and building an intermediate representation. # The backend is then responsible for writing out that information in a way that # the target language can understand it. This design allows different backends # (say for PASCAL/Delphi) to be generated without having to rewrite lots of # code. Unfortunately, this separation is not as good as it could be. For example, # GLBackEnd is really not designed to be derived from. It should be more of an # interface, than an actual implementation. Nevertheless, it works quite well for # C++. If you want something else, I suggest just changing the code in GLBackEnd # perform error checking on config parameters begin if $target != "win32" && $target != "x" raise "Incorrect target specification" end if $path[-1] != '/'[0] && $path[-1] != '\\'[0] $path += '/' print "WARNING: No trailing slash in path ... adjusting\n" print "WARNING: New path is '", $path, "'\n" end require 'script/glextension.rb' require 'script/glfrontend.rb' require 'script/glmunger.rb' require 'script/glbackend.rb' # here we choose the classes we will use frontEndClass = GLExtGen::GLFrontEnd mungerClass = GLExtGen::GLMunger backEndClass = GLExtGen::GLBackEnd # we will use these hash tables to hold string => GLExtension pairs glExtensionHash = {} wglExtensionHash = {} glXExtensionHash = {} # create our front end frontEnd = frontEndClass.new # queue up some jobs to scan frontEnd.addFile($path+"glext.h", '(#ifndef) (GL_\w+)', '(.+) (gl\w+)', glExtensionHash) if $target == "win32" frontEnd.addFile($path+"wglext.h", '(#ifndef) (WGL_\w+)', '(.+) (wgl\w+)', wglExtensionHash) end if $target == "x" frontEnd.addFile($path+"glxext.h", '(#ifndef) (GLX_\w+)', '(.+) (glX\w+)', glXExtensionHash) end # let's work it frontEnd.scanAll # now, for the MS-Windows world, this is fine, but other OpenGL implementations (such as Mesa) # already define some of the symbols, as their GL/gl.h implements version 1.2 and not 1.1 (as # the Windows header). So, what we do is, we analyze the regular gl-header file. extensionExp = Regexp.new('(#ifndef) (GL_\w+)') versionExp = Regexp.new('(#define) (GL_VERSION\w+)') glNativeSupportArray = [] print "\nSearching for native extensions in '"+$path+"gl.h\n" File.open($path+"gl.h").each { |line| if md = extensionExp.match(line) glNativeSupportArray.push(md[2]); print "Found extension: " + md[2] + "\n" elsif md = versionExp.match(line) glNativeSupportArray.push(md[2]); print "Found version: " + md[2] + "\n" end } # before we pass this data to the backend we get a chance to transform it. munger = mungerClass.new(glNativeSupportArray) munger.processGL(glExtensionHash) munger.processWGL(wglExtensionHash) munger.processGLX(glXExtensionHash) # at this point the extension hashes contain valid data (let's cross our fingers) # now we have done all our processing and sort the extensions glExtensionArray = glExtensionHash.sort wglExtensionArray = wglExtensionHash.sort glXExtensionArray = glXExtensionHash.sort # create back end backEnd = backEndClass.new # glExtensionArray.each { |item| # item[1].functionList.each { |func| # print "debug output: " + func + "\n" # } # } # now, we just hand our extension arrays over to the backend # # Note: we are also passing in the frontEnd, because it should contain information # on how to 'procize' a function (generate function pointer typedef given a # function name) backEnd.generate(frontEnd, glExtensionArray, wglExtensionArray, glXExtensionArray) rescue StandardError => bang print "ERROR: ", bang, "\n" end |