danini-the-panini/mittsu-opengl

View on GitHub
lib/mittsu/generic_lib.rb

Summary

Maintainability
A
0 mins
Test Coverage
D
68%
require 'opengl'
require 'open3'

module Mittsu
  module GenericLib
    def discover
      case GL.get_platform
      when :OPENGL_PLATFORM_WINDOWS
        self::Windows.new
      when :OPENGL_PLATFORM_MACOSX
        self::MacOS.new
      when :OPENGL_PLATFORM_LINUX
        self::Linux.new
      else
        warn "WARNING: Unsupported platform: #{GL.get_platform}"
        Base.new
      end
    end

    class Base
      def path; nil; end
    end

    class Linux < Base
      def path
        @_path ||= begin
          ldconfig_lib || driver_specific_lib || sixtyfour_bit_lib || fallback_lib || give_up
        end.tap do |result|
          print_debug_info(result) if DEBUG
        end
      end

      class << self
        def kernel_module_in_use
          lspci_line, stderr, _status = Open3.capture3("lspci -nnk | grep -i vga -A3 | grep 'in use'")
          puts stderr if DEBUG
          /in use:\s*(\S+)/ =~ lspci_line && $1
        rescue
          ''
        end

        def lib_paths
          Dir.glob('/usr/lib*/**/libGL.so*')
        rescue
          []
        end

        def sixtyfour_bits?
          1.size == 8
        end

        def ldconfig
          `ldconfig -p | grep 'libGL\\.so'`.lines
        rescue
          []
        end
      end

      private

        def ldconfig_lib
          return nil if ldconfig.empty?
          @_debug = { source: 'ldconfig', info: ldconfig.inspect } if DEBUG
          ldconfig_for_arch = ldconfig.reject { |lib| @loader.sixtyfour_bits? ^ ldconfig_64?(lib) }
          ldconfig_for_arch.first.match(/=> (\/.*)$/)[1]
        end

        def ldconfig_64?(lib)
          lib =~ /\([^\)]*64[^\)]*\) =>/
        end

        def driver_specific_lib
          return nil if libs.empty?
          @_debug = { source: 'driver', info: kernel_module } if DEBUG
          libs.select { |lib| lib =~ /nvidia/ }.first if kernel_module =~ /nvidia/
        end

        def sixtyfour_bit_lib
          return nil if libs.empty?
          sixtyfour_bit_libs = libs.select { |lib| lib =~ /64/ }
          @_debug = { source: '64', info: sixtyfour_bit_libs.inspect } if DEBUG
          sixtyfour_bit_libs.first if @loader.sixtyfour_bits?
        end

        def fallback_lib
          return nil if libs.empty?
          @_debug = { source: 'fallback', info: libs.inspect } if DEBUG
          libs.first
        end

        def give_up
          @_debug = { source: 'none', info: nil } if DEBUG
          nil
        end

        def kernel_module
          @_kernel_module ||= @loader.kernel_module_in_use
        end

        def libs
          @_libs ||= @loader.lib_paths.sort_by(&:length)
        end

        def ldconfig
          @_ldconfig ||= @loader.ldconfig
        end

        def print_debug_info(result)
          puts "Loading lib path: #{result.inspect}"
          puts "Source: #{@_debug[:source]}"
          puts "Info: #{@_debug[:info]}"
          puts "64-bit? #{@loader.sixtyfour_bits?}"
        end
    end
  end
end