disper -s selects wrong screen

Bug #1060365 reported by Jacob Beck
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
disper
New
Undecided
Unassigned

Bug Description

This bug is for the trunk build of disper, version 0.3.99. I am comparing it to disper version 0.3.0 (the one supplied by my distribution)

I am running on OpenSuse 12.2 x86_64 with nvidia binary drivers v304.43. I have a thinkpad that sits in a docking station at work, with two displays plugged in via VGA and DVI. The main laptop screen is off except when I undock. When undocking I run "disper -s" to switch to the laptop screen. When I re-dock, I run "disper --displays=CRT-0,DFP-3 -e" to get an extended desktop across both monitors. Unfortunately, since upgrading to nvidia 304.x drivers I get all the xrandr-related errors.

When running "disper -s" with the trunk build of disper, I get the wrong screen. Since the "-s" flag doesn't accept display arguments I can't force it onto the right screen. I assume it is related to the change in ordering of "disper -l" output I've observed between versions - on the new version the VGA connection is first, on the old one the internal laptop screen is first.

I've attached my the output of both disper versions, the contents of Xorg.0.log, and dmesg output as a concatenated file since I couldn't figure out how to attach multiple files.
Sorry if that's an inconvenience, let me know if there's anything else I can supply.

Revision history for this message
Jacob Beck (beckjake) wrote :

A bit of debugging work I did to try to figure out what the deal is below.

The list of displays is generated by xrandr.core.Screen, specifically the 'outputs' dict generated in Screen._load_outputs. I'm reasonably proficient with python but I don't know anything about xrandr, so I naively tried replacing all calls in Screen to self.outputs.values() and self.outputs.keys() with self.outputs_values() and self.outputs_keys(), respectively. They work like this:

def outputs_values(self):
  olist = []
  for name in self.outputs.keys():
    if name.startswith('LVDS'): #internal laptop connector
      olist.insert(0, self.outputs[name])
    else:
      olist.append(self.outputs[name])
    return olist

outputs_keys follows the same principle but with keys instead of values.

When I do this, I get the right output order with "./disper.py -l" and "./disper.py --displays=VGA-0,DP-2 -e" works like it always did. But "./disper.py -s" throws an exception that begins at Screen.apply_output_config() on the 'raise RRError' line. It's right below a FIXME comment but I doubt that's the issue.

Stepping through the loading code, it appears that the LVDS-0 interface doesn't, in fact, have a crtc set. I don't know nearly enough about xrandr to understand why that would be. However, it looks like the code that sets that functionality involves querying libXrandr.so.2 directly, in Screen._load_outputs():

xrroutputinfo = goi(self._display, self_resources, o[i])
output = Output(xrroutputinfo, o[i], self)
crtc = self.get_crtc_by_xid(output.get_crtc()).

Some investigation via pdb reveals the following: output.get_crtc() returns 0 for 'LVDS-0' and so self.get_crtc_by_xid() returns None when I check it in the debugger in LVDS-0's part of the loop. The other two displays return >0 values and self._get_crtc_by_xid() returns something. I considered injecting my own values into there from the debugger or via a similar trick to the outputs_keys and outputs_values, but I don't think that's really going to help.

I hope all that helps you out a little, even if it just ends up being a WONTFIX or nVidia driver bug.

Revision history for this message
Jacob Beck (beckjake) wrote :
Revision history for this message
Jacob Beck (beckjake) wrote :
Revision history for this message
Jacob Beck (beckjake) wrote :
Revision history for this message
wvengen (wvengen) wrote :

Hi Jacob, thanks for your extensive post! I'll look into it later when I have more time. Disper should accept a -d argument also when using -s or -S. Perhaps that may be a temporary workaround.

Revision history for this message
Jacob Beck (beckjake) wrote :

Okay, the -d argument has the same issue. After some fiddling about with the xrandr utility, I have come to an interesting conclusion. With only one graphics device that has 3 monitors plugged in, only two can be 'active' at a given time. To my knowledge, that's a known limitation of pretty much every graphics card and is therefore expected behavior. What was unexpected is that only 'active' monitors seem to have a crtc value (or maybe only active monitors can be queried, same end result). So if I want to switch to my laptop screen:

xrandr --output VGA-0 --off --output DP-2 --off; xrandr --output LVDS-0 --auto

And if I want to switch back:
xrandr --output LVDS-0 --off; xrandr --output VGA-0 --auto --output DP-2 --right-of VGA-0

The results of this are a little flaky, but work most of the time. I'd rather do it through disper since it's a much nicer interface.

I don't see how my xrandr discoveries would map to what disper does, especially in the general case. Perhaps you have more insight into the workings of the xrandr library.
I can't think of a way to get crtc information for the 'off' monitor without disabling an active one first. I assume it's necessary for enabling (hence the exception) so maybe some sort of switching at the point where you know what the user wants?

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.