lib/mittsu/opengl/gl_debug.rb
require 'opengl'
ERROR_STRINGS = {
GL::NO_ERROR => 'NO_ERROR',
GL::INVALID_ENUM => 'INVALID_ENUM',
GL::INVALID_VALUE => 'INVALID_VALUE',
GL::INVALID_OPERATION => 'INVALID_OPERATION',
GL::STACK_OVERFLOW => 'STACK_OVERFLOW',
GL::STACK_UNDERFLOW => 'STACK_UNDERFLOW',
GL::OUT_OF_MEMORY => 'OUT_OF_MEMORY',
# GL::TABLE_TOO_LARGE => 'TABLE_TOO_LARGE'
}
OriginalGL = GL
module OpenGLDebug
class DebugShader
def initialize(handle)
@handle = handle
@uniforms = {}
end
def set_uniform(handle, name)
@uniforms[handle] = name
end
def get_uniform_name(handle)
@uniforms[handle]
end
end
def self.load_lib(*args)
OriginalGL.load_lib(*args)
end
OriginalGL.constants.each do |c|
const_set c, OriginalGL.const_get(c)
end
class << self
OriginalGL::GL_FUNCTION_SYMBOLS
.map { |m| m.to_s.gsub(/^gl/, '').to_sym }
.each do |m|
define_method(m) do |*args|
call_debug_method(m, caller[0], *args)
end
end
def call_debug_method m, called_from = caller[0], *args
if m.to_s.start_with?('Uniform')
uniform_name = @@current_shader.get_uniform_name(args.first)
call = "#{m}('#{uniform_name}',#{args[1..-1].map { |s| s.to_s[0..20] }.join(', ')})"
else
call = "#{m}(#{args.map { |s| s.to_s[0..20] }.join(', ')})"
end
print call
r = OriginalGL.send(m, *args)
ret = r.nil? ? '' : " => #{r}"
puts "#{ret} (#{called_from})"
e = OriginalGL.GetError
raise "ERROR: #{m} => #{ERROR_STRINGS[e]}" unless e == GL::NO_ERROR
r
end
def CreateProgram
call_debug_method(:CreateProgram, caller[0]).tap do |handle|
@@shaders ||= {}
@@shaders[handle] = DebugShader.new(handle)
end
end
def UseProgram(handle)
@@current_shader = @@shaders[handle]
call_debug_method(:UseProgram, caller[0], handle)
end
def GetUniformLocation(program, name)
call_debug_method(:GetUniformLocation, caller[0], program, name).tap do |handle|
@@shaders[program].set_uniform(handle, name)
end
end
end
end
GL = OpenGLDebug