/[soft]/drakx-kbd-mouse-x11/trunk/lib/Xconfig/card.pm
ViewVC logotype

Annotation of /drakx-kbd-mouse-x11/trunk/lib/Xconfig/card.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2391 - (hide annotations) (download)
Mon Dec 12 19:54:37 2011 UTC (12 years, 4 months ago) by tv
File size: 17542 byte(s)
(check_bad_card,from_raw_X) simplify
1 dmorgan 391 package Xconfig::card; # $Id: card.pm 266355 2010-02-22 20:51:38Z pzanoni $
2    
3     use diagnostics;
4     use strict;
5    
6     use lib '/usr/lib/libDrakX';
7     use detect_devices;
8     use Xconfig::xfree;
9     use modules;
10     use common;
11     use interactive;
12     use log;
13     use run_program;
14    
15     my $lib = arch() =~ /x86_64/ ? "lib64" : "lib";
16    
17     sub modules_dir() { "/usr/$lib/xorg/modules" }
18    
19     my %VideoRams = (
20     256 => N_("256 kB"),
21     512 => N_("512 kB"),
22     1024 => N_("1 MB"),
23     2048 => N_("2 MB"),
24     4096 => N_("4 MB"),
25     8192 => N_("8 MB"),
26     16384 => N_("16 MB"),
27     32768 => N_("32 MB"),
28     65536 => N_("64 MB or more"),
29     );
30    
31     my @xfree4_Drivers = ((arch() =~ /^sparc/ ? qw(sunbw2 suncg14 suncg3 suncg6 sunffb sunleo suntcx) :
32     qw(apm ark ast chips cirrus i128 i740 intel mga
33     neomagic newport nouveau nv openchrome psb qxl
34     rendition s3 s3virge savage siliconmotion sis sisusb
35     tdfx tga trident tseng vesa vmware xgi xgixp)),
36     if_(arch() =~ /i.86/, qw(geode)),
37     qw(ati glint fbdev));
38    
39     sub from_raw_X {
40     my ($raw_X) = @_;
41    
42     my ($device, @cards) = $raw_X->get_devices or die "no card configured";
43    
44     my $card = {
45     use_DRI_GLX => eval { any { /dri/ } $raw_X->get_modules },
46 tv 2391 DRI_GLX_SPECIAL => $device->{Driver} eq 'nvidia' && eval { member('glx', $raw_X->get_modules) },
47 dmorgan 391 %$device,
48     if_($device->{Driver} eq 'nvidia',
49     DriverVersion =>
50     readlink("$::prefix/etc/alternatives/gl_conf") =~ m!nvidia(.*)/! ? $1 : '97xx'),
51     if_(@cards, cards => \@cards),
52     };
53     add_to_card__using_Cards($card, $card->{BoardName});
54     $card;
55     }
56    
57     sub to_raw_X {
58     my ($card, $raw_X) = @_;
59    
60     my @cards = ($card, @{$card->{cards} || []});
61    
62     foreach (@cards) {
63     if (arch() =~ /ppc/ && ($_->{Driver} eq 'r128' || $_->{Driver} eq 'radeon')) {
64     $_->{UseFBDev} = 1;
65     }
66     }
67    
68     $raw_X->set_devices(@cards);
69    
70     $raw_X->get_ServerLayout->{Xinerama} = { commented => !$card->{Xinerama}, Option => 1 }
71     if defined $card->{Xinerama};
72    
73     # cleanup deprecated previous special nvidia explicit libglx
74     $raw_X->remove_load_module(modules_dir() . "$_/libglx.so") foreach '/extensions/nvidia', '/extensions/nvidia_legacy', '/extensions';
75    
76     # remove ModulePath that we added
77     $raw_X->remove_ModulePath(modules_dir() . "/extensions/$_") foreach 'nvidia97xx', 'nvidia96xx', 'nvidia71xx', 'nvidia-current';
78     $raw_X->remove_ModulePath(modules_dir());
79     #- if we have some special ModulePath, ensure the last one is the standard ModulePath
80     $raw_X->add_ModulePath(modules_dir()) if $raw_X->get_ModulePaths;
81    
82     #- un-disable modules that we previously disabled
83     $raw_X->remove_disable_module('glx');
84     $raw_X->remove_disable_module('dri');
85    
86     $raw_X->remove_Section('DRI');
87    
88     $raw_X->remove_load_module('v4l') if $card->{use_DRI_GLX} && $card->{Driver} eq 'r128';
89     }
90    
91     sub probe() {
92     #-for Pixel tests
93     #- my @c = { driver => 'Card:Matrox Millennium G400 DualHead', description => 'Matrox|Millennium G400 Dual HeadCard' };
94     my @c = detect_devices::matching_driver__regexp('^(Card|Server|Driver):');
95    
96 anssi 1001 # prefer the boot device
97     my @cards = sort { $b->{boot_device} cmp $a->{boot_device} } map {
98 dmorgan 391 my @l = $_->{description} =~ /(.*?)\|(.*)/;
99     my $card = {
100     description => $_->{description},
101     VendorName => $l[0], BoardName => $l[1],
102     BusID => "PCI:$_->{pci_bus}:$_->{pci_device}:$_->{pci_function}",
103 anssi 1001 boot_device => chomp_(cat_($_->{sysfs_device} . "/boot_vga")) || 0,
104 dmorgan 391 };
105     if (my ($card_name) = $_->{driver} =~ /Card:(.*)/) {
106     $card->{BoardName} = $card_name;
107     add_to_card__using_Cards($card, $card_name);
108     } elsif ($_->{driver} =~ /Driver:(.*)/) {
109     $card->{Driver} = $1;
110     } else {
111     internal_error();
112     }
113     #dual head ATI card have a dummy DISPLAY_OTHER pci device because it
114     #was needed by Win2000, filter those out because we don't want to
115     #behave as if there were 2 video cards in the system in such cases
116     ($_->{media_type} eq 'DISPLAY_VGA') ? $card : ();
117     } @c;
118    
119     if (@cards >= 2 && $cards[0]{card_name} eq $cards[1]{card_name} && $cards[0]{card_name} eq 'Intel 830 - 965') {
120     shift @cards;
121     }
122     #- take a default on sparc if nothing has been found.
123     if (arch() =~ /^sparc/ && !@cards) {
124     log::l("Using probe with /proc/fb as nothing has been found!");
125     my $s = cat_("/proc/fb");
126     @cards = { server => $s =~ /Mach64/ ? "Mach64" : $s =~ /Permedia2/ ? "3DLabs" : "Sun24" };
127     }
128    
129     #- disabling MULTI_HEAD when not available
130     foreach (@cards) {
131     $_->{MULTI_HEAD} && $_->{card_name} =~ /G[24]00/ or next;
132     if ($ENV{MATROX_HAL}) {
133     $_->{need_MATROX_HAL} = 1;
134     } else {
135     delete $_->{MULTI_HEAD};
136     }
137     }
138    
139     #- in case of only one cards, remove all BusID reference, this will avoid
140     #- need of change of it if the card is moved.
141     #- on many PPC machines, card is on-board, BusID is important, leave?
142     if (@cards == 1 && !$cards[0]{MULTI_HEAD} && arch() !~ /ppc/) {
143     delete $cards[0]{BusID};
144     }
145    
146     @cards;
147     }
148    
149     sub card_config__not_listed {
150     my ($in, $card, $options) = @_;
151    
152     my $vendors_regexp = join '|', map { quotemeta } (
153     '3Dlabs',
154     'AOpen', 'ASUS', 'ATI', 'Ark Logic', 'Avance Logic',
155     'Cardex', 'Chaintech', 'Chips & Technologies', 'Cirrus Logic', 'Compaq', 'Creative Labs',
156     'Dell', 'Diamond', 'Digital',
157     'ET', 'Elsa',
158     'Genoa', 'Guillemot', 'Hercules', 'Intel', 'Leadtek',
159     'Matrox', 'Miro', 'NVIDIA', 'NeoMagic', 'Number Nine',
160     'Oak', 'Orchid',
161     'RIVA', 'Rendition Verite',
162     'S3', 'Silicon Motion', 'STB', 'SiS', 'Sun',
163     'Toshiba', 'Trident',
164     'VideoLogic',
165     );
166     my $cards = readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+");
167    
168     my @xf4 = grep { $options->{allowFB} || $::isStandalone || $_ ne 'fbdev' }
169     uniq(@xfree4_Drivers, map { $_->{Driver} } values %$cards);
170     my @list = (
171     (map { 'Vendor|' . $_ } keys %$cards),
172     (map { 'Xorg|' . $_ } @xf4),
173     );
174    
175     my $r = exists $cards->{$card->{BoardName}} ? "Vendor|$card->{BoardName}" : 'Xorg|vesa';
176     $in->ask_from_({ title => N("X server"),
177     messages => N("Choose an X server"),
178     interactive_help_id => 'configureX_card_list',
179     },
180     [ { val => \$r, separator => '|', list => \@list, sort => 1,
181     format => sub { $_[0] =~ /^Vendor\|($vendors_regexp)\s*-?(.*)/ ? "Vendor|$1|$2" :
182     $_[0] =~ /^Vendor\|(.*)/ ? "Vendor|Other|$1" : $_[0] } } ]) or return;
183    
184     log::explanations("Xconfig::card: $r manually chosen");
185    
186     $r eq "Vendor|$card->{BoardName}" and return 1; #- it is unchanged, do not modify $card
187    
188     my ($kind, $s) = $r =~ /(.*?)\|(.*)/;
189    
190     %$card = ();
191     if ($kind eq 'Vendor') {
192     add_to_card__using_Cards($card, $s);
193     } else {
194     $card->{Driver} = $s;
195     $card->{DRI_GLX} = 0;
196     }
197     $card->{manually_chosen} = 1;
198     1;
199     }
200    
201     sub multi_head_choose {
202     my ($in, $_auto, @cards) = @_;
203    
204     my @choices = multi_head_choices('', @cards);
205    
206     my $tc = $choices[0];
207     if (@choices > 1) {
208     $tc = $in->ask_from_listf(N("Multi-head configuration"),
209     N("Your system supports multiple head configuration.
210     What do you want to do?"), sub { $_[0]{text} }, \@choices) or return;
211     }
212     $tc->{code} or die internal_error();
213     return $tc->{code}();
214     }
215    
216     sub configure_auto_install {
217     my ($raw_X, $do_pkgs, $old_X, $options) = @_;
218    
219     my $card = $old_X->{card} || {};
220    
221     if ($card->{card_name}) {
222     #- try to get info from given card_name
223     add_to_card__using_Cards($card, $card->{card_name});
224     if (!$card->{Driver}) {
225     log::l("bad card_name $card->{card_name}, using probe");
226     undef $card->{card_name};
227     }
228     }
229    
230     my ($boot_xdriver) = cat_("/proc/cmdline") =~ /.*\bxdriver=(\S+)/;
231    
232     $options->{freedriver} = 1 if $boot_xdriver eq 'free';
233    
234     if (!$card->{Driver} && $boot_xdriver && !member($boot_xdriver, 'auto', 'free')) {
235     log::explanations("using driver $boot_xdriver from kernel command line");
236     $card = {
237     Driver => $boot_xdriver,
238     description => "Set by boot parameter",
239     VendorName => "Custom",
240     BoardName => "Set by boot parameter",
241     };
242     if ($boot_xdriver =~ /^(nvidia.|fglrx)/) {
243     $card->{Driver} = "vesa";
244     $card->{Driver2} = $boot_xdriver;
245     }
246     }
247    
248     if (!$card->{Driver}) {
249     my @cards = probe();
250     my ($choice) = multi_head_choices($old_X->{Xinerama}, @cards);
251     $card = $choice ? $choice->{code}() : do {
252     log::explanations('no graphic card probed, try providing one using $o->{card}{Driver} or $o->{card}{card_name}. Defaulting...');
253     { Driver => $options->{allowFB} ? 'fbdev' : 'vesa' };
254     };
255     }
256    
257     install_server($card, $options, $do_pkgs, undef) or return;
258     $card = configure_Driver2($card, undef);
259    
260     Xconfig::various::various_auto_install($raw_X, $card, $old_X);
261     set_glx_restrictions($card);
262    
263     if ($card->{needVideoRam} && !$card->{VideoRam}) {
264     $card->{VideoRam} = $options->{VideoRam_probed} || 4096;
265     log::explanations("argh, I need to know VideoRam! Taking " . ($options->{probed_VideoRam} ? "the probed" : "a default") . " value: VideoRam = $card->{VideoRam}");
266     }
267     to_raw_X($card, $raw_X);
268     $card;
269     }
270    
271     sub configure {
272     my ($in, $raw_X, $do_pkgs, $auto, $options) = @_;
273    
274     my @cards = probe();
275     @cards or @cards = {};
276    
277     if (!$cards[0]{Driver}) {
278     if ($options->{allowFB}) {
279     $cards[0]{Driver} = 'fbdev';
280     }
281     }
282     if (!$auto || !$cards[0]{Driver}) {
283     card_config__not_listed:
284     card_config__not_listed($in, $cards[0], $options) or return;
285     }
286    
287     my $card = multi_head_choose($in, $auto, @cards) or return;
288    
289     install_server($card, $options, $do_pkgs, $in) or goto card_config__not_listed;
290    
291     $card = configure_Driver2($card, $in);
292    
293     Xconfig::various::various($in, $raw_X, $card, $options, $auto);
294     set_glx_restrictions($card);
295    
296     if ($card->{needVideoRam} && !$card->{VideoRam}) {
297     $card->{VideoRam} = (find { $_ <= $options->{VideoRam_probed} } reverse ikeys %VideoRams) || 4096;
298     $in->ask_from('', N("Select the memory size of your graphics card"),
299     [ { val => \$card->{VideoRam},
300     type => 'list',
301     list => [ ikeys %VideoRams ],
302     format => sub { translate($VideoRams{$_[0]}) },
303     not_edit => 0 } ]) or return;
304     }
305    
306     to_raw_X($card, $raw_X);
307     $card;
308     }
309    
310     sub install_server {
311     my ($card, $options, $do_pkgs, $o_in) = @_;
312    
313     my @packages;
314     my @must_have = "x11-driver-video-$card->{Driver}";
315    
316     if ($options->{freedriver}) {
317     delete $card->{Driver2};
318     }
319    
320     if ($card->{Driver2}) {
321     require Xconfig::proprietary;
322     Xconfig::proprietary::handle_DRIVER2_NO_SSE($card);
323     my @pkgs = Xconfig::proprietary::pkgs_for_Driver2($card->{Driver2}, $do_pkgs);
324     if (@pkgs && (!$o_in || $o_in->ask_yesorno('', formatAlaTeX(N("There is a proprietary driver available for your video card which may support additional features.
325     Do you wish to use it?")), 1))) {
326     push @packages, @pkgs;
327     } else {
328     delete $card->{Driver2};
329     }
330     }
331    
332     $do_pkgs->ensure_are_installed([ @must_have, @packages ], 1) or
333     @must_have == listlength($do_pkgs->are_installed(@must_have))
334     or return;
335    
336     if ($card->{need_MATROX_HAL}) {
337     require Xconfig::proprietary;
338     Xconfig::proprietary::install_matrox_hal($::prefix);
339     }
340     1;
341     }
342    
343     sub configure_Driver2 {
344     my ($card, $o_in) = @_;
345    
346     if ($card->{Driver2}) {
347     require Xconfig::proprietary;
348     if (my $card2 = Xconfig::proprietary::may_use_Driver2($card)) {
349     $card = $card2;
350     } else {
351     $o_in and $o_in->ask_warn('', formatAlaTeX(N("The proprietary driver was not properly installed, defaulting to free software driver.")));
352     log::l("defaulting to free software driver");
353     }
354     }
355    
356     libgl_config_and_more($card);
357     $card;
358     }
359    
360     #- configures which libGL.so.1 to use, using update-alternatives
361     #- it also configures nvidia_drv.so (using a slave alternative, cf "update-alternatives --display gl_conf")
362     sub libgl_config_and_more {
363     my ($card) = @_;
364    
365     if ($card->{Driver} eq 'nvidia') {
366     $card->{DriverVersion} or internal_error("DriverVersion should be set for driver nvidia!");
367     }
368    
369     #- ensure old deprecated conf files are not there anymore
370     unlink("/etc/ld.so.conf.d/$_.conf") foreach 'nvidia', 'nvidia_legacy', 'ati';
371    
372     my %files = (
373     fglrx => "/etc/ld.so.conf.d/GL/ati$card->{DriverVersion}.conf",
374     nvidia => "/etc/nvidia$card->{DriverVersion}/ld.so.conf",
375     psb => "/etc/ld.so.conf.d/GL/libdrm-psb.conf",
376     );
377     my $wanted = $files{$card->{Driver}} || '/etc/ld.so.conf.d/GL/standard.conf';
378     my $link = "$::prefix/etc/alternatives/gl_conf";
379     my $need_run_ldconfig = readlink($link) ne $wanted;
380     -e "$::prefix$wanted" or log::l("ERROR: $wanted does not exist, linking $link to it anyway");
381     common::symlinkf_update_alternatives('gl_conf', $wanted);
382     if ($need_run_ldconfig) {
383     log::explanations("ldconfig will be run because the GL library was switched to $wanted");
384     run_program::rooted($::prefix, 'ldconfig', '-X');
385     }
386    
387     if (member($card->{Driver}, 'fglrx', 'nvidia')) {
388     log::l("workaround buggy fglrx/nvidia driver: make dm restart xserver (#29550, #38297)");
389     eval { common::update_gnomekderc_no_create("$::prefix/etc/kde/kdm/kdmrc", 'X-:0-Core' => (
390     TerminateServer => "true",
391     )) };
392     eval { update_gnomekderc("$::prefix/etc/X11/gdm/custom.conf", daemon => (
393     AlwaysRestartServer => "true",
394     )) };
395     }
396     }
397    
398     sub multi_head_choices {
399     my ($want_Xinerama, @cards) = @_;
400     my @choices;
401    
402     my $has_multi_head = @cards > 1 || @cards && $cards[0]{MULTI_HEAD} > 1;
403     my $disable_multi_head = any {
404     $_->{Driver} or log::explanations("found card $_->{description} not supported by XF4, disabling multi-head support");
405     !$_->{Driver};
406     } @cards;
407    
408     if ($has_multi_head && !$disable_multi_head) {
409     my $configure_multi_head = sub {
410    
411     #- special case for multi head card using only one BusID.
412     @cards = map {
413     map_index { { Screen => $::i, %$_ } } ($_) x ($_->{MULTI_HEAD} || 1);
414     } @cards;
415    
416     my $card = shift @cards; #- assume good default.
417     $card->{cards} = \@cards;
418     $card->{Xinerama} = $_[0];
419     $card;
420     };
421     my $independent = { text => N("Configure all heads independently"), code => sub { $configure_multi_head->('') } };
422     my $xinerama = { text => N("Use Xinerama extension"), code => sub { $configure_multi_head->(1) } };
423     push @choices, $want_Xinerama ? ($xinerama, $independent) : ($independent, $xinerama);
424     }
425    
426     foreach my $c (@cards) {
427     push @choices, { text => N("Configure only card \"%s\"%s", $c->{description}, $c->{BusID} && " ($c->{BusID})"),
428     code => sub { $c } };
429     }
430     @choices;
431     }
432    
433     sub set_glx_restrictions {
434     my ($card) = @_;
435    
436     #- 3D acceleration configuration for XFree 4 using DRI, this is enabled by default
437     #- but for some there is a need to specify VideoRam (else it will not run).
438     if ($card->{use_DRI_GLX}) {
439     $card->{needVideoRam} = 1 if $card->{description} =~ /Matrox.* G[245][05]0/;
440     ($card->{needVideoRam}, $card->{VideoRam}) = (1, 16384)
441     if $card->{card_name} eq 'Intel 810 / 815';
442    
443     #- hack for ATI Rage 128 card using a bttv or peripheral with PCI bus mastering exchange
444     #- AND using DRI at the same time.
445     if ($card->{card_name} eq 'ATI Rage 128 TV-out') {
446     $card->{Options}{UseCCEFor2D} = bool2text(detect_devices::probe_category('multimedia/tv'));
447     }
448     }
449     }
450    
451     sub add_to_card__using_Cards {
452     my ($card, $name) = @_;
453     my $cards = readCardsDB("$ENV{SHARE_PATH}/ldetect-lst/Cards+");
454     add2hash($card, $cards->{$name});
455     $card->{BoardName} = $card->{card_name};
456    
457     $card;
458     }
459    
460     #- needed for bad cards not restoring cleanly framebuffer, according to which version of Xorg are used.
461     sub check_bad_card {
462     my ($card) = @_;
463     my $bad_card = $card->{BAD_FB_RESTORE};
464 tv 2391 $bad_card ||= member($card->{Driver}, qw(intel fbdev));
465 dmorgan 391 $bad_card ||= member($card->{Driver}, 'nvidia', 'vmware') if !$::isStandalone; #- avoid testing during install at any price.
466    
467     log::explanations("the graphics card does not like X in framebuffer") if $bad_card;
468    
469     !$bad_card;
470     }
471    
472     sub readCardsDB {
473     my ($file) = @_;
474     my ($card, %cards);
475    
476     my $F = openFileMaybeCompressed($file);
477    
478     my $lineno = 0;
479     my ($cmd, $val);
480     my $fs = {
481     NAME => sub {
482     $cards{$card->{card_name}} = $card if $card;
483     $card = { card_name => $val };
484     },
485     SEE => sub {
486     my $c = $cards{$val} or die "Error in database, invalid reference $val at line $lineno";
487     add2hash($card, $c);
488     },
489     LINE => sub { $val =~ s/^\s*//; $card->{raw_LINES} .= "$val\n" },
490     CHIPSET => sub { $card->{Chipset} = $val },
491     DRIVER => sub { $card->{Driver} = $val },
492     DRIVER2 => sub { $card->{Driver2} = $val },
493     DRIVER2_NO_SSE => sub { $card->{DRIVER2_NO_SSE} = $val },
494     NEEDVIDEORAM => sub { $card->{needVideoRam} = 1 },
495     DRI_GLX => sub { $card->{DRI_GLX} = 1 if $card->{Driver} },
496     DRI_GLX_EXPERIMENTAL => sub { $card->{DRI_GLX_EXPERIMENTAL} = 1 if $card->{Driver} },
497     MULTI_HEAD => sub { $card->{MULTI_HEAD} = $val if $card->{Driver} },
498     BAD_FB_RESTORE => sub { $card->{BAD_FB_RESTORE} = 1 },
499     FB_TVOUT => sub { $card->{FB_TVOUT} = 1 },
500     UNSUPPORTED => sub { delete $card->{Driver} },
501     COMMENT => sub {},
502     };
503    
504     local $_;
505     while (<$F>) { $lineno++;
506     s/\s+$//;
507     /^#/ and next;
508     /^$/ and next;
509     /^END/ and do { $cards{$card->{card_name}} = $card if $card; last };
510    
511     ($cmd, $val) = /(\S+)\s*(.*)/ or next;
512    
513     my $f = $fs->{$cmd};
514    
515     $f ? $f->() : log::l("unknown line $lineno ($_)");
516     }
517     \%cards;
518     }
519    
520     1;
521    

  ViewVC Help
Powered by ViewVC 1.1.30