phillipberndt / fakexrandr

Fake XRandR configurations for multi-head setups with crappy video drivers, like fakexinerama but with xrandr
270 stars 40 forks source link

Virtual Display faking XRandR resolutions / allowing resize? #41

Open vans163 opened 7 years ago

vans163 commented 7 years ago

I am having a problem and I wonder if this library can help fix it.

When I start a fake/virtual display without a CRT/DFP attached, xrandr -q only shows the screen. When an application wants to do things like find an appropriate resolution or resize it fails as there is no attached physical displays.

Example of an error.

X Error of failed request:  BadRRCrtc (invalid Crtc parameter)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  20 (RRGetCrtcInfo)
  Crtc id in failed request: 0x38
  Serial number of failed request:  60
  Current serial number in output stream:  60

My video card only has CRT-0 and DFP-0,1,2,3. I can spoof a monitor via an edid but i can only get up to 5 displays with xrandr this way, I am trying to get 10+ isolated from eachother displays with xrandr support.

Can fakexrandr help here when there is 0 displays attached, to fake this information and allow the resize to happen inside the virtual display?

phillipberndt commented 7 years ago

Yes, though you'll have to patch it to unconditionally add the fake outputs, and not only if there's a CRT with the correct resolution present.

Note that this library currently only works with Xlib. xcb applications will still see the real data. There's a PR for xcb support stuck in an early stage, feel free to pick it up if you'd like.

vans163 commented 7 years ago

I will look through the code tonight. Any tips where to start, I guess from the config parsing as the shim assumes there is 1 real display connected?

phillipberndt commented 7 years ago

config_handle_output is called for each output that has an edid. Outputs themselves are then added by _config_foreach_split. Alternatively, use the version with hard-coded splits - it is much more straightforward to read & modify.

vans163 commented 7 years ago

Thank you much easier, going to reference this, seems to be the same issue https://github.com/phillipberndt/fakexrandr/issues/11

vans163 commented 7 years ago

I managed to make 1 full fake screenresource but its failing at panning.

XRRScreenResources* fake_screenres;

XID fake_crt_xid = 63;
RRCrtc fake_crts[1];

XID fake_output_xid = 64;
RROutput fake_outputs[1];

XRRModeInfo fake_mode1;
XRRModeInfo fake_modes[1];
RRMode fake_mode_list[1];

XRRCrtcInfo fake_crt_info;
XRROutputInfo fake_output_info;

XRRScreenResources* XRRGetScreenResources(Display *dpy, Window window) {
    printf("screen resources\n");

    fake_screenres = _XRRGetScreenResources(dpy, window);

    memset(&fake_outputs, 0, sizeof(fake_outputs));

    memset(&fake_crt_info, 0, sizeof(fake_crt_info));
    fake_crt_info.timestamp = 76474;
    fake_crt_info.x = 0;
    fake_crt_info.y = 0;
    fake_crt_info.width = 600;
    fake_crt_info.height = 480;
    fake_crt_info.mode = 65;
    fake_crt_info.rotation = 1;
    fake_crt_info.noutput = 1;
    fake_crt_info.outputs = fake_outputs;
    fake_crt_info.rotations = 63;
    fake_crt_info.npossible = 1;
    fake_crt_info.possible = fake_outputs;

    memset(&fake_output_info, 0, sizeof(fake_output_info));
    memset(&fake_mode_list, 0, sizeof(fake_mode_list));
    fake_output_info.timestamp = 76474;
    fake_output_info.crtc = 63;
    fake_output_info.name = "HDMI-1";
    fake_output_info.nameLen = 6;
    fake_output_info.mm_width = 509;
    fake_output_info.mm_height = 286;
    fake_output_info.connection = 0;
    fake_output_info.subpixel_order = 0;
    fake_output_info.ncrtc = 1;
    fake_output_info.crtcs = fake_crts;
    fake_output_info.nclone = 0;
    fake_output_info.clones = 0;
    fake_output_info.nmode = 65;
    fake_output_info.npreferred = 1;

    fake_mode_list[0] = 65;
    fake_output_info.modes = fake_mode_list;

    memset(&fake_mode1, 0, sizeof(fake_mode1));
    fake_mode1.id = 65;
    fake_mode1.width = 600;
    fake_mode1.height = 480;
    fake_mode1.dotClock = 148500000;
    fake_mode1.hSyncStart = 2008;
    fake_mode1.hSyncEnd = 2052;
    fake_mode1.hTotal = 2200;
    fake_mode1.hSkew = 0;
    fake_mode1.vSyncStart = 1084;
    fake_mode1.vSyncEnd = 1089;
    fake_mode1.vTotal = 1125;
    fake_mode1.name = "1920x1080";
    fake_mode1.nameLength = 9;
    fake_mode1.modeFlags = 5;

    fake_screenres->timestamp = 76474;
    //fake_screenres->configTimestamp = 76474;
    fake_screenres->ncrtc = 1;
    fake_crts[0] = fake_crt_xid;
    fake_screenres->crtcs = fake_crts;

    fake_screenres->noutput = 1;
    fake_outputs[0] = fake_output_xid;
    fake_screenres->outputs = fake_outputs;

    fake_screenres->nmode = 1;
    fake_modes[0] = fake_mode1;
    fake_screenres->modes = fake_modes;

    return fake_screenres;
}

XRRScreenResources *XRRGetScreenResourcesCurrent(Display *dpy, Window window) {
    printf("screen resuorces current not called\n");

    return _XRRGetScreenResourcesCurrent(dpy, window);
}

XRRCrtcInfo *XRRGetCrtcInfo(Display *dpy, XRRScreenResources *resources, RRCrtc crtc) {
    return &fake_crt_info;
}

static XRRPanning * (*_XRRGetPanning)(Display *dpy, XRRScreenResources *resources, RRCrtc crtc);
XRRPanning * XRRGetPanning(Display *dpy, XRRScreenResources *resources, RRCrtc crtc) {
    printf("getpanning %d\n", crtc);

    return _XRRGetPanning(dpy, resources, crtc);
}
xrandr -q
init
screen resources
getCrtcInfo crtc 63
getCrtcInfo crtc 63
getpanning 63
X Error of failed request:  BadRRCrtc (invalid Crtc parameter)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  28 (RRGetPanning)
  Crtc id in failed request: 0x3f
  Serial number of failed request:  13
  Current serial number in output stream:  13

Any idea what can be wrong?

Also when this gets called

XRRCrtcInfo *XRRGetCrtcInfo(Display *dpy, XRRScreenResources *resources, RRCrtc crtc) {
    XRRCrtcInfo* retv = _XRRGetCrtcInfo(dpy, resources, crtc);
    return retv;
}

XRRCrtcInfo* retv = _XRRGetCrtcInfo(dpy, resources, crtc);

X Error of failed request:  BadRRCrtc (invalid Crtc parameter)
  Major opcode of failed request:  140 (RANDR)
  Minor opcode of failed request:  20 (RRGetCrtcInfo)
  Crtc id in failed request: 0x3f
  Serial number of failed request:  13
  Current serial number in output stream:  13

We can return our fake here instead of retv, but itl fail panning then.