Skip to content
This repository was archived by the owner on May 31, 2020. It is now read-only.

Commit 9a26e11

Browse files
committed
Change the generated commands script.
Commands and their type info are now kept in a hash of function names to hashes of data types (GL_COMMAND_TYPES). This effectively allows me to query a function's info rather than just loading it and hoping it exists. As a result, the loading code can be reduce to a call to __load_gl_sym__, which is also included in the generated code. I should probably break it off into the GlSym code but for now this'll do. The upshot to this is that loading a symbol no longer raises exceptions if it doesn't exist. It simply returns the wrapped function if loaded or false if not. So, if you load a symbol and it's not there, the exception only comes from attempting to use that symbol. So, it's better now to query whether the function is loaded first rather than using it if I can't be certain it's available. Also, Gl#have_gl_command? is now a thing, so the above query is now doable as well. There's also Gl#load_all_gl_commands!, which does what it says on the tin. -- GlSym is now a submodule of Gl. __load_gl_sym__ caches the loaded function. It also stores the command types because I didn't want to make those part of the Gl module (and thereby accidentally infect the global namespace if someone does `include Gl`, which sounds pretty reasonable to me).
1 parent fbca139 commit 9a26e11

File tree

4 files changed

+62
-28
lines changed

4 files changed

+62
-28
lines changed

ext/opengl-core/opengl_stub.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ static VALUE plat_is_linux(VALUE self)
4747

4848
void Init_opengl_stub(void)
4949
{
50-
VALUE module = rb_define_module("GlSym");
51-
rb_define_singleton_method(module, "apple?", plat_is_apple, 0);
52-
rb_define_singleton_method(module, "windows?", plat_is_windows, 0);
53-
rb_define_singleton_method(module, "unix?", plat_is_unix, 0);
54-
rb_define_singleton_method(module, "linux?", plat_is_linux, 0);
50+
VALUE gl_module = rb_define_module("Gl");
51+
VALUE gl_sym_module = rb_define_module_under(gl_module, "GlSym");
52+
rb_define_singleton_method(gl_sym_module, "apple?", plat_is_apple, 0);
53+
rb_define_singleton_method(gl_sym_module, "windows?", plat_is_windows, 0);
54+
rb_define_singleton_method(gl_sym_module, "unix?", plat_is_unix, 0);
55+
rb_define_singleton_method(gl_sym_module, "linux?", plat_is_linux, 0);
5556
}

gen_from_xml.rb

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -224,33 +224,34 @@ module Gl
224224
require 'opengl-core/gl_sym'
225225

226226
module Gl
227-
EOS
228227

229-
filtered_commands.each {
230-
|name, cmd|
231-
io.puts " # @api private\n @@#{name}__fnptr__ = nil"
232-
}
228+
#{
229+
filtered_commands.map {
230+
|name, cmd|
231+
# Put a _ on the end of each argument to avoid conflicts with reserved words
232+
param_string = cmd.parameters.map { |p| "#{p.name}_" }.join(', ')
233233

234-
filtered_commands.each {
235-
|name, cmd|
236-
# Put a _ on the end of each argument to avoid conflicts with reserved words
237-
param_string = cmd.parameters.map { |p| "#{p.name}_" }.join(', ')
238-
io.puts <<-EOS
234+
<<-EOS_INNER
235+
GlSym::GL_COMMAND_TYPES[:#{name}] = {
236+
:parameter_types => [#{cmd.parameters.map { |p| fiddle_type(p) }.join(', ') }],
237+
:return_type => #{ fiddle_type(cmd.type) }
238+
}
239239

240-
# @api private
240+
# @api raw
241241
def #{name}__(#{param_string})
242-
if @@#{name}__fnptr__.nil?
243-
sym = GlSym.load_gl_sym__('#{name}')
244-
@@#{name}__fnptr__ = Fiddle::Function.new(sym, [#{
245-
cmd.parameters.map { |p| fiddle_type(p) }.join(', ') }], #{ fiddle_type(cmd.type) })
242+
unless (fn = GlSym.__load_gl_sym__(:#{name}))
243+
raise NotImplementedError, "GL function #{name} is not available."
246244
end
247-
@@#{name}__fnptr__.call(#{param_string})
245+
fn.call(#{param_string})
248246
end
247+
249248
alias_method :'#{name}', :'#{name}__'
250-
EOS
251-
}
252249

253-
io.puts "end # module Gl"
250+
EOS_INNER
251+
}.join('')
252+
}
253+
end # module Gl
254+
EOS
254255
}
255256
end
256257

lib/opengl-core.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,16 @@
44
require 'opengl-core/gl_commands'
55

66
module Gl
7+
8+
def have_gl_command?(command)
9+
!!GlSym.__load_gl_sym__(command.intern)
10+
end
11+
12+
def load_all_gl_commands!()
13+
GlSym::GL_COMMAND_TYPES.each_key { |fnsym| GlSym.__load_gl_sym__(fnsym) }
14+
self
15+
end
16+
717
extend self
18+
819
end

lib/opengl-core/gl_sym.rb

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,25 @@
11
require 'fiddle'
22
require 'opengl-core/opengl_stub'
33

4+
module Gl ; end
5+
46
# @api private
5-
module GlSym
7+
module Gl::GlSym
8+
9+
# Filled by gl_commands.rb
10+
GL_COMMAND_TYPES = {}
11+
# Filled by __load_gl_sym__
12+
GL_COMMAND_FUNCTIONS = {}
613

714
# OpenGL library handle.
815
@@opengl_lib = nil
916

1017
# Loads a symbol from the GL library. If the GL library hasn't yet been loaded
11-
# it will also do that.
12-
def self.load_gl_sym__(name)
18+
# it will also do that. The returned function will be a wrapped Fiddle
19+
# function using the types that function name is associated with in
20+
# GL_COMMAND_TYPES. The returned value is cached in GL_COMMAND_FUNCTIONS and
21+
# returned if __load_gl_sym__ is called for the same name again.
22+
def self.__load_gl_sym__(name)
1323
if @@opengl_lib.nil?
1424
lib_path = case
1525
when apple?
@@ -24,7 +34,18 @@ def self.load_gl_sym__(name)
2434
@@opengl_lib = Fiddle.dlopen(lib_path)
2535
end
2636

27-
@@opengl_lib[name]
37+
fn = GL_COMMAND_FUNCTIONS[name]
38+
if fn.nil?
39+
fn = (GL_COMMAND_FUNCTIONS[name] = begin
40+
sym = @@opengl_lib[name.to_s]
41+
types = GL_COMMAND_TYPES[name]
42+
Fiddle::Function.new(sym, types[:parameter_types], types[:return_type])
43+
rescue
44+
false
45+
end)
46+
end
47+
48+
fn
2849
end
2950

3051
end # module GlSym

0 commit comments

Comments
 (0)