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_("Compiz Fusion"), methods => [ qw(native Xgl) ], wms => [ qw(compiz-fusion) ], }, ); 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-fusion', configuration_tool => 'ccsm', packages => [ 'compiz-fusion', 'compiz-decorator-gtk' ], desktop_packages => { KDE => [ 'compiz-decorator-kde' ], KDE4 => [ 'compiz-decorator-kde4' ], }, name => 'Compiz Fusion', description => N_("Compiz Fusion is a 3D compositing window manager."), }, { 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(geode mga nv openchrome sis tdfx vboxvideo vesa 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 !member($driver, 'i810', 'intel') || $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 ($do_pkgs) = @_; $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, $o_installed_only) = @_; my ($available, $type) = detect_types($glx); @$available = grep { !$_->{wms} || -e '/usr/bin/' . first(@{$_->{wms}}) } @$available if $o_installed_only; $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 ($do_pkgs, $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; $do_pkgs->ensure_are_installed(\@packages); } #- FIXME: move in common.pm and factorize with network::network::proxy_configure_gnome sub _gconf_set { my ($key, $type, $value) = @_; -d "$::prefix/etc/gconf/2/" or return; my $defaults_dir = "/etc/gconf/gconf.xml.local-defaults"; my $p_defaults_dir = "$::prefix$defaults_dir"; run_program::rooted($::prefix, 'gconftool-2', '>', '/dev/null', "--config-source=xml::$p_defaults_dir", "--direct", "--set", "--type=$type", if_($type eq "list", '--list-type', 'string'), $key, $value); } sub write { my ($glx) = @_; my $server_start = member($glx->{method}, 'Xgl', 'Xmetisse'); my $wm_start = member($glx->{method}, qw(native 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($wm_start), COMPOSITING_WM => $glx->{wm}, }); _gconf_set("/system/gstreamer/0.10/default/videosink", "string", $wm_start ? "ximagesink" : "autovideosink"); } 1;