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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4435 - (show annotations) (download)
Wed May 9 21:48:16 2012 UTC (11 years, 10 months ago) by tv
File size: 16746 byte(s)
(allowed) allow to select depth other than 16bit on Poulsbo (mga#5695)
1 package Xconfig::resolution_and_depth; # $Id: resolution_and_depth.pm 250289 2008-12-08 09:59:02Z pixel $
2
3 use diagnostics;
4 use strict;
5 # perl_checker: require MDK::Common
6 # perl_checker: require ugtk2
7 use common;
8
9
10 our %depth2text = (
11 8 => N_("256 colors (8 bits)"),
12 15 => N_("32 thousand colors (15 bits)"),
13 16 => N_("65 thousand colors (16 bits)"),
14 24 => N_("16 million colors (24 bits)"),
15 );
16 our @depths_available = ikeys(%depth2text);
17
18 my @bios_vga_modes = (
19 { bios => 769, X => 640, Y => 480, Depth => 8 },
20 { bios => 771, X => 800, Y => 600, Depth => 8 },
21 { bios => 773, X => 1024, Y => 768, Depth => 8 },
22 { bios => 775, X => 1280, Y => 1024, Depth => 8 },
23 { bios => 777, X => 1600, Y => 1200, Depth => 8 },
24 { bios => 784, X => 640, Y => 480, Depth => 15 },
25 { bios => 787, X => 800, Y => 600, Depth => 15 },
26 { bios => 790, X => 1024, Y => 768, Depth => 15 },
27 { bios => 793, X => 1280, Y => 1024, Depth => 15 },
28 { bios => 796, X => 1600, Y => 1200, Depth => 15 },
29 { bios => 785, X => 640, Y => 480, Depth => 16 },
30 { bios => 788, X => 800, Y => 600, Depth => 16 },
31 { bios => 791, X => 1024, Y => 768, Depth => 16 },
32 { bios => 794, X => 1280, Y => 1024, Depth => 16 },
33 { bios => 797, X => 1600, Y => 1200, Depth => 16 },
34 );
35
36 sub from_bios {
37 my ($bios) = @_;
38 my $bios_int = $bios =~ /^0x(.*)/ ? hex($1) : $bios;
39 find { $_->{bios} == $bios_int } @bios_vga_modes;
40 }
41
42 sub bios_vga_modes() { @bios_vga_modes }
43
44 sub size2default_resolution {
45 my ($size) = @_; #- size in inch
46
47 require detect_devices;
48 if (arch() =~ /ppc/) {
49 return "1024x768" if detect_devices::get_mac_model() =~ /^PowerBook|^iMac/;
50 } elsif (detect_devices::is_xbox()) {
51 return "640x480";
52 }
53
54 my %monitorSize2resolution = (
55 13 => "640x480",
56 14 => "800x600",
57 15 => "800x600",
58 16 => "1024x768",
59 17 => "1024x768",
60 18 => "1024x768",
61 19 => "1280x1024",
62 20 => "1280x1024",
63 21 => "1600x1200",
64 22 => "1600x1200",
65 );
66 $monitorSize2resolution{round($size)} || ($size < 13 ? "640x480" : "1600x1200");
67 }
68
69 sub XxY { &Xconfig::xfree::XxY }
70
71 sub to_string {
72 my ($resolution) = @_;
73 $resolution or return '';
74
75 $resolution->{automatic}
76 ? N("Automatic") . ($resolution->{Depth} ? sprintf(" (%dbpp)", $resolution->{Depth}) : '')
77 : $resolution->{X} ? sprintf("%sx%s %dbpp", @$resolution{'X', 'Y', 'Depth'}) : 'frame-buffer';
78 }
79
80 sub allowed {
81 my ($card) = @_;
82
83 my ($prefered_depth, @resolution_and_depth);
84
85 if ($card->{Driver} eq 'fbdev' && $card->{BoardName} !~ /Poulsbo/) {
86 @resolution_and_depth = grep { $_->{Depth} == 16 } @bios_vga_modes;
87 } else {
88 my @depths;
89 if (member($card->{Driver}, qw(fglrx qxl savage))) {
90 @depths = 24;
91 } elsif ($card->{BoardName} eq 'NVIDIA RIVA 128') {
92 @depths = qw(8 15 24);
93 } elsif ($card->{use_DRI_GLX}) {
94 $prefered_depth = 24;
95 @depths = (16, 24);
96 } else {
97 @depths = our @depths_available;
98 }
99 my @resolutions = @Xconfig::xfree::resolutions;
100
101 push @resolution_and_depth,
102 map {
103 my $Depth = $_;
104 map { m/(\d+)x(\d+)/ && { X => $1, Y => $2, Depth => $Depth } } @resolutions;
105 } @depths;
106 }
107 $prefered_depth, @resolution_and_depth;
108 }
109
110 # ($card->{VideoRam} || ($card->{server} eq 'FBDev' ? 2048 : 32768))
111 sub filter_using_VideoRam {
112 my ($VideoRam, @resolutions) = @_;
113 my $mem = 1024 * $VideoRam;
114 grep { $_->{X} * $_->{Y} * $_->{Depth}/8 <= $mem } @resolutions;
115
116 }
117 sub filter_using_HorizSync_VertRefresh {
118 my ($HorizSync, $VertRefresh, @resolutions) = @_;
119 my $max_hsync = 1000 * max(split(/[,-]/, $HorizSync));
120 my ($min_vsync, $max_vsync) = (min(split(/[,-]/, $VertRefresh)), max(split(/[,-]/, $VertRefresh)));
121
122 #- enforce at least 60Hz, if max_vsync > 100 (ie don't do it on LCDs which are ok with low vsync)
123 $min_vsync = max(60, $min_vsync) if $max_vsync > 100;
124
125 #- computing with {Y} which is active sync instead of total sync, but that's ok
126 grep { $max_hsync / $_->{Y} > $min_vsync } @resolutions;
127 }
128
129 sub choose {
130 my ($in, $default_resolution, @resolutions) = @_;
131
132 my @Depths = uniq(reverse map { $_->{Depth} } @resolutions);
133 my $resolution = $default_resolution || {};
134 $in->ask_from(N("Resolutions"), "",
135 [ {
136 val => \$resolution, type => 'list', sort => 0,
137 list => [ (sort { $a->{X} <=> $b->{X} } @resolutions),
138 (map { { automatic => 1, Depth => $_ } } @Depths) ],
139 format => \&to_string,
140 } ]) or return;
141 $resolution;
142 }
143
144
145 sub choices {
146 my ($_raw_X, $resolution_wanted, $card, $monitors) = @_;
147 $resolution_wanted ||= {};
148
149 my ($prefered_depth, @resolutions) = allowed($card);
150
151 @resolutions = filter_using_HorizSync_VertRefresh($monitors->[0]{HorizSync}, $monitors->[0]{VertRefresh}, @resolutions) if $monitors->[0]{HorizSync};
152 @resolutions = filter_using_VideoRam($card->{VideoRam}, @resolutions) if $card->{VideoRam};
153
154 #- sort it, so we can take the first one when we want the "best"
155 @resolutions = sort { $b->{X} <=> $a->{X} || $b->{Y} <=> $a->{Y} || $b->{Depth} <=> $a->{Depth} } @resolutions;
156
157 $_->{ratio} ||= Xconfig::xfree::resolution2ratio($_) foreach @resolutions;
158
159 if ($resolution_wanted->{automatic} || !$resolution_wanted->{X} && !$monitors->[0]{HorizSync}) {
160 return { automatic => 1, Depth => $resolution_wanted->{Depth} }, @resolutions;
161 }
162
163 if ($resolution_wanted->{X} && !$resolution_wanted->{Y}) {
164 #- assuming ratio 4/3
165 $resolution_wanted->{Y} = round($resolution_wanted->{X} * 3 / 4);
166 } elsif (!$resolution_wanted->{X}) {
167 if ($monitors->[0]{preferred_resolution}) {
168 put_in_hash($resolution_wanted, $monitors->[0]{preferred_resolution});
169 } elsif ($monitors->[0]{ModelName} =~ /^Flat Panel (\d+)x(\d+)$/) {
170 put_in_hash($resolution_wanted, { X => $1, Y => $2 });
171 } elsif ($monitors->[0]{diagonal_size}) {
172 my ($X, $Y) = split('x', size2default_resolution($monitors->[0]{diagonal_size} * 1.08));
173 put_in_hash($resolution_wanted, { X => $X, Y => $Y });
174 } else {
175 put_in_hash($resolution_wanted, { X => 1024, Y => 768 });
176 }
177 }
178 my @matching = grep { $_->{X} eq $resolution_wanted->{X} && $_->{Y} eq $resolution_wanted->{Y} } @resolutions;
179 if (!@matching) {
180 #- hard choice :-(
181 #- first trying the greater resolution with same ratio
182 my $ratio = $resolution_wanted->{X} / $resolution_wanted->{Y};
183 @matching = grep { abs($ratio - $_->{X} / $_->{Y}) < 0.01 } @resolutions;
184 }
185 if (!@matching) {
186 #- really hard choice :'-(
187 #- take the first available resolution <= the wanted resolution
188 @matching = grep { $_->{X} < $resolution_wanted->{X} } @resolutions;
189 }
190 if (!@matching) {
191 @matching = @resolutions;
192 }
193
194 my $default_resolution;
195 foreach my $Depth ($resolution_wanted->{Depth}, $prefered_depth) {
196 $Depth and $default_resolution ||= find { $_->{Depth} eq $Depth } @matching;
197 }
198 $default_resolution ||= $matching[0];
199
200 $default_resolution, @resolutions;
201 }
202
203 sub configure {
204 my ($in, $raw_X, $card, $monitors, $b_auto, $o_resolution) = @_;
205
206 my ($default_resolution, @resolutions) = choices($raw_X, $o_resolution || $raw_X->get_resolution, $card, $monitors);
207
208 my $resolution;
209 if ($b_auto) {
210 #- use $default_resolution
211 if ($card->{Driver} eq 'fglrx' && !$default_resolution->{automatic}) {
212 $resolution = first(find { $default_resolution->{Y} eq $_->{Y} && $_->{Depth} == 24 }
213 $default_resolution, @resolutions);
214 $resolution ||= first(find { $_->{Depth} == 24 } $resolution, @resolutions);
215 }
216 } elsif ($in->isa('interactive::gtk')) {
217 $resolution = choose_gtk($in, $card, $default_resolution, @resolutions) or return;
218 } else {
219 $resolution = choose($in, $default_resolution, @resolutions) or return;
220 }
221 set_resolution_($raw_X, $card, $monitors, $default_resolution, $resolution, @resolutions);
222 }
223
224 sub configure_auto_install {
225 my ($raw_X, $card, $monitors, $old_X) = @_;
226
227 my ($default_resolution, @resolutions);
228 if ($old_X->{resolution_wanted} eq 'automatic') {
229 $default_resolution = { automatic => 1 };
230 } else {
231 my $resolution_wanted = $old_X->{resolution_wanted} && do {
232 my ($X, $Y) = split('x', $old_X->{resolution_wanted});
233 { X => $X, Y => $Y, Depth => $old_X->{default_depth} };
234 };
235
236 ($default_resolution, @resolutions) = choices($raw_X, $resolution_wanted, $card, $monitors);
237 $default_resolution or die "you selected an unusable depth";
238 }
239 set_resolution($raw_X, $card, $monitors, $default_resolution, @resolutions);
240 }
241
242 sub set_resolution {
243 my ($raw_X, $card, $monitors, $resolution, @other) = @_;
244 set_resolution_($raw_X, $card, $monitors, $resolution, $resolution, @other);
245 }
246 sub set_resolution_ {
247 my ($raw_X, $card, $monitors, $default_resolution, $resolution, @other) = @_;
248
249 my $PreferredMode;
250 if (!$resolution->{automatic}) {
251 my $ratio = Xconfig::xfree::resolution2ratio($resolution, 'non-strict');
252 @other = uniq_ { XxY($_) } @other;
253 @other = grep { $_->{X} < $resolution->{X} } @other;
254 @other = filter_on_ratio($ratio, @other);
255
256 set_915resolution($resolution) if is_915resolution_configured();
257
258 if (XxY($default_resolution) ne XxY($resolution)) {
259 log::l("setting PreferredMode since wanted resolution (" . XxY($resolution) . ") differs from the default one (" . XxY($default_resolution) . ")");
260 $PreferredMode = XxY($resolution);
261 }
262 }
263 if ($monitors->[0]{PreferredMode} ne $PreferredMode) {
264 if ($PreferredMode) {
265 $monitors->[0]{PreferredMode} = $PreferredMode;
266 } else {
267 delete $monitors->[0]{PreferredMode};
268 }
269 $raw_X->set_monitors(@$monitors);
270 }
271 if ($card->{Driver} eq 'geode') {
272 $card->{Options}{PanelGeometry} = XxY($resolution);
273 Xconfig::card::to_raw_X($card, $raw_X);
274 }
275
276 set_default_background($resolution);
277 my $resolutions = [ $resolution, @other ];
278 $raw_X->set_resolutions($resolutions);
279 $resolutions;
280 }
281 sub set_default_background {
282 my ($resolution) = @_;
283
284 $resolution->{X} && $resolution->{Y} or do {
285 $resolution = { X => 1024, Y => 768 };
286 log::l("defaulting background resolution to $resolution->{X}x$resolution->{Y}");
287 };
288
289 my $ratio = $resolution->{X} / $resolution->{Y};
290 my $dir = "$::prefix/usr/share/mga/backgrounds";
291 my %theme = getVarsFromSh("$::prefix/etc/sysconfig/bootsplash");
292
293 my @l = map {
294 if (my ($X, $Y, undef, $hour) = /^\Q$theme{THEME}\E-(\d+)x(\d+)(-(.*))?.jpg$/) {
295 { file => $_, X => $X, Y => $Y, hour => $hour };
296 } else { () }
297 } all($dir);
298
299 my ($best, $_other) =
300 sort {
301 $a->[2] <=> $b->[2] || $b->[3] <=> $a->[3] || $a->[4] <=> $b->[4];
302 } map {
303 [
304 $_->{X}, $_->{Y},
305 int(abs($ratio - $_->{X} / $_->{Y}) * 100), #- we want the nearest ratio (precision .01)
306 $_->{X} >= $resolution->{X}, #- then we don't want a resolution smaller
307 abs($_->{X} - $resolution->{X}), #- the nearest resolution
308 ];
309 } @l;
310
311 my @wanted = grep { $best->[0] == $_->{X} && $best->[1] == $_->{Y} } @l;
312
313 if (-e "$dir/$theme{THEME}.xml") {
314 symlinkf "$theme{THEME}.xml", "$dir/Mageia.xml";
315 }
316
317 foreach (@wanted) {
318 if ($_->{hour}) {
319 symlinkf $_->{file}, "$dir/$theme{THEME}-$_->{hour}.jpg";
320 } else {
321 symlinkf $_->{file}, "$dir/default.jpg";
322 }
323 }
324 }
325 sub is_915resolution_configured() {
326 my $f = "$::prefix/etc/sysconfig/915resolution";
327 -e $f && { getVarsFromSh($f) }->{XRESO};
328 }
329 sub set_915resolution {
330 my ($resolution) = @_;
331
332 my $f = "$::prefix/etc/sysconfig/915resolution";
333 setVarsInSh($f, {
334 MODE => 'best',
335 XRESO => $resolution->{X},
336 YRESO => $resolution->{Y},
337 });
338 run_program::rooted($::prefix, 'service', '915resolution', 'start');
339 }
340
341 sub filter_on_ratio {
342 my ($ratio, @l) = @_;
343 grep {
344 !$ratio
345 || $_->{ratio} eq $ratio
346 || $ratio eq '4/3' && "$_->{X}x$_->{Y}" eq '1280x1024';
347 } @l;
348 }
349
350 sub choose_gtk {
351 my ($in, $card, $default_resolution, @resolutions) = @_;
352
353 my $chosen_Depth = $default_resolution->{Depth};
354 my $chosen_res = { X => $default_resolution->{X} || 1024, Y => $default_resolution->{Y} };
355 my $chosen_ratio = Xconfig::xfree::resolution2ratio($chosen_res, 'non-strict') || '4/3';
356
357 my $filter_on_Depth = sub {
358 grep { $_->{Depth} == $chosen_Depth } @_;
359 };
360 my $filter_on_res = sub {
361 grep { $_->{X} == $chosen_res->{X} && $_->{Y} == $chosen_res->{Y} } @_;
362 };
363 my $automatic_resolution = { automatic => 1, text => N_("Automatic") };
364 $chosen_res =
365 $default_resolution->{automatic} ? $automatic_resolution :
366 #- $chosen_res must be one of @resolutions, so that it has a correct {ratio} field
367 first($filter_on_res->(@resolutions)) || $resolutions[0];
368
369 require ugtk2;
370 mygtk2->import;
371 ugtk2->import(qw(:create :helpers :wrappers));
372 my $W = ugtk2->new(N("Resolution"), modal => 1);
373
374 my %monitor_images_x_res = do {
375 my @l = qw(640 800 1024 1152 1280 1400 1600 1920 2048);
376 my %h = map { $_ => ugtk2::_find_imgfile("monitor-$_.png") } @l;
377
378 #- for the other, use the biggest smaller
379 foreach my $x_res (uniq map { $_->{X} } @resolutions) {
380 my $x_res_ = max(grep { $_ <= $x_res } @l);
381 $h{$x_res} ||= $h{$x_res_} || $h{640};
382 }
383 %h;
384 };
385
386 my $res2text = sub { "$_[0]{X}x$_[0]{Y}" . ($chosen_ratio || $_[0]{ratio} =~ /other/ ? '' : " ($_[0]{ratio})") };
387 my @matching_ratio;
388 my $proposed_resolutions = [];
389 my $set_proposed_resolutions = sub {
390 my ($suggested_res) = @_;
391 @matching_ratio = filter_on_ratio($chosen_ratio, @resolutions);
392 gtkval_modify(\$proposed_resolutions, [
393 (reverse uniq_ { $res2text->($_) } @matching_ratio),
394 $automatic_resolution,
395 if_($chosen_ratio, { text => N_("Other") }),
396 ]);
397 if ($suggested_res->{automatic}) {
398 gtkval_modify(\$chosen_res, $automatic_resolution);
399 } elsif (!$filter_on_res->(@matching_ratio)) {
400 my $res = $suggested_res || find { $_->{X} == $chosen_res->{X} } @matching_ratio;
401 gtkval_modify(\$chosen_res, $res || $matching_ratio[0]);
402 }
403 };
404 $set_proposed_resolutions->($chosen_res);
405
406 my $depth_combo = gtknew('ComboBox', width => 220,
407 text_ref => \$chosen_Depth,
408 format => sub { translate($depth2text{$_[0]}) },
409 list => [ uniq(reverse map { $_->{Depth} } @resolutions) ],
410 changed => sub {
411 my @matching_Depth = $filter_on_Depth->(@matching_ratio);
412 if (!$filter_on_res->(@matching_Depth) && !$chosen_res->{automatic}) {
413 gtkval_modify(\$chosen_res, $matching_Depth[0]);
414 }
415 });
416 my $pix_colors = gtknew('Image',
417 file_ref => \$chosen_Depth,
418 format => sub {
419 $_[0] >= 24 ? "colors.png" : $_[0] >= 15 ? "colors16.png" : "colors8.png";
420 });
421 my $previous_res = $chosen_res;
422 my $res_combo = gtknew('ComboBox',
423 text_ref => \$chosen_res,
424 format => sub { $_[0]{text} ? translate($_[0]{text}) : &$res2text },
425 list_ref => \$proposed_resolutions,
426 changed => sub {
427 if ($chosen_res->{text} eq 'Other') {
428 undef $chosen_ratio;
429 $set_proposed_resolutions->($previous_res);
430 } elsif (!$chosen_res->{automatic}) {
431 my @matching_res = $filter_on_res->(@matching_ratio);
432 if (!$filter_on_Depth->(@matching_res)) {
433 gtkval_modify(\$chosen_Depth, $matching_res[0]{Depth});
434 }
435 }
436 $previous_res = $chosen_res;
437 });
438 my $pixmap_mo = gtknew('Image',
439 file_ref => \$chosen_res,
440 format => sub {
441 my $X = $_[0]{X} || '1024';
442 $monitor_images_x_res{$X} or internal_error("no image for resolution $X");
443 });
444
445 my $help_sub = $in->interactive_help_sub_display_id('configureX_resolution');
446 gtkadd($W->{window},
447 gtkpack_($W->create_box_with_title(N("Choose the resolution and the color depth"),
448 if_($card->{BoardName}, "(" . N("Graphics card: %s", $card->{BoardName}) . ")"),
449 ),
450 1, '',
451 0, $pixmap_mo,
452 0, gtknew('HBox', children => [
453 1, '',
454 0, gtknew('Table', col_spacings => 5, row_spacings => 5,
455 children => [
456 [ $res_combo, gtknew('Label', text => "") ],
457 [ $depth_combo, gtknew('Frame', shadow_type => 'etched_out', child => $pix_colors) ],
458 ]),
459 1, '',
460 ]),
461 1, '',
462 0, gtkadd($W->create_okcancel(N("Ok"), N("Cancel"), '', if_($help_sub, [ N("Help"), $help_sub, 1 ]))),
463 ));
464 $W->{ok}->grab_focus;
465
466 $W->main or return;
467
468 if ($chosen_res->{automatic}) {
469 $chosen_res->{Depth} = $chosen_Depth;
470 $chosen_res;
471 } else {
472 find { $_->{X} == $chosen_res->{X} &&
473 $_->{Y} == $chosen_res->{Y} &&
474 $_->{Depth} == $chosen_Depth } @resolutions;
475 }
476 }
477
478 1;

  ViewVC Help
Powered by ViewVC 1.1.30