diff --git a/gen_from_xml.rb b/gen_from_xml.rb index 6c897ce..9ab0450 100755 --- a/gen_from_xml.rb +++ b/gen_from_xml.rb @@ -4,17 +4,20 @@ require 'open-uri' require 'fiddle' -KHRONOS_GL_XML = 'https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml' - -if !File.exist?('gl.xml') - puts "gl.xml doesn't exist: downloading <#{KHRONOS_GL_XML}>..." - curl_pid = Process.spawn("curl --output 'gl.xml' '#{KHRONOS_GL_XML}'") - Process.wait(curl_pid) - if !$?.exited? || !$?.success? - puts "Download failed. Try again." - exit 1 +KHRONOS_GL_XMLS = ['gl.xml','glx.xml','wgl.xml'] +KHRONOS_GL_XML_PATH = 'https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/' + +KHRONOS_GL_XMLS.each do |filename| + if !File.exist?(filename) + puts "#{filename} doesn't exist: downloading <#{KHRONOS_GL_XML_PATH}#{filename}>..." + curl_pid = Process.spawn("curl --output '#{filename}' '#{KHRONOS_GL_XML_PATH}#{filename}'") + Process.wait(curl_pid) + if !$?.exited? || !$?.success? + puts "Download failed. Try again." + exit 1 + end + puts "Download complete." end - puts "Download complete." end # name => String @@ -122,13 +125,13 @@ def generate_binding_impl(document) } extensions = document.xpath("registry/extensions/extension") - core_exts = extensions.select { |ext| ext['supported'] =~ /\bglcore\b/ } + core_exts = extensions.select { |ext| ext['supported'] =~ /\bglcore\b/ || ext['supported'] =~ /\bglx\b/ || ext['supported'] =~ /\bwgl\b/ } core_exts.each { |ext| ext.xpath('extension/require/*[(self::command|self::enum)]').each(&pull_feature) } features = document.xpath('registry/feature') - gl_features = features.select { |feature| feature['api'] =~ /\bgl\b/ } + gl_features = features.select { |feature| feature['api'] =~ /\bgl\b/ || feature['api'] =~ /\bglx\b/ || feature['api'] =~ /\bwgl\b/ } gl_features.each { |feature| feature.xpath('require/*[(self::command|self::enum)]').each(&pull_feature) if GEN_GL3_AND_UP @@ -230,7 +233,7 @@ def #{name}__(#{param_string}) # Read gl.xml -document_paths = [ 'gl.xml' ] +document_paths = [ 'gl.xml', 'glx.xml', 'wgl.xml' ] document_paths.each { |path| diff --git a/lib/opengl-core.rb b/lib/opengl-core.rb index abf5782..a75c85f 100644 --- a/lib/opengl-core.rb +++ b/lib/opengl-core.rb @@ -11,6 +11,10 @@ require 'opengl-core/gl-sym' require 'opengl-core/gl-enums' require 'opengl-core/gl-commands' +require 'opengl-core/glx-enums' +require 'opengl-core/glx-commands' +require 'opengl-core/wgl-enums' +require 'opengl-core/wgl-commands' module GL diff --git a/lib/opengl-core/gl-sym.rb b/lib/opengl-core/gl-sym.rb index a389e03..e4a40ed 100644 --- a/lib/opengl-core/gl-sym.rb +++ b/lib/opengl-core/gl-sym.rb @@ -51,7 +51,10 @@ def load_sym(name) symfunc = self.loader.load_sym(name, GL_COMMAND_TYPES[name]) if symfunc.nil? - raise NoMethodError, "GL function #{name} could not be loaded" + symfunc = self.loader.load_ext_sym(name, GL_COMMAND_TYPES[name]) + if symfunc.ptr.to_i > -2 && symfunc.ptr.to_i < 5 + raise NoMethodError, "GL function #{name} could not be loaded" + end end symfunc diff --git a/lib/opengl-core/gl-sym/fiddle-symbol-loader.rb b/lib/opengl-core/gl-sym/fiddle-symbol-loader.rb index 50f5784..b7213fc 100644 --- a/lib/opengl-core/gl-sym/fiddle-symbol-loader.rb +++ b/lib/opengl-core/gl-sym/fiddle-symbol-loader.rb @@ -8,14 +8,18 @@ require 'fiddle' +require 'fiddle/import' +require 'fiddle/types' require 'rbconfig' - module GL module GLSym -class FiddleSymbolLoader +class SymLoaderHash + extend Fiddle::Importer + @type_alias = {} + include Fiddle::Win32Types TYPE_MAPPINGS = { :'void' => Fiddle::TYPE_VOID, @@ -56,25 +60,35 @@ class FiddleSymbolLoader :'GLDEBUGPROCARB' => Fiddle::TYPE_VOIDP, :'GLDEBUGPROCKHR' => Fiddle::TYPE_VOIDP, :'GLDEBUGPROCAMD' => Fiddle::TYPE_VOIDP, - } - TYPE_MAPPINGS.default_proc = -> (hash, key) do - if key.to_s.end_with?('*') - hash[key] = Fiddle::TYPE_VOIDP - else - raise ArgumentError, "No type mapping defined for #{key}" + :'PROC' => Fiddle::TYPE_VOIDP, + :'HGLRC' => Fiddle::TYPE_VOIDP + } + def self.[](key) + if TYPE_MAPPINGS.has_key?(key) + TYPE_MAPPINGS[key] + elsif key.to_s.end_with?('*') + TYPE_MAPPINGS[key] = Fiddle::TYPE_VOIDP + else + TYPE_MAPPINGS[key] = SymLoaderHash.parse_ctype key.to_s, @type_alias #parse_ctype Raises an error on "unsupported type" + end end - end + def self.[]=(key, val) + TYPE_MAPPINGS[key] = val + end +end +class FiddleSymbolLoader def fiddle_typed(types) case types when Array then types.map { |i| fiddle_typed(i) } - else TYPE_MAPPINGS[types.to_sym] + else SymLoaderHash[types.to_sym] end end def initialize - @opengl_lib = nil + @opengl_lib = Fiddle::dlopen('opengl32.dll') + @glGetProcAddress = nil @loaded = {} end @@ -93,7 +107,7 @@ def unload # GL_COMMAND_TYPES. The returned value is cached in GL_COMMAND_FUNCTIONS and # returned if load_sym is called for the same name again. def load_sym(name, types) - if @opengl_lib.nil? + if @opengl_lib.nil? || @glGetProcAddress.nil? # Platform detection based on code by Thomas Enebo, written for this # Stack Overflow answer: http://stackoverflow.com/a/13586108/457812. As # such, this particular bit of code is also available under the same @@ -113,7 +127,27 @@ def load_sym(name, types) raise 'Unrecognized platform' end + getProcAddressName = + case host + when %r[ mac\sos | darwin ]ix + :aglGetProcAddress + when %r[ mswin | msys | mingw | cygwin | bcwin | wince | emc ]ix + :wglGetProcAddress + when %r[ linux | solaris | bsd]ix + :glXGetProcAddress + else + raise 'Unrecognized platform' + end + @opengl_lib = Fiddle.dlopen(lib_path) + getProcAddress = @opengl_lib[getProcAddressName.to_s] + + + @glGetProcAddress = Fiddle::Function.new( + getProcAddress, + fiddle_typed(GL_COMMAND_TYPES[getProcAddressName][:parameter_types]), + fiddle_typed(GL_COMMAND_TYPES[getProcAddressName][:return_type]) + ) end begin @@ -129,6 +163,15 @@ def load_sym(name, types) end if @opengl_lib end + def load_ext_sym(name, types) + sym = @glGetProcAddress.call(name.to_s) + Fiddle::Function.new( + sym, + fiddle_typed(types[:parameter_types]), + fiddle_typed(types[:return_type]) + ) + end + end # FiddleSymbolLoader end # GLSym