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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1001 - (show annotations) (download)
Wed Apr 27 19:40:18 2011 UTC (12 years, 11 months ago) by anssi
File size: 17563 byte(s)
prefer boot display devices when probing cards (fixes at least an issue
with an SLI laptop as reported by Maarten Vanraes)
1 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 DRI_GLX_SPECIAL => $device->{Driver} eq 'nvidia' && eval { any { $_ eq 'glx' } $raw_X->get_modules },
47 %$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 # prefer the boot device
97 my @cards = sort { $b->{boot_device} cmp $a->{boot_device} } map {
98 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 boot_device => chomp_(cat_($_->{sysfs_device} . "/boot_vga")) || 0,
104 };
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 $bad_card ||= $card->{Driver} eq 'intel' || $card->{Driver} eq 'fbdev';
465 $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