diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Xconfig/glx.pm | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/lib/Xconfig/glx.pm b/lib/Xconfig/glx.pm new file mode 100644 index 0000000..35ad413 --- /dev/null +++ b/lib/Xconfig/glx.pm @@ -0,0 +1,272 @@ +package Xconfig::glx; + +use diagnostics; +use strict; + +use common; +use any; + +my $compositing_server_config = '/etc/sysconfig/compositing-server'; +my $compositing_wm_config = '/etc/sysconfig/compositing-wm'; + +our @gl_compositing_types = ( + { + type => "none", + name => N_("No 3D desktop effects"), + }, + { + type => "metisse", + name => N_("Metisse"), + methods => [ qw(Xmetisse) ], + wms => [ qw(metisse-start-fvwm) ], + }, + { + type => "cube", + name => N_("3D desktop (cube workspace)"), + methods => [ qw(native Xgl) ], + wms => [ qw(compiz beryl) ], + }, +); + +our @gl_compositing_servers = ( + { + method => "native", + name => N_("native support"), + packages => [], + description => N_("Some drivers provide native support for OpenGL compositing (using AIGLX for example). If your system supports it, it is the preferred solution."), + }, + { + method => "Xgl", + name => "Xgl", + packages => [ 'x11-server-xgl' ], + description => N_("Xgl is an additional graphical server that adds 3D desktop support."), + }, + { + method => "Xmetisse", + name => "Metisse (experimental)", + packages => [ 'x11-server-xmetisse' ], + description => N_("Metisse is an experimental X-based window system."), + }, +); + +our @gl_compositing_wms = ( + { + wm => 'compiz', + configuration_tool => 'gset-compiz', + packages => [ 'compiz', 'compiz-decorator-gtk', 'gset-compiz' ], + desktop_packages => { + KDE => [ 'compiz-decorator-kde' ], + }, + name => 'Compiz', + description => N_("Compiz is the reference compositing window manager."), + }, + { + wm => 'beryl', + configuration_tool => 'beryl-settings', + packages => [ 'beryl-core', 'beryl-manager' ], + desktop_packages => { + KDE => [ 'aquamarine' ], + GNOME => [ 'heliodor' ], + }, + name => 'Beryl', + description => N_("Beryl is a fork of compiz and provides bleeding-edge features."), + }, + { + wm => 'metisse-start-fvwm', + configuration_tool => '', + packages => [ 'metisse' ], + name => 'Metisse FVWM', + description => N_("Metisse FVWM is a FVWM window manager modified for Metisse."), + }, +); + +sub parse_glxinfo { + my (%options) = @_; + + my $glx_info = {}; + my $extensions_section; + + my @glxinfo = $options{file} ? cat_($options{file}) : do { + require run_program; + my $lib = arch() =~ /x86_64/ ? "lib64" : "lib"; + local $ENV{LD_LIBRARY_PATH} = $options{Mesa} && "/usr/$lib/mesa"; + run_program::rooted_get_stdout($::prefix, '/usr/bin/glxinfo', '2>', '/dev/null'); + }; + foreach (@glxinfo) { + chomp; + if (/^direct rendering: Yes/) { + $glx_info->{capabilities}{direct_rendering} = 1; + } elsif (my ($type, $value) = /^(.*) string: (.*)$/) { + $type =~ s/\s/_/g; + $glx_info->{strings}{$type} = $value; + } elsif (/^(.*) extensions:/) { + $extensions_section = $1; + $extensions_section =~ s/\s/_/g; + } elsif (/^\s/) { + if ($extensions_section) { + push @{$glx_info->{extensions}{$extensions_section}}, grep { $_ } split(/,?\s+/); + } + } else { + undef $extensions_section; + } + } + $glx_info; +} + +my @glx_blacklist = qw(nv sis tdfx vmware); + +sub is_in_metisse() { + my $display = $ENV{DISPLAY}; + $display =~ s/\..*//; + $display && any { + member($display, split("\0", cat_("/proc/" . $_ . "/cmdline"))); + } fuzzy_pidofs("Xmetisse"); +} + +sub get_glx_status { + my ($o_mesa_file, $o_system_file) = @_; + + my ($driver, $resolution); + require Xconfig::xfree; + eval { + my $raw_X = Xconfig::xfree->read; + $driver = $raw_X->get_Driver; + $resolution = $raw_X->get_resolution; + }; + $resolution ||= {}; + member($driver, @glx_blacklist) and return {}; + + my ($mesa_glx_info, $system_glx_info); + if ($o_mesa_file) { + $mesa_glx_info = parse_glxinfo(file => $o_mesa_file); + $system_glx_info = $o_system_file ? parse_glxinfo(file => $o_system_file) : $mesa_glx_info; + } else { + $system_glx_info = parse_glxinfo(); + $mesa_glx_info = parse_glxinfo(Mesa => 1); + } + + my $glx_status = {}; + + $glx_status->{context}{Mesa} = $system_glx_info->{strings}{OpenGL_renderer} =~ /Mesa/; + $glx_status->{context}{MesaDRI} = $system_glx_info->{strings}{OpenGL_renderer} =~ /Mesa DRI/; + $glx_status->{context}{Xgl} = + $system_glx_info->{strings}{server_glx_vendor} eq 'SGI' && + member('GLX_EXT_texture_from_pixmap', @{$mesa_glx_info->{extensions}{GLX}}) && ( + #- avoid nv, but detect i810 and fglrx + member('GL_ARB_fragment_program', @{$mesa_glx_info->{extensions}{OpenGL}}) || + !$glx_status->{context}{Mesa} && member('GLX_SGIX_fbconfig', @{$system_glx_info->{extensions}{GLX}}) + ); + $glx_status->{context}{Xmetisse} = is_in_metisse(); + + $glx_status->{capabilities}{direct_rendering} = + $system_glx_info->{capabilities}{direct_rendering} || + $glx_status->{context}{Xgl} || + $glx_status->{context}{Xmetisse}; + + $glx_status->{capabilities}{Xgl} = + $glx_status->{context}{Xgl} || + $glx_status->{capabilities}{direct_rendering} && ( + !$glx_status->{context}{MesaDRI} || + member('GLX_MESA_allocate_memory', @{$system_glx_info->{extensions}{GLX}}) + ) && ( + #- Xgl turns black with i810 and 16 bits + $driver ne 'i810' || $resolution->{Depth} eq '24' + ); + + $glx_status->{capabilities}{native} = + $glx_status->{capabilities}{direct_rendering} && + member('GLX_EXT_texture_from_pixmap', @{$system_glx_info->{extensions}{client_glx}}) && + member('GLX_EXT_texture_from_pixmap', @{$system_glx_info->{extensions}{server_glx}}); + + $glx_status->{capabilities}{Xmetisse} = $glx_status->{capabilities}{direct_rendering}; + + #- no support in configuration tools yet + # $glx_status->{capabilities}{'3d-desktop'} = $glx_status->{capabilities}{direct_rendering}; + + $glx_status; +} + +sub detect() { + my $compositing_server = +{ getVarsFromSh($::prefix . $compositing_server_config) }; + my $compositing_wm = +{ getVarsFromSh($::prefix . $compositing_wm_config) }; + my $glx = { capabilities => get_glx_status()->{capabilities} }; + $glx->{supported} = $glx->{capabilities}{direct_rendering}; + $glx->{compositing} = $compositing_wm->{COMPOSITING_WM_START} eq 'yes' || $compositing_wm->{COMPOSITING_WM_START} eq 'auto' && $glx->{supported}; + $glx->{wm} = $compositing_wm->{COMPOSITING_WM}; + $glx->{method} = + $glx->{compositing} ? ( + $glx->{capabilities}{native} && member($compositing_server->{COMPOSITING_SERVER_START}, qw(auto no)) && !$compositing_server->{COMPOSITING_SERVER} ? + 'native' : + $glx->{capabilities}{Xgl} && member($compositing_server->{COMPOSITING_SERVER_START}, qw(auto yes)) && $compositing_server->{COMPOSITING_SERVER} eq 'Xgl' ? + 'Xgl' : + $glx->{capabilities}{Xmetisse} && member($compositing_server->{COMPOSITING_SERVER_START}, qw(auto yes)) && $compositing_server->{COMPOSITING_SERVER} eq 'Xmetisse' ? + 'Xmetisse' : + '' + ) : ''; + $glx; +} + +sub detect_may_install { + my ($in) = @_; + $in->do_pkgs->ensure_is_installed('mesa-demos', '/usr/bin/glxinfo') or return; + Xconfig::glx::detect(); +} + +sub detect_types { + my ($glx) = @_; + my @available_types = ( + grep { + !$_->{methods} || + any { $glx->{capabilities}{$_} } @{$_->{methods}}; + } @gl_compositing_types + ); + my $type = find { member($glx->{method}, @{$_->{methods}}) } @available_types; + \@available_types, $type; +} + +sub choose_interactive { + my ($in, $glx) = @_; + + my ($available, $type) = detect_types($glx); + + $in->ask_from_({ title => N("3D Desktop effects") }, [ + { label => N("3D Desktop effects"), title => 1 }, + if_(!$glx->{supported}, + { label => N("Your system does not support 3D desktop effects.") }), + { type => 'list', val => \$type, allow_empty_list => 1, + list => $available, format => sub { translate($_[0]{name}) } }, + ]) or return; + + $glx->{method} = find { $glx->{capabilities}{$_} } @{$type->{methods}}; + $glx->{wm} = first(@{$type->{wms}}); + + 1; +} + +sub install { + my ($in, $glx) = @_; + my $server = find { $_->{method} eq $glx->{method} } @gl_compositing_servers; + my $wm = find { $_->{wm} eq $glx->{wm} } @gl_compositing_wms; + my @sessions = any::sessions(); + my @packages = map { + my $entry = $_; + @{$entry->{packages}}, + map { @{$entry->{desktop_packages}{$_} || []} } @sessions; + } grep { $_ } $server, $wm; + $in->do_pkgs->ensure_are_installed(\@packages); +} + +sub write { + my ($glx) = @_; + my $server_start = member($glx->{method}, 'Xgl', 'Xmetisse'); + addVarsInSh($::prefix . $compositing_server_config, { + COMPOSITING_SERVER_START => bool2yesno($server_start), + COMPOSITING_SERVER => $server_start && $glx->{method}, + }); + addVarsInSh($::prefix . $compositing_wm_config, { + COMPOSITING_WM_START => bool2yesno(member($glx->{method}, qw(native Xgl Xmetisse))), + COMPOSITING_WM => $glx->{wm}, + }); +} + +1; |