← Back to team overview

hybrid-graphics-linux team mailing list archive

Fwd: [ubuntu-x] Hybrid graphics detection

 

Thought you guys might be interested.

- Eric

-------- Original Message --------
Subject: 	[ubuntu-x] Hybrid graphics detection
Date: 	Mon, 31 Oct 2011 11:36:39 -0700
From: 	Evan Broder <evan@xxxxxxxxxxx>
To: 	ubuntu-x <ubuntu-x@xxxxxxxxxxxxxxxx>



At the hybrid graphics session today, we discussed how we could detect
which GPU was actively being used in a hybrid graphics configuration.
I have some code that I've been using to do this, using libpciaccess.

It's based on the code that X itself uses to pick which drivers to
load at startup, so it likely suffers from some of the issues we
discussed in the session. But it does seem to work for nVidia Optimus,
which is the only hybrid graphics system I have access to.

I'm currently using the following Upstart job when either
nvidia-current or fglrx are installed:

 start on starting gdm

 task
 script
     if [ "$(hybrid-detect)" = "integrated" ]; then
         update-alternatives --set gl_conf /usr/lib/mesa/ld.so.conf
         ldconfig
     fi
 end script

Both of these are a bit rough around the edges, and would definitely
need some tuning before being adapted by Ubuntu in general.

- Evan


/* hybrid-detect:
 *
 * Detect which GPU in a hybrid graphics configuration should be
 * used
 *
 * Based on code from ./hw/xfree86/common/xf86pciBus.c in xorg-server
 *
 * Build with `gcc -o hybrid-detect hybrid-detect.c $(pkg-config --cflags --libs pciaccess)`
 */

#include <stdio.h>
#include <pciaccess.h>

#define PCI_CLASS_PREHISTORIC           0x00

#define PCI_CLASS_DISPLAY               0x03

#define PCI_CLASS_MULTIMEDIA            0x04
#define PCI_SUBCLASS_MULTIMEDIA_VIDEO   0x00

#define PCI_CLASS_PROCESSOR             0x0b
#define PCI_SUBCLASS_PROCESSOR_COPROC   0x40

#define PCIINFOCLASSES(c)                                               \
    ( (((c) & 0x00ff0000) == (PCI_CLASS_PREHISTORIC << 16))             \
      || (((c) & 0x00ff0000) == (PCI_CLASS_DISPLAY << 16))              \
      || ((((c) & 0x00ffff00)                                           \
           == ((PCI_CLASS_MULTIMEDIA << 16) | (PCI_SUBCLASS_MULTIMEDIA_VIDEO << 8)))) \
      || ((((c) & 0x00ffff00)                                           \
           == ((PCI_CLASS_PROCESSOR << 16) | (PCI_SUBCLASS_PROCESSOR_COPROC << 8)))) )

static struct pci_slot_match match = {
    PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, PCI_MATCH_ANY, 0
};

int main(int argc, char *argv[]) {
    pci_system_init();

    struct pci_device_iterator *iter = pci_slot_match_iterator_create(&match);
    if (!iter)
        return 1;

    struct pci_device *info;
    while ((info = pci_device_next(iter)) != NULL) {
        if (PCIINFOCLASSES(info->device_class) &&
            pci_device_is_boot_vga(info)) {
            if (info->vendor_id == 0x8086)
                printf("integrated\n");
            else
                printf("discrete\n");
            break;
        }
    }

    pci_iterator_destroy(iter);
    return 0;
}
-- 
Ubuntu-x mailing list
Ubuntu-x@xxxxxxxxxxxxxxxx
Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/ubuntu-x