From b4d4fc8f79918bbd6dbf288fb43c4ce5ee22bdaf Mon Sep 17 00:00:00 2001 From: Arseny Kapoulkine Date: Thu, 1 May 2014 22:39:21 -0700 Subject: [PATCH] Optimize _glfwInitJoysticks on OS X. This function used to enumerate all devices and capture all properties of every device into a dictionary. This takes 180 ms on a MacBook Pro without external devices and 280 ms with an external keyboard/mouse attached. Since we're only interested in a few properties, we can just get them one by one - this reduces the time to <1 ms. Note that we still use the dictionary to get the joystick elements. For unknown reason this is required to get all axes/buttons - without doing this we don't get any joystick elements in addJoystickElement. Closes #332. --- README.md | 2 ++ src/iokit_joystick.m | 65 ++++++++++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index a0bbb73d..c9a8fa28 100644 --- a/README.md +++ b/README.md @@ -81,6 +81,7 @@ GLFW bundles a number of dependencies in the `deps/` directory. found for a given `CGDisplay` - [Cocoa] Bugfix: Modifier key events were lost if the corresponding modifier bit field was unchanged + - [Cocoa] Bugfix: Joystick enumeration took hundreds of ms on some systems - [Win32] Enabled generation of pkg-config file for MinGW - [Win32] Bugfix: Failure to load winmm or its functions was not reported to the error callback @@ -160,6 +161,7 @@ skills. - heromyth - Paul Holden - Toni Jovanoski + - Arseny Kapoulkine - Osman Keskin - Cameron King - Peter Knut diff --git a/src/iokit_joystick.m b/src/iokit_joystick.m index a09fbcf3..5ff67dd8 100644 --- a/src/iokit_joystick.m +++ b/src/iokit_joystick.m @@ -324,44 +324,49 @@ void _glfwInitJoysticks(void) HRESULT plugInResult = S_OK; SInt32 score = 0; - long usagePage, usage; + long usagePage = 0; + long usage = 0; - // Check device type + valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, + CFSTR(kIOHIDPrimaryUsagePageKey), + kCFAllocatorDefault, kNilOptions); + if (valueRef) + { + CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage); + CFRelease(valueRef); + } + + valueRef = IORegistryEntryCreateCFProperty(ioHIDDeviceObject, + CFSTR(kIOHIDPrimaryUsageKey), + kCFAllocatorDefault, kNilOptions); + if (valueRef) + { + CFNumberGetValue(valueRef, kCFNumberLongType, &usage); + CFRelease(valueRef); + } + + if (usagePage != kHIDPage_GenericDesktop) + { + // This device is not relevant to GLFW + continue; + } + + if ((usage != kHIDUsage_GD_Joystick && + usage != kHIDUsage_GD_GamePad && + usage != kHIDUsage_GD_MultiAxisController)) + { + // This device is not relevant to GLFW + continue; + } + result = IORegistryEntryCreateCFProperties(ioHIDDeviceObject, &propsRef, kCFAllocatorDefault, kNilOptions); - + if (result != kIOReturnSuccess) continue; - valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDPrimaryUsagePageKey)); - if (valueRef) - { - CFNumberGetValue(valueRef, kCFNumberLongType, &usagePage); - if (usagePage != kHIDPage_GenericDesktop) - { - // This device is not relevant to GLFW - CFRelease(propsRef); - continue; - } - } - - valueRef = CFDictionaryGetValue(propsRef, CFSTR(kIOHIDPrimaryUsageKey)); - if (valueRef) - { - CFNumberGetValue(valueRef, kCFNumberLongType, &usage); - - if ((usage != kHIDUsage_GD_Joystick && - usage != kHIDUsage_GD_GamePad && - usage != kHIDUsage_GD_MultiAxisController)) - { - // This device is not relevant to GLFW - CFRelease(propsRef); - continue; - } - } - _GLFWjoystickIOKit* joystick = _glfw.iokit_js + joy; joystick->present = GL_TRUE;