Wednesday, August 7, 2013

Detecting Graphics Hardware using Objective-C

Recently, I encountered an issue with a specific graphics card and as a fix, I wanted my application to detect the Graphics Hardware and proceed accordingly. While I was searching on the web, I couldn't find much about solving the problem but I somehow managed to a collect bits and pieces and come up with the solution. So, in this post I am going to discuss the approaches which came to my mind to solve the problem, and the approach used by me.

Approaches:

1. Forking a new process and using exec() family of methods to execute the system command system_profiler SPDisplays and fetching the graphics information.

2. Second approach is almost similar to the first one, the only difference is that instead of using fork to
create a new process, we use NSTask to execute system_profiler .

3. The third approach is to use IOKit. Below is the code which can be used to get the model of the graphics card:

- (void)displayGraphicsInfo
{
    // Get dictionary of all the PCI Devicces
    CFMutableDictionaryRef matchDict = IOServiceMatching("IOPCIDevice");
    
    // Create an iterator
    io_iterator_t iterator;
    
    if (IOServiceGetMatchingServices(kIOMasterPortDefault,matchDict,
                                     &iterator) == kIOReturnSuccess)
    {
        // Iterator for devices found
        io_registry_entry_t regEntry;
        
        while ((regEntry = IOIteratorNext(iterator))) {
            // Put this services object into a dictionary object.
            CFMutableDictionaryRef serviceDictionary;
            if (IORegistryEntryCreateCFProperties(regEntry,
                                                  &serviceDictionary,
                                                  kCFAllocatorDefault,
                                                  kNilOptions) != kIOReturnSuccess)
            {
                // Service dictionary creation failed.
                IOObjectRelease(regEntry);
                continue;
            }
            const void *GPUModel = CFDictionaryGetValue(serviceDictionary, @"model");
            
            if (GPUModel != nil) {
                if (CFGetTypeID(GPUModel) == CFDataGetTypeID()) {
                    // Create a string from the CFDataRef.
                    NSString *modelName = [[NSString alloc] initWithData:
                                           (NSData *)GPUModel encoding:NSASCIIStringEncoding];
                    
                    NSLog(@"GPU Model: %@", modelName);
                    [modelName release];
                }
            }
            // Release the dictionary
            CFRelease(serviceDictionary);
            // Release the serviceObject
            IOObjectRelease(regEntry);
        }
        // Release the iterator
        IOObjectRelease(iterator);
    }
}

The approach which I have used is the 3rd approach. The drawbacks of 1st and 2nd approaches are that they are considerably slow as compared to the 3rd approach.

Source: The credit of the above solution goes to the author of *Coder Blog, Mike Piatek-Jimenez and the original post can be found here.

    No comments:

    Post a Comment