bool IT87x::start(IOService * provider)
{
	DebugLog("starting ...");
  
	if (!super::start(provider))
		return false;
	
	InfoLog("found ITE %s", getModelName());
  OSDictionary* list = OSDynamicCast(OSDictionary, getProperty("Sensors Configuration"));

  OSDictionary *configuration=NULL; 
  OSData *data;
  IORegistryEntry * rootNode = fromPath("/efi/platform", gIODTPlane);

  if(rootNode) {
    data = OSDynamicCast(OSData, rootNode->getProperty("OEMVendor"));
    if (data) {
      bcopy(data->getBytesNoCopy(), vendor, data->getLength());
      OSString * VendorNick = vendorID(OSString::withCString(vendor));
      if (VendorNick) {
        data = OSDynamicCast(OSData, rootNode->getProperty("OEMBoard"));
        if (!data) {
          WarningLog("no OEMBoard");
          data = OSDynamicCast(OSData, rootNode->getProperty("OEMProduct"));
        }
        if (data) {
          bcopy(data->getBytesNoCopy(), product, data->getLength());
          OSDictionary *link = OSDynamicCast(OSDictionary, list->getObject(VendorNick));
          if (link){
            configuration = OSDynamicCast(OSDictionary, link->getObject(OSString::withCString(product)));
            InfoLog(" mother vendor=%s product=%s", vendor, product);
          }
        }
      } else {
        WarningLog("unknown OEMVendor %s", vendor);
      }
    } else {
      WarningLog("no OEMVendor");
    }
  }
  
  if (list && !configuration) {
    configuration = OSDynamicCast(OSDictionary, list->getObject("Default"));
    WarningLog("set default configuration");
  }
  
  if(configuration) {
    this->setProperty("Current Configuration", configuration);
  }
	
	// Temperature Sensors
	if (configuration) {
		for (int i = 0; i < 3; i++) {
			char key[8];
			
			snprintf(key, 8, "TEMPIN%X", i);
      if(readTemperature(i)<MAX_TEMP_THRESHOLD) { // Need to check if temperature sensor valid
        if (OSString* name = OSDynamicCast(OSString, configuration->getObject(key))) {
          if (name->isEqualTo("CPU")) {
            if (!addSensor(KEY_CPU_HEATSINK_TEMPERATURE, TYPE_SP78, 2, kSuperIOTemperatureSensor, i)) {
              WarningLog("error adding heatsink temperature sensor");
            }
          }
          else if (name->isEqualTo("System")) {
            if (!addSensor(KEY_NORTHBRIDGE_TEMPERATURE, TYPE_SP78, 2, kSuperIOTemperatureSensor,i)) {
              WarningLog("error adding system temperature sensor");
            }
          }
          else if (name->isEqualTo("Ambient")) {
            if (!addSensor(KEY_AMBIENT_TEMPERATURE, TYPE_SP78, 2, kSuperIOTemperatureSensor,i)) {
              WarningLog("error adding Ambient temperature sensor");
            }
          }
        }
      }
		}
	}
	else {
    if(readTemperature(0)<MAX_TEMP_THRESHOLD)  // Need to check if temperature sensor valid
      if (!addSensor(KEY_CPU_HEATSINK_TEMPERATURE, TYPE_SP78, 2, kSuperIOTemperatureSensor, 0)) {
        WarningLog("error adding heatsink temperature sensor");
      }
    if(readTemperature(1)<MAX_TEMP_THRESHOLD)  // Need to check if temperature sensor valid
      if (!addSensor(KEY_AMBIENT_TEMPERATURE, TYPE_SP78, 2, kSuperIOTemperatureSensor, 1)) {
        WarningLog("error adding Ambient temperature sensor");
      }
    if(readTemperature(2)<MAX_TEMP_THRESHOLD)  // Need to check if temperature sensor valid
      if (!addSensor(KEY_NORTHBRIDGE_TEMPERATURE, TYPE_SP78, 2, kSuperIOTemperatureSensor, 2)) {
        WarningLog("error adding system temperature sensor");
      }
	}
	
	
	// Voltage
  UInt8 tmp = readByte(address, ITE_ADC_CHANNEL_ENABLE);
  DebugLog("ADC Enable register = %X",tmp);
  
  vbat_updates = false;
  if(configuration)
  {
    OSBoolean* smartGuard = OSDynamicCast(OSBoolean, configuration->getObject("VBATNeedUpdates"));
    if(smartGuard && smartGuard->isTrue())
        vbat_updates=true;
  }
  // Refresh VBAT reading on each access to the key
  if(vbat_updates)
    writeByte(address, ITE_CONFIGURATION_REGISTER, readByte(address, ITE_CONFIGURATION_REGISTER) | 0x40);
  
	if (configuration) {
		for (int i = 0; i < 9; i++) {		
			char key[5];
      OSString * name;
      long Ri=0;
      long Rf=1;
      long Vf=0;
			
			snprintf(key, 5, "VIN%X", i);
			
			if (process_sensor_entry(configuration->getObject(key), &name, &Ri, &Rf, &Vf)) {
				if (name->isEqualTo("CPU")) {
					if (!addSensor(KEY_CPU_VRM_SUPPLY0, TYPE_FP2E, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf))
						WarningLog("error adding CPU voltage sensor");
				}
				else if (name->isEqualTo("Memory")) {
					if (!addSensor(KEY_MEMORY_VOLTAGE, TYPE_FP2E, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf))
						WarningLog("error adding memory voltage sensor");
				}
        else if (name->isEqualTo("+5VC")) {  
          if (!addSensor(KEY_5VC_VOLTAGE, TYPE_SP4B, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding AVCC Voltage Sensor!");
          }
        }
        else if (name->isEqualTo("+5VSB")) {  
          if (!addSensor(KEY_5VSB_VOLTAGE, TYPE_SP4B, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding AVCC Voltage Sensor!");
          }
        }                
        else if (name->isEqualTo("+12VC")) {
          if (!addSensor(KEY_12V_VOLTAGE, TYPE_SP4B, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding 12V Voltage Sensor!");
          }
        }
        else if (name->isEqualTo("-12VC")) {
          if (!addSensor(KEY_N12VC_VOLTAGE, TYPE_SP4B, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding 12V Voltage Sensor!");
          }
        }
        else if (name->isEqualTo("3VCC")) {
          if (!addSensor(KEY_3VCC_VOLTAGE, TYPE_FP2E, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding 3VCC Voltage Sensor!");
          }
        }
        
        else if (name->isEqualTo("3VSB")) {
          if (!addSensor(KEY_3VSB_VOLTAGE, TYPE_FP2E, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding 3VSB Voltage Sensor!");
          }
        }
        else if (name->isEqualTo("VBAT")) {
          if (!addSensor(KEY_VBAT_VOLTAGE, TYPE_FP2E, 2, kSuperIOVoltageSensor, i,Ri,Rf,Vf)) {
            WarningLog("ERROR Adding VBAT Voltage Sensor!");
          }
        }
			}
		}
	}
	
	// Tachometers
	for (int i = 0; i < 5; i++) {
		OSString* name = NULL;
		char key[5];
		if (configuration) {
			char key_temp[7];
			
			snprintf(key_temp, 7, "FANIN%X", i);
			
			name = OSDynamicCast(OSString, configuration->getObject(key_temp));
		}
		
		UInt32 nameLength = name ? (UInt32)strlen(name->getCStringNoCopy()) : 0;
		
		if (readTachometer(i) > 10 || nameLength > 0) {
      // Pff WTF ??? Add tachometer if it doesn't exist in a system but only the name defined in the config???   
       
			if (!addTachometer(i, (nameLength > 0 ? name->getCStringNoCopy() : 0)))
        // Need to look at this a bit later
				WarningLog("error adding tachometer sensor %d", i);      
    }
    
    // Check if this chip support SmartGuardian feature  
    
    hasSmartGuardian=false;
    if(configuration) {
      if(OSBoolean* smartGuard=OSDynamicCast(OSBoolean, configuration->getObject("SmartGuardian")))
        if(smartGuard->isTrue())
          hasSmartGuardian=true;      
    }
    
    if(hasSmartGuardian) {
      // Ugly development hack started for (SuperIOSensorGroup)
      snprintf(key,5,KEY_FORMAT_FAN_TARGET_SPEED,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardPWMControl, i))
        WarningLog("error adding PWM fan control");
      
      snprintf(key,5,KEY_FORMAT_FAN_START_TEMP,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardTempFanStart, i))
        WarningLog("error adding start temp fan control");
      
      snprintf(key,5,KEY_FORMAT_FAN_OFF_TEMP,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardTempFanStop, i))
        WarningLog("error adding stop temp fan control");
      
      snprintf(key,5,KEY_FORMAT_FAN_FULL_TEMP,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardTempFanFullOn, i))
        WarningLog("error adding full speed temp fan control");
      
      snprintf(key,5,KEY_FORMAT_FAN_START_PWM,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardPWMStart, i))
        WarningLog("error adding start PWM fan control");
      
      snprintf(key,5,KEY_FORMAT_FAN_TEMP_DELTA,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardTempFanFullOff, i))
        WarningLog("error adding temp full off fan control");
      
      snprintf(key,5,KEY_FORMAT_FAN_CONTROL,i);
      if (!addSensor(key, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardTempFanControl, i))
        WarningLog("error adding register fan control");
    }
	}
  if(hasSmartGuardian) {
    if (!addSensor(KEY_FORMAT_FAN_MAIN_CONTROL, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardMainControl, 0))
      WarningLog("error adding Main fan control"); 
    if (!addSensor(KEY_FORMAT_FAN_REG_CONTROL, TYPE_UI8, 1, (SuperIOSensorGroup)kSuperIOSmartGuardRegControl, 0))
      WarningLog("error adding Main fan control"); 
  }
	
	return true;	
}
Beispiel #2
0
bool Andigilog::start(IOService *provider)
{
    int i;
    bool res;
    UInt8 cmd, data, addrs[] = ASC7621_ADDRS;
    /* Mapping common for Intel boards */
    struct MList list[] = {
        { ASC7621_TEMP1H, ASC7621_TEMP1L, {"TC0D",TYPE_SP78,2,-1}, -1, 0, true },
        { ASC7621_TEMP2H, ASC7621_TEMP2L, {KEY_AMBIENT_TEMPERATURE,TYPE_SP78,2,-1}, -1, 0, true },
        { ASC7621_TEMP3H, ASC7621_TEMP3L, {KEY_DIMM_TEMPERATURE,TYPE_SP78,2,-1}, -1, 0, true },
        { ASC7621_TEMP4H, ASC7621_TEMP4L, {KEY_CPU_HEATSINK_TEMPERATURE,TYPE_SP78,2,-1}, -1, 0, true },
        
        { ASC7621_TACH1L, ASC7621_TACH1H, {"Fan 1",TYPE_FPE2,2,0}, true, 0, true },
        { ASC7621_TACH2L, ASC7621_TACH2H, {"Fan 2",TYPE_FPE2,2,1}, true, 0, true },
        { ASC7621_TACH3L, ASC7621_TACH3H, {"Fan 3",TYPE_FPE2,2,2}, true, 0, true },
        { ASC7621_TACH4L, ASC7621_TACH4H, {"Fan 4",TYPE_FPE2,2,2}, true, 0, true }
    };
    struct PList pwm[] = {
        { ASC7621_PWM1R, 0, -2 },
        { ASC7621_PWM2R, 0, -2 },
        { ASC7621_PWM3R, 0, -2 },
    };

    OSDictionary *conf = NULL, *sconf = OSDynamicCast(OSDictionary, getProperty("Sensors Configuration")), *dict;
    IOService *fRoot = getServiceRoot();
    OSString *str, *vendor = NULL;
    char *key;
    char tempkey[] = "_temp ", /* Ugly hack to keep keys in order for auto-generated plist */
    fankey[] = "tach ";

    
    res = super::start(provider);
    DbgPrint("start\n");
    
    if (!(i2cNub = OSDynamicCast(I2CDevice, provider))) {
        IOPrint("Failed to cast provider\n");
        return false;
    }
    
    i2cNub->retain();
    i2cNub->open(this);
    
    for (i = 0; i < sizeof(addrs) / sizeof(addrs[0]); i++)
        if (!i2cNub->ReadI2CBus(addrs[i], &(cmd = ASC7621_VID_REG), sizeof(cmd), &data,
                            sizeof(data)) && data == ASC7621_VID &&
            !i2cNub->ReadI2CBus(addrs[i], &(cmd = ASC7621_PID_REG), sizeof(cmd), &data,
                            sizeof(data)) && (data == ASC7621_PID || data == ASC7621A_PID)) {
                Asc7621_addr = addrs[i];
                IOPrint("aSC7621 attached at 0x%x.\n", Asc7621_addr);
                break;
            }
    if (!Asc7621_addr) {
        IOPrint("Device matching failed.\n");
        return false;
    }
    
    memcpy(&Measures, &list, sizeof(Measures));
    memcpy(&Pwm, &pwm, sizeof(Pwm));
    
    if (fRoot) {
        vendor = vendorID(OSDynamicCast(OSString, fRoot->getProperty("oem-mb-manufacturer") ?
                                        fRoot->getProperty("oem-mb-manufacturer") :
                                        (fRoot->getProperty("oem-manufacturer") ?
                                         fRoot->getProperty("oem-manufacturer") : NULL)));
        str = OSDynamicCast(OSString, fRoot->getProperty("oem-mb-product") ?
                            fRoot->getProperty("oem-mb-product") :
                            (fRoot->getProperty("oem-product-name") ?
                             fRoot->getProperty("oem-product-name") : NULL));
    }
    if (vendor)
        if (OSDictionary *link = OSDynamicCast(OSDictionary, sconf->getObject(vendor)))
            if(str)
                conf = OSDynamicCast(OSDictionary, link->getObject(str));
    if (sconf && !conf)
        conf = OSDynamicCast(OSDictionary, sconf->getObject("Active"));
    i = 0;
    for (int s = 0, j = 0, k = 0; i < NUM_SENSORS; i++) {
        if (conf) {
                if (Measures[i].fan < 0) {
                    snprintf(&tempkey[5], 2, "%d", j++);
                    key = tempkey;
                } else {
                    snprintf(&fankey[4], 2, "%d", k++);
                    key = fankey;
                }
                if ((dict = OSDynamicCast(OSDictionary, conf->getObject(key)))) {
                    str = OSDynamicCast(OSString, dict->getObject("id"));
                    memcpy(Measures[i].hwsensor.key, str->getCStringNoCopy(), str->getLength()+1);
                    if (Measures[i].fan > -1)
                        Measures[i].hwsensor.pwm = ((OSNumber *)OSDynamicCast(OSNumber, dict->getObject("pwm")))->
                        unsigned8BitValue();
                    Measures[i].hwsensor.size = ((OSNumber *)OSDynamicCast(OSNumber, dict->getObject("size")))->
                    unsigned8BitValue();
                    str = OSDynamicCast(OSString, dict->getObject("type"));
                    memcpy(Measures[i].hwsensor.type, str->getCStringNoCopy(), str->getLength()+1);
                }
        }
        if (Measures[i].hwsensor.key[0]) {
            if (Measures[i].fan < 0) {
                addSensor(Measures[i].hwsensor.key, Measures[i].hwsensor.type,
                          Measures[i].hwsensor.size, s);
                s++;
            } else {
                if (!config.start_fan)
                    config.start_fan = i;
                addTachometer(&Measures[i], Measures[i].fan = config.num_fan);
                config.num_fan++;
            }
        }
    }
    config.num_fan++;
    addKey(KEY_FAN_FORCE, TYPE_UI16, 2, 0);
  
    GetConf();
        
    return res;
}
Beispiel #3
0
QList<DMXInterface *> LibFTDIInterface::interfaces(QList<DMXInterface *> discoveredList)
{
    QList <DMXInterface*> interfacesList;
    int id = 0;

    struct ftdi_context ftdi;

    ftdi_init(&ftdi);

#ifdef LIBFTDI1
    libusb_device *dev;
    libusb_device **devs;
    struct libusb_device_descriptor dev_descriptor;
    int i = 0;

    if (libusb_get_device_list(ftdi.usb_ctx, &devs) < 0)
    {
        qDebug() << "usb_find_devices() failed";
        return interfacesList;
    }

    while ((dev = devs[i++]) != NULL)
    {
        libusb_get_device_descriptor(dev, &dev_descriptor);
#else
    struct usb_bus *bus;
    struct usb_device *dev;
    struct usb_device_descriptor dev_descriptor;

    usb_init();

    if (usb_find_busses() < 0)
    {
        qDebug() << "usb_find_busses() failed";
        return interfacesList;
    }
    if (usb_find_devices() < 0)
    {
        qDebug() << "usb_find_devices() failed";
        return interfacesList;
    }

    for (bus = usb_get_busses(); bus; bus = bus->next)
    {
      for (dev = bus->devices; dev; dev = dev->next)
      {
        dev_descriptor = dev->descriptor;
#endif
        Q_ASSERT(dev != NULL);

        // Skip non wanted devices
        if (validInterface(dev_descriptor.idVendor, dev_descriptor.idProduct) == false)
            continue;

        char ser[256];
        memset(ser, 0, 256);
        char nme[256];
        char vend[256];

        ftdi_usb_get_strings(&ftdi, dev, vend, 256, nme, 256, ser, 256);

        QString serial(ser);
        QString name(nme);
        QString vendor(vend);

        qDebug() << Q_FUNC_INFO << "DMX USB VID:" << QString::number(dev_descriptor.idVendor, 16) <<
                    "PID:" << QString::number(dev_descriptor.idProduct, 16);
        qDebug() << Q_FUNC_INFO << "DMX USB serial: " << serial << "name:" << name << "vendor:" << vendor;

        bool found = false;
        for (int c = 0; c < discoveredList.count(); c++)
        {
            if (discoveredList.at(c)->checkInfo(serial, name, vendor) == true)
            {
                found = true;
                break;
            }
        }
        if (found == false)
        {
            LibFTDIInterface *iface = new LibFTDIInterface(serial, name, vendor, dev_descriptor.idVendor,
                                                           dev_descriptor.idProduct, id++);
#ifdef LIBFTDI1
            iface->setBusLocation(libusb_get_port_number(dev));
#else
            iface->setBusLocation(dev->bus->location);
#endif
            interfacesList << iface;
        }

#ifndef LIBFTDI1
      }
#endif
    }

#ifdef LIBFTDI1
    libusb_free_device_list(devs, 1);
#endif

    ftdi_deinit(&ftdi);

    return interfacesList;
}

bool LibFTDIInterface::open()
{
    if (isOpen() == true)
        return true;

    QByteArray sba = serial().toLatin1();
    const char *ser = NULL;
    if (serial().isEmpty() == false)
        ser = (const char *)sba.data();

    if (ftdi_usb_open_desc(&m_handle, vendorID(), productID(),
                           name().toLatin1(), ser) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::openByPID(const int PID)
{
    if (isOpen() == true)
        return true;

    if (ftdi_usb_open(&m_handle, DMXInterface::FTDIVID, PID) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::close()
{
    if (ftdi_usb_close(&m_handle) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::isOpen() const
{
    return (m_handle.usb_dev != NULL) ? true : false;
}

bool LibFTDIInterface::reset()
{
    if (ftdi_usb_reset(&m_handle) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::setLineProperties()
{
    if (ftdi_set_line_property(&m_handle, BITS_8, STOP_BIT_2, NONE) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::setBaudRate()
{
    if (ftdi_set_baudrate(&m_handle, 250000) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::setFlowControl()
{
    if (ftdi_setflowctrl(&m_handle, SIO_DISABLE_FLOW_CTRL) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::clearRts()
{
    if (ftdi_setrts(&m_handle, 0) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::purgeBuffers()
{
    if (ftdi_usb_purge_buffers(&m_handle) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}

bool LibFTDIInterface::setBreak(bool on)
{
    ftdi_break_type type;
    if (on == true)
        type = BREAK_ON;
    else
        type = BREAK_OFF;

    if (ftdi_set_line_property2(&m_handle, BITS_8, STOP_BIT_2, NONE, type) < 0)
    {
        qWarning() << Q_FUNC_INFO << name() << ftdi_get_error_string(&m_handle);
        return false;
    }
    else
    {
        return true;
    }
}
Beispiel #4
0
void
OSGLContext_x11::getGPUInfos(std::list<OpenGLRendererInfo>& renderers)
{
    const OSGLContext_glx_data* glxInfo = appPTR->getGLXData();

    assert(glxInfo);
    if (!glxInfo->_imp->MESA_query_renderer) {
        boost::scoped_ptr<OSGLContext_x11> context;
        try {
            context.reset( new OSGLContext_x11(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, GLRendererID(), 0) );
        } catch (const std::exception& e) {
            std::cerr << e.what() << std::endl;

            return;
        }

        if ( !makeContextCurrent( context.get() ) ) {
            return;
        }

        try {
            OSGLContext::checkOpenGLVersion();
        } catch (const std::exception& e) {
            std::cerr << e.what() << std::endl;

            return;
        }

        OpenGLRendererInfo info;
        info.vendorName = std::string( (const char *) glGetString(GL_VENDOR) );
        info.rendererName = std::string( (const char *) glGetString(GL_RENDERER) );
        info.glVersionString = std::string( (const char *) glGetString(GL_VERSION) );
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);
        // We don't have any way to get memory size, set it to 0
        info.maxMemBytes = 0;
        info.rendererID.renderID = -1;
        renderers.push_back(info);
    } else {
        // Just use the first screen
        const int screen = 0;
        // The function QueryRendererIntegerMESA can return at most 3 values:  https://www.opengl.org/registry/specs/MESA/glx_query_renderer.txt
        unsigned int v[3];
        int renderer = 0;
        bool gotRenderer;
        do {
            gotRenderer = (bool)glxInfo->_imp->QueryRendererIntegerMESA(glxInfo->_imp->x11.display, screen, renderer, GLX_RENDERER_DEVICE_ID_MESA, v);
            if (gotRenderer) {
                int rendererID = v[0];
                if ( (unsigned int)rendererID == 0xFFFFFFFF ) {
                    gotRenderer = false;
                } else {
                    bool ok = glxInfo->_imp->QueryRendererIntegerMESA(glxInfo->_imp->x11.display, screen, renderer, GLX_RENDERER_ACCELERATED_MESA, v);
                    assert(ok);
                    if (!ok || !v[0]) {
                        ++renderer;
                        continue;
                    }


                    ok = glxInfo->_imp->QueryRendererIntegerMESA(glxInfo->_imp->x11.display, screen, renderer, GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA, v);
                    assert(ok);
                    if (!ok) {
                        ++renderer;
                        continue;
                    }

                    int maxCompatGLVersionMajor = (int)v[0];
                    int maxCompatGLVersionMinor = (int)v[1];

                    ok = glxInfo->_imp->QueryRendererIntegerMESA(glxInfo->_imp->x11.display, screen, renderer,  GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA, v);
                    assert(ok);
                    if (!ok) {
                        ++renderer;
                        continue;
                    }

                    int maxCoreGLVersionMajor = (int)v[0];
                    int maxCoreGLVersionMinor = (int)v[1];
                    const char* vendorIDStr = glxInfo->_imp->QueryRendererStringMesa(glxInfo->_imp->x11.display, screen, renderer, GLX_RENDERER_VENDOR_ID_MESA);
                    if (!vendorIDStr) {
                        ++renderer;
                        continue;
                    }
                    const char* deviceIDStr = glxInfo->_imp->QueryRendererStringMesa(glxInfo->_imp->x11.display, screen, renderer, GLX_RENDERER_DEVICE_ID_MESA);
                    if (!deviceIDStr) {
                        ++renderer;
                        continue;
                    }
                    std::string vendorID(vendorIDStr);
                    std::string deviceID(deviceIDStr);
                    std::stringstream ss;
                    ss << "Creating context for Device:" << deviceID << ", Vendor:" << vendorID << std::endl;
                    ss << "Max Compatibility OpenGL profile version: " << maxCompatGLVersionMajor << "." << maxCompatGLVersionMinor << std::endl;
                    ss << "Max Core OpenGL profile version: " << maxCoreGLVersionMajor << "." << maxCoreGLVersionMinor;
#ifdef DEBUG
                    std::cerr << ss.str() << std::endl;
#endif

                    OpenGLRendererInfo info;

                    ok = glxInfo->_imp->QueryRendererIntegerMESA(glxInfo->_imp->x11.display, screen, renderer, GLX_RENDERER_VIDEO_MEMORY_MESA, v);
                    assert(ok);
                    info.maxMemBytes = v[0] * 1e6;

                    // Now create a context with the renderer ID
                    boost::scoped_ptr<OSGLContext_x11> context;
                    try {
                        context.reset( new OSGLContext_x11(FramebufferConfig(), GLVersion.major, GLVersion.minor, false, GLRendererID( (int)renderer ), 0) );
                    } catch (const std::exception& e) {
#ifndef DEBUG
                        std::cerr << ss.str() << std::endl;
#endif
                        std::cerr << e.what() << std::endl;
                        ++renderer;
                        continue;
                    }

                    if ( !makeContextCurrent( context.get() ) ) {
                        ++renderer;
                        continue;
                    }

                    try {
                        OSGLContext::checkOpenGLVersion();
                    } catch (const std::exception& e) {
#ifndef DEBUG
                        std::cerr << ss.str() << std::endl;
#endif
                        std::cerr << e.what() << std::endl;
                        ++renderer;
                        continue;
                    }

                    info.rendererID.renderID = renderer;
                    info.vendorName = std::string( (const char *) glGetString(GL_VENDOR) );
                    info.rendererName = std::string( (const char *) glGetString(GL_RENDERER) );
                    info.glVersionString = std::string( (const char *) glGetString(GL_VERSION) );
                    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &info.maxTextureSize);

                    renderers.push_back(info);

                    makeContextCurrent(0);
                }
            }
            ++renderer;
        } while (gotRenderer);
    }
} // OSGLContext_x11::getGPUInfos