Initial commit
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Enable and disable system keys
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformEnableSystemKeys( void )
|
||||
{
|
||||
// This is checked in macosx_window.m; we take no action here
|
||||
}
|
||||
|
||||
void _glfwPlatformDisableSystemKeys( void )
|
||||
{
|
||||
// This is checked in macosx_window.m; we take no action here
|
||||
// I don't think it's really possible to disable stuff like Exposé
|
||||
// except in full-screen mode.
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
//========================================================================
|
||||
// Check whether the display mode should be included in enumeration
|
||||
//========================================================================
|
||||
|
||||
static BOOL modeIsGood( NSDictionary *mode )
|
||||
{
|
||||
// This is a bit controversial, if you've got something other than an
|
||||
// LCD computer monitor as an output device you might not want these
|
||||
// checks. You might also want to reject modes which are interlaced,
|
||||
// or TV out. There is no one-size-fits-all policy that can work here.
|
||||
// This seems like a decent compromise, but certain applications may
|
||||
// wish to patch this...
|
||||
return [[mode objectForKey:(id)kCGDisplayBitsPerPixel] intValue] >= 15 &&
|
||||
[mode objectForKey:(id)kCGDisplayModeIsSafeForHardware] != nil &&
|
||||
[mode objectForKey:(id)kCGDisplayModeIsStretched] == nil;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Convert Core Graphics display mode to GLFW video mode
|
||||
//========================================================================
|
||||
|
||||
static GLFWvidmode vidmodeFromCGDisplayMode( NSDictionary *mode )
|
||||
{
|
||||
unsigned int width = [[mode objectForKey:(id)kCGDisplayWidth] unsignedIntValue];
|
||||
unsigned int height = [[mode objectForKey:(id)kCGDisplayHeight] unsignedIntValue];
|
||||
unsigned int bps = [[mode objectForKey:(id)kCGDisplayBitsPerSample] unsignedIntValue];
|
||||
|
||||
GLFWvidmode result;
|
||||
result.Width = width;
|
||||
result.Height = height;
|
||||
result.RedBits = bps;
|
||||
result.GreenBits = bps;
|
||||
result.BlueBits = bps;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Get a list of available video modes
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformGetVideoModes( GLFWvidmode *list, int maxcount )
|
||||
{
|
||||
NSArray *modes = (NSArray *)CGDisplayAvailableModes( CGMainDisplayID() );
|
||||
|
||||
unsigned int i, j = 0, n = [modes count];
|
||||
for( i = 0; i < n && j < (unsigned)maxcount; i++ )
|
||||
{
|
||||
NSDictionary *mode = [modes objectAtIndex:i];
|
||||
if( modeIsGood( mode ) )
|
||||
{
|
||||
list[j++] = vidmodeFromCGDisplayMode( mode );
|
||||
}
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Get the desktop video mode
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformGetDesktopMode( GLFWvidmode *mode )
|
||||
{
|
||||
*mode = vidmodeFromCGDisplayMode( CGDisplayCurrentMode( CGMainDisplayID() ) );
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Check if an OpenGL extension is available at runtime
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformExtensionSupported( const char *extension )
|
||||
{
|
||||
// There are no AGL, CGL or NSGL extensions.
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Get the function pointer to an OpenGL function
|
||||
//========================================================================
|
||||
|
||||
void * _glfwPlatformGetProcAddress( const char *procname )
|
||||
{
|
||||
CFStringRef symbolName = CFStringCreateWithCString( kCFAllocatorDefault,
|
||||
procname,
|
||||
kCFStringEncodingASCII );
|
||||
|
||||
void *symbol = CFBundleGetFunctionPointerForName( _glfwLibrary.OpenGLFramework,
|
||||
symbolName );
|
||||
|
||||
CFRelease( symbolName );
|
||||
|
||||
return symbol;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,195 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@interface GLFWThread : NSThread
|
||||
@end
|
||||
|
||||
@implementation GLFWThread
|
||||
|
||||
- (void)main
|
||||
{
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
//========================================================================
|
||||
// Change to our application bundle's resources directory, if present
|
||||
//========================================================================
|
||||
|
||||
static void changeToResourcesDirectory( void )
|
||||
{
|
||||
char resourcesPath[MAXPATHLEN];
|
||||
|
||||
CFBundleRef bundle = CFBundleGetMainBundle();
|
||||
if( !bundle )
|
||||
return;
|
||||
|
||||
CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL( bundle );
|
||||
|
||||
CFStringRef last = CFURLCopyLastPathComponent( resourcesURL );
|
||||
if( CFStringCompare( CFSTR( "Resources" ), last, 0 ) != kCFCompareEqualTo )
|
||||
{
|
||||
CFRelease( last );
|
||||
CFRelease( resourcesURL );
|
||||
return;
|
||||
}
|
||||
|
||||
CFRelease( last );
|
||||
|
||||
if( !CFURLGetFileSystemRepresentation( resourcesURL,
|
||||
true,
|
||||
(UInt8*) resourcesPath,
|
||||
MAXPATHLEN) )
|
||||
{
|
||||
CFRelease( resourcesURL );
|
||||
return;
|
||||
}
|
||||
|
||||
CFRelease( resourcesURL );
|
||||
|
||||
chdir( resourcesPath );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Terminate GLFW when exiting application
|
||||
//========================================================================
|
||||
|
||||
static void glfw_atexit( void )
|
||||
{
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Initialize GLFW thread package
|
||||
//========================================================================
|
||||
|
||||
static void initThreads( void )
|
||||
{
|
||||
// Initialize critical section handle
|
||||
(void) pthread_mutex_init( &_glfwThrd.CriticalSection, NULL );
|
||||
|
||||
// The first thread (the main thread) has ID 0
|
||||
_glfwThrd.NextID = 0;
|
||||
|
||||
// Fill out information about the main thread (this thread)
|
||||
_glfwThrd.First.ID = _glfwThrd.NextID ++;
|
||||
_glfwThrd.First.Function = NULL;
|
||||
_glfwThrd.First.PosixID = pthread_self();
|
||||
_glfwThrd.First.Previous = NULL;
|
||||
_glfwThrd.First.Next = NULL;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Initialize the GLFW library
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformInit( void )
|
||||
{
|
||||
_glfwLibrary.autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||
|
||||
_glfwLibrary.OpenGLFramework =
|
||||
CFBundleGetBundleWithIdentifier( CFSTR( "com.apple.opengl" ) );
|
||||
if( _glfwLibrary.OpenGLFramework == NULL )
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
GLFWThread* thread = [[GLFWThread alloc] init];
|
||||
[thread start];
|
||||
[thread release];
|
||||
|
||||
changeToResourcesDirectory();
|
||||
|
||||
_glfwPlatformGetDesktopMode( &_glfwLibrary.desktopMode );
|
||||
|
||||
// Install atexit routine
|
||||
atexit( glfw_atexit );
|
||||
|
||||
initThreads();
|
||||
|
||||
_glfwInitTimer();
|
||||
|
||||
_glfwInitJoysticks();
|
||||
|
||||
_glfwLibrary.eventSource = CGEventSourceCreate( kCGEventSourceStateHIDSystemState );
|
||||
if( !_glfwLibrary.eventSource )
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
CGEventSourceSetLocalEventsSuppressionInterval( _glfwLibrary.eventSource,
|
||||
0.0 );
|
||||
|
||||
_glfwPlatformSetTime( 0.0 );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Close window, if open, and shut down GLFW
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformTerminate( void )
|
||||
{
|
||||
if( pthread_self() != _glfwThrd.First.PosixID )
|
||||
{
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
glfwCloseWindow();
|
||||
|
||||
// TODO: Kill all non-main threads?
|
||||
// TODO: Probably other cleanup
|
||||
|
||||
if( _glfwLibrary.eventSource )
|
||||
{
|
||||
CFRelease( _glfwLibrary.eventSource );
|
||||
_glfwLibrary.eventSource = NULL;
|
||||
}
|
||||
|
||||
_glfwTerminateJoysticks();
|
||||
|
||||
[_glfwLibrary.autoreleasePool release];
|
||||
_glfwLibrary.autoreleasePool = nil;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,648 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_error.h>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <IOKit/IOKitLib.h>
|
||||
#include <IOKit/IOCFPlugIn.h>
|
||||
#include <IOKit/hid/IOHIDLib.h>
|
||||
#include <IOKit/hid/IOHIDKeys.h>
|
||||
#include <Kernel/IOKit/hidsystem/IOHIDUsageTables.h>
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Joystick state
|
||||
//------------------------------------------------------------------------
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int present;
|
||||
char product[256];
|
||||
|
||||
IOHIDDeviceInterface** interface;
|
||||
|
||||
int numAxes;
|
||||
int numButtons;
|
||||
int numHats;
|
||||
|
||||
CFMutableArrayRef axes;
|
||||
CFMutableArrayRef buttons;
|
||||
CFMutableArrayRef hats;
|
||||
|
||||
} _glfwJoystick;
|
||||
|
||||
static _glfwJoystick _glfwJoysticks[GLFW_JOYSTICK_LAST + 1];
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IOHIDElementCookie cookie;
|
||||
|
||||
long value;
|
||||
|
||||
long min;
|
||||
long max;
|
||||
|
||||
long minReport;
|
||||
long maxReport;
|
||||
|
||||
} _glfwJoystickElement;
|
||||
|
||||
|
||||
void GetElementsCFArrayHandler( const void* value, void* parameter );
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Adds an element to the specified joystick
|
||||
//========================================================================
|
||||
|
||||
static void addJoystickElement( _glfwJoystick* joystick, CFTypeRef refElement )
|
||||
{
|
||||
long elementType, usagePage, usage;
|
||||
CFTypeRef refElementType, refUsagePage, refUsage;
|
||||
|
||||
refElementType = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementTypeKey ) );
|
||||
refUsagePage = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementUsagePageKey ) );
|
||||
refUsage = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementUsageKey ) );
|
||||
|
||||
CFMutableArrayRef elementsArray = NULL;
|
||||
|
||||
CFNumberGetValue( refElementType, kCFNumberLongType, &elementType );
|
||||
CFNumberGetValue( refUsagePage, kCFNumberLongType, &usagePage );
|
||||
CFNumberGetValue( refUsage, kCFNumberLongType, &usage );
|
||||
|
||||
if( elementType == kIOHIDElementTypeInput_Axis ||
|
||||
elementType == kIOHIDElementTypeInput_Button ||
|
||||
elementType == kIOHIDElementTypeInput_Misc )
|
||||
{
|
||||
switch( usagePage ) /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */
|
||||
{
|
||||
case kHIDPage_GenericDesktop:
|
||||
{
|
||||
switch( usage )
|
||||
{
|
||||
case kHIDUsage_GD_X:
|
||||
case kHIDUsage_GD_Y:
|
||||
case kHIDUsage_GD_Z:
|
||||
case kHIDUsage_GD_Rx:
|
||||
case kHIDUsage_GD_Ry:
|
||||
case kHIDUsage_GD_Rz:
|
||||
case kHIDUsage_GD_Slider:
|
||||
case kHIDUsage_GD_Dial:
|
||||
case kHIDUsage_GD_Wheel:
|
||||
joystick->numAxes++;
|
||||
elementsArray = joystick->axes;
|
||||
break;
|
||||
case kHIDUsage_GD_Hatswitch:
|
||||
joystick->numHats++;
|
||||
elementsArray = joystick->hats;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case kHIDPage_Button:
|
||||
joystick->numButtons++;
|
||||
elementsArray = joystick->buttons;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if( elementsArray )
|
||||
{
|
||||
long number;
|
||||
CFTypeRef refType;
|
||||
|
||||
_glfwJoystickElement* element = (_glfwJoystickElement*) malloc( sizeof( _glfwJoystickElement ) );
|
||||
|
||||
CFArrayAppendValue( elementsArray, element );
|
||||
|
||||
refType = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementCookieKey ) );
|
||||
if( refType && CFNumberGetValue( refType, kCFNumberLongType, &number ) )
|
||||
{
|
||||
element->cookie = (IOHIDElementCookie) number;
|
||||
}
|
||||
|
||||
refType = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementMinKey ) );
|
||||
if( refType && CFNumberGetValue( refType, kCFNumberLongType, &number ) )
|
||||
{
|
||||
element->minReport = element->min = number;
|
||||
}
|
||||
|
||||
refType = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementMaxKey ) );
|
||||
if( refType && CFNumberGetValue( refType, kCFNumberLongType, &number ) )
|
||||
{
|
||||
element->maxReport = element->max = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CFTypeRef refElementTop = CFDictionaryGetValue( refElement, CFSTR( kIOHIDElementKey ) );
|
||||
if( refElementTop )
|
||||
{
|
||||
CFTypeID type = CFGetTypeID( refElementTop );
|
||||
if( type == CFArrayGetTypeID() ) /* if element is an array */
|
||||
{
|
||||
CFRange range = { 0, CFArrayGetCount( refElementTop ) };
|
||||
CFArrayApplyFunction( refElementTop, range, GetElementsCFArrayHandler, joystick );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Adds an element to the specified joystick
|
||||
//========================================================================
|
||||
|
||||
void GetElementsCFArrayHandler( const void* value, void* parameter )
|
||||
{
|
||||
if( CFGetTypeID( value ) == CFDictionaryGetTypeID() )
|
||||
{
|
||||
addJoystickElement( (_glfwJoystick*) parameter, (CFTypeRef) value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Returns the value of the specified element of the specified joystick
|
||||
//========================================================================
|
||||
|
||||
static long getElementValue( _glfwJoystick* joystick, _glfwJoystickElement* element )
|
||||
{
|
||||
IOReturn result = kIOReturnSuccess;
|
||||
IOHIDEventStruct hidEvent;
|
||||
hidEvent.value = 0;
|
||||
|
||||
if( joystick && element && joystick->interface )
|
||||
{
|
||||
result = (*(joystick->interface))->getElementValue( joystick->interface,
|
||||
element->cookie,
|
||||
&hidEvent );
|
||||
if( kIOReturnSuccess == result )
|
||||
{
|
||||
/* record min and max for auto calibration */
|
||||
if( hidEvent.value < element->minReport )
|
||||
{
|
||||
element->minReport = hidEvent.value;
|
||||
}
|
||||
if( hidEvent.value > element->maxReport )
|
||||
{
|
||||
element->maxReport = hidEvent.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* auto user scale */
|
||||
return (long) hidEvent.value;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Removes the specified joystick
|
||||
//========================================================================
|
||||
|
||||
static void removeJoystick( _glfwJoystick* joystick )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( joystick->present )
|
||||
{
|
||||
joystick->present = GL_FALSE;
|
||||
|
||||
for( i = 0; i < joystick->numAxes; i++ )
|
||||
{
|
||||
_glfwJoystickElement* axes =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick->axes, i );
|
||||
free( axes );
|
||||
}
|
||||
CFArrayRemoveAllValues( joystick->axes );
|
||||
joystick->numAxes = 0;
|
||||
|
||||
for( i = 0; i < joystick->numButtons; i++ )
|
||||
{
|
||||
_glfwJoystickElement* button =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick->buttons, i );
|
||||
free( button );
|
||||
}
|
||||
CFArrayRemoveAllValues( joystick->buttons );
|
||||
joystick->numButtons = 0;
|
||||
|
||||
for( i = 0; i < joystick->numHats; i++ )
|
||||
{
|
||||
_glfwJoystickElement* hat =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick->hats, i );
|
||||
free( hat );
|
||||
}
|
||||
CFArrayRemoveAllValues( joystick->hats );
|
||||
joystick->hats = 0;
|
||||
|
||||
(*(joystick->interface))->close( joystick->interface );
|
||||
(*(joystick->interface))->Release( joystick->interface );
|
||||
|
||||
joystick->interface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Callback for user-initiated joystick removal
|
||||
//========================================================================
|
||||
|
||||
static void removalCallback( void* target, IOReturn result, void* refcon, void* sender )
|
||||
{
|
||||
removeJoystick( (_glfwJoystick*) refcon );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Polls for joystick events and updates GFLW state
|
||||
//========================================================================
|
||||
|
||||
static void pollJoystickEvents( void )
|
||||
{
|
||||
int i;
|
||||
CFIndex j;
|
||||
|
||||
for( i = 0; i < GLFW_JOYSTICK_LAST + 1; i++ )
|
||||
{
|
||||
_glfwJoystick* joystick = &_glfwJoysticks[i];
|
||||
|
||||
if( joystick->present )
|
||||
{
|
||||
for( j = 0; j < joystick->numButtons; j++ )
|
||||
{
|
||||
_glfwJoystickElement* button =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick->buttons, j );
|
||||
button->value = getElementValue( joystick, button );
|
||||
}
|
||||
|
||||
for( j = 0; j < joystick->numAxes; j++ )
|
||||
{
|
||||
_glfwJoystickElement* axes =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick->axes, j );
|
||||
axes->value = getElementValue( joystick, axes );
|
||||
}
|
||||
|
||||
for( j = 0; j < joystick->numHats; j++ )
|
||||
{
|
||||
_glfwJoystickElement* hat =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick->hats, j );
|
||||
hat->value = getElementValue( joystick, hat );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** GLFW internal functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Initialize joystick interface
|
||||
//========================================================================
|
||||
|
||||
void _glfwInitJoysticks( void )
|
||||
{
|
||||
int deviceCounter = 0;
|
||||
IOReturn result = kIOReturnSuccess;
|
||||
mach_port_t masterPort = 0;
|
||||
io_iterator_t objectIterator = 0;
|
||||
CFMutableDictionaryRef hidMatchDictionary = NULL;
|
||||
io_object_t ioHIDDeviceObject = 0;
|
||||
|
||||
result = IOMasterPort( bootstrap_port, &masterPort );
|
||||
hidMatchDictionary = IOServiceMatching( kIOHIDDeviceKey );
|
||||
if( kIOReturnSuccess != result || !hidMatchDictionary )
|
||||
{
|
||||
if( hidMatchDictionary )
|
||||
{
|
||||
CFRelease( hidMatchDictionary );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
result = IOServiceGetMatchingServices( masterPort,
|
||||
hidMatchDictionary,
|
||||
&objectIterator );
|
||||
if( result != kIOReturnSuccess )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( !objectIterator ) /* there are no joysticks */
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
while( ( ioHIDDeviceObject = IOIteratorNext( objectIterator ) ) )
|
||||
{
|
||||
CFMutableDictionaryRef hidProperties = 0;
|
||||
kern_return_t result;
|
||||
CFTypeRef refCF = 0;
|
||||
|
||||
IOCFPlugInInterface** ppPlugInInterface = NULL;
|
||||
HRESULT plugInResult = S_OK;
|
||||
SInt32 score = 0;
|
||||
|
||||
long usagePage, usage;
|
||||
|
||||
result = IORegistryEntryCreateCFProperties( ioHIDDeviceObject,
|
||||
&hidProperties,
|
||||
kCFAllocatorDefault,
|
||||
kNilOptions );
|
||||
|
||||
if( result != kIOReturnSuccess )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check device type */
|
||||
refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDPrimaryUsagePageKey ) );
|
||||
if( refCF )
|
||||
{
|
||||
CFNumberGetValue( refCF, kCFNumberLongType, &usagePage );
|
||||
if( usagePage != kHIDPage_GenericDesktop )
|
||||
{
|
||||
/* We are not interested in this device */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDPrimaryUsageKey ) );
|
||||
if( refCF )
|
||||
{
|
||||
CFNumberGetValue( refCF, kCFNumberLongType, &usage );
|
||||
|
||||
if( usage != kHIDUsage_GD_Joystick &&
|
||||
usage != kHIDUsage_GD_GamePad &&
|
||||
usage != kHIDUsage_GD_MultiAxisController )
|
||||
{
|
||||
/* We are not interested in this device */
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
_glfwJoystick* joystick = &_glfwJoysticks[deviceCounter];
|
||||
|
||||
joystick->present = GL_TRUE;
|
||||
|
||||
result = IOCreatePlugInInterfaceForService( ioHIDDeviceObject,
|
||||
kIOHIDDeviceUserClientTypeID,
|
||||
kIOCFPlugInInterfaceID,
|
||||
&ppPlugInInterface,
|
||||
&score );
|
||||
|
||||
if( kIOReturnSuccess != result )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
plugInResult = (*ppPlugInInterface)->QueryInterface( ppPlugInInterface,
|
||||
CFUUIDGetUUIDBytes( kIOHIDDeviceInterfaceID ),
|
||||
(void *) &(joystick->interface) );
|
||||
|
||||
if( plugInResult != S_OK )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
(*ppPlugInInterface)->Release( ppPlugInInterface );
|
||||
|
||||
(*(joystick->interface))->open( joystick->interface, 0 );
|
||||
(*(joystick->interface))->setRemovalCallback( joystick->interface,
|
||||
removalCallback,
|
||||
joystick,
|
||||
joystick );
|
||||
|
||||
/* Get product string */
|
||||
refCF = CFDictionaryGetValue( hidProperties, CFSTR( kIOHIDProductKey ) );
|
||||
if( refCF )
|
||||
{
|
||||
CFStringGetCString( refCF,
|
||||
(char*) &(joystick->product),
|
||||
256,
|
||||
CFStringGetSystemEncoding() );
|
||||
}
|
||||
|
||||
joystick->numAxes = 0;
|
||||
joystick->numButtons = 0;
|
||||
joystick->numHats = 0;
|
||||
joystick->axes = CFArrayCreateMutable( NULL, 0, NULL );
|
||||
joystick->buttons = CFArrayCreateMutable( NULL, 0, NULL );
|
||||
joystick->hats = CFArrayCreateMutable( NULL, 0, NULL );
|
||||
|
||||
CFTypeRef refTopElement = CFDictionaryGetValue( hidProperties,
|
||||
CFSTR( kIOHIDElementKey ) );
|
||||
CFTypeID type = CFGetTypeID( refTopElement );
|
||||
if( type == CFArrayGetTypeID() )
|
||||
{
|
||||
CFRange range = { 0, CFArrayGetCount( refTopElement ) };
|
||||
CFArrayApplyFunction( refTopElement,
|
||||
range,
|
||||
GetElementsCFArrayHandler,
|
||||
(void*) joystick);
|
||||
}
|
||||
|
||||
deviceCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Close all opened joystick handles
|
||||
//========================================================================
|
||||
|
||||
void _glfwTerminateJoysticks( void )
|
||||
{
|
||||
int i;
|
||||
|
||||
for( i = 0; i < GLFW_JOYSTICK_LAST + 1; i++ )
|
||||
{
|
||||
_glfwJoystick* joystick = &_glfwJoysticks[i];
|
||||
removeJoystick( joystick );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Determine joystick capabilities
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformGetJoystickParam( int joy, int param )
|
||||
{
|
||||
if( !_glfwJoysticks[joy].present )
|
||||
{
|
||||
// TODO: Figure out if this is an error
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
switch( param )
|
||||
{
|
||||
case GLFW_PRESENT:
|
||||
return GL_TRUE;
|
||||
|
||||
case GLFW_AXES:
|
||||
return (int) CFArrayGetCount( _glfwJoysticks[joy].axes );
|
||||
|
||||
case GLFW_BUTTONS:
|
||||
return (int) CFArrayGetCount( _glfwJoysticks[joy].buttons ) +
|
||||
((int) CFArrayGetCount( _glfwJoysticks[joy].hats )) * 4;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Get joystick axis positions
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformGetJoystickPos( int joy, float *pos, int numaxes )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
_glfwJoystick joystick = _glfwJoysticks[joy];
|
||||
|
||||
if( !joystick.present )
|
||||
{
|
||||
// TODO: Figure out if this is an error
|
||||
return 0;
|
||||
}
|
||||
|
||||
numaxes = numaxes < joystick.numAxes ? numaxes : joystick.numAxes;
|
||||
|
||||
// Update joystick state
|
||||
pollJoystickEvents();
|
||||
|
||||
for( i = 0; i < numaxes; i++ )
|
||||
{
|
||||
_glfwJoystickElement* axes =
|
||||
(_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick.axes, i );
|
||||
|
||||
long readScale = axes->maxReport - axes->minReport;
|
||||
|
||||
if( readScale == 0 )
|
||||
{
|
||||
pos[i] = axes->value;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos[i] = (2.0f * (axes->value - axes->minReport) / readScale) - 1.0f;
|
||||
}
|
||||
|
||||
//printf("%ld, %ld, %ld\n", axes->value, axes->minReport, axes->maxReport);
|
||||
|
||||
if( i & 1 )
|
||||
{
|
||||
pos[i] = -pos[i];
|
||||
}
|
||||
}
|
||||
|
||||
return numaxes;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Get joystick button states
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformGetJoystickButtons( int joy, unsigned char *buttons, int numbuttons )
|
||||
{
|
||||
int i, j, button;
|
||||
|
||||
if( joy < GLFW_JOYSTICK_1 || joy > GLFW_JOYSTICK_LAST )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
_glfwJoystick joystick = _glfwJoysticks[joy];
|
||||
|
||||
if( !joystick.present )
|
||||
{
|
||||
// TODO: Figure out if this is an error
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Update joystick state
|
||||
pollJoystickEvents();
|
||||
|
||||
for( button = 0; button < numbuttons && button < joystick.numButtons; button++ )
|
||||
{
|
||||
_glfwJoystickElement* element = (_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick.buttons, button );
|
||||
buttons[button] = element->value ? GLFW_PRESS : GLFW_RELEASE;
|
||||
}
|
||||
|
||||
// Virtual buttons - Inject data from hats
|
||||
// Each hat is exposed as 4 buttons which exposes 8 directions with concurrent button presses
|
||||
|
||||
const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; // Bit fields of button presses for each direction, including nil
|
||||
|
||||
for( i = 0; i < joystick.numHats; i++ )
|
||||
{
|
||||
_glfwJoystickElement* hat = (_glfwJoystickElement*) CFArrayGetValueAtIndex( joystick.hats, i );
|
||||
int value = hat->value;
|
||||
if( value < 0 || value > 8 )
|
||||
{
|
||||
value = 8;
|
||||
}
|
||||
|
||||
for( j = 0; j < 4 && button < numbuttons; j++ )
|
||||
{
|
||||
buttons[button++] = directions[value] & (1 << j) ? GLFW_PRESS : GLFW_RELEASE;
|
||||
}
|
||||
}
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,414 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** GLFW internal functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// _glfwNewThread() - This is simply a "wrapper" for calling the user
|
||||
// thread function.
|
||||
//========================================================================
|
||||
|
||||
void * _glfwNewThread( void * arg )
|
||||
{
|
||||
GLFWthreadfun threadfun;
|
||||
_GLFWthread *t;
|
||||
|
||||
// Get pointer to thread information for current thread
|
||||
t = _glfwGetThreadPointer( glfwGetThreadID() );
|
||||
if( t == NULL )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get user thread function pointer
|
||||
threadfun = t->Function;
|
||||
|
||||
// Call the user thread function
|
||||
threadfun( arg );
|
||||
|
||||
// Remove thread from thread list
|
||||
ENTER_THREAD_CRITICAL_SECTION
|
||||
_glfwRemoveThread( t );
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
|
||||
// When the thread function returns, the thread will die...
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformCreateThread() - Create a new thread
|
||||
//========================================================================
|
||||
|
||||
GLFWthread _glfwPlatformCreateThread( GLFWthreadfun fun, void *arg )
|
||||
{
|
||||
GLFWthread ID;
|
||||
_GLFWthread *t;
|
||||
int result;
|
||||
|
||||
// Enter critical section
|
||||
ENTER_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Create a new thread information memory area
|
||||
t = (_GLFWthread *) malloc( sizeof(_GLFWthread) );
|
||||
if( t == NULL )
|
||||
{
|
||||
// Leave critical section
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get a new unique thread id
|
||||
ID = _glfwThrd.NextID ++;
|
||||
|
||||
// Store thread information in the thread list
|
||||
t->Function = fun;
|
||||
t->ID = ID;
|
||||
|
||||
// Create thread
|
||||
result = pthread_create(
|
||||
&t->PosixID, // Thread handle
|
||||
NULL, // Default thread attributes
|
||||
_glfwNewThread, // Thread function (a wrapper function)
|
||||
(void *)arg // Argument to thread is user argument
|
||||
);
|
||||
|
||||
// Did the thread creation fail?
|
||||
if( result != 0 )
|
||||
{
|
||||
free( (void *) t );
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Append thread to thread list
|
||||
_glfwAppendThread( t );
|
||||
|
||||
// Leave critical section
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Return the GLFW thread ID
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformDestroyThread() - Kill a thread. NOTE: THIS IS A VERY
|
||||
// DANGEROUS OPERATION, AND SHOULD NOT BE USED EXCEPT IN EXTREME
|
||||
// SITUATIONS!
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformDestroyThread( GLFWthread ID )
|
||||
{
|
||||
_GLFWthread *t;
|
||||
|
||||
// Enter critical section
|
||||
ENTER_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Get thread information pointer
|
||||
t = _glfwGetThreadPointer( ID );
|
||||
if( t == NULL )
|
||||
{
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
return;
|
||||
}
|
||||
|
||||
// Simply murder the process, no mercy!
|
||||
pthread_kill( t->PosixID, SIGKILL );
|
||||
|
||||
// Remove thread from thread list
|
||||
_glfwRemoveThread( t );
|
||||
|
||||
// Leave critical section
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformWaitThread() - Wait for a thread to die
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformWaitThread( GLFWthread ID, int waitmode )
|
||||
{
|
||||
pthread_t thread;
|
||||
_GLFWthread *t;
|
||||
|
||||
// Enter critical section
|
||||
ENTER_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Get thread information pointer
|
||||
t = _glfwGetThreadPointer( ID );
|
||||
|
||||
// Is the thread already dead?
|
||||
if( t == NULL )
|
||||
{
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
// If got this far, the thread is alive => polling returns FALSE
|
||||
if( waitmode == GLFW_NOWAIT )
|
||||
{
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
// Get thread handle
|
||||
thread = t->PosixID;
|
||||
|
||||
// Leave critical section
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Wait for thread to die
|
||||
(void) pthread_join( thread, NULL );
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformGetThreadID() - Return the thread ID for the current
|
||||
// thread
|
||||
//========================================================================
|
||||
|
||||
GLFWthread _glfwPlatformGetThreadID( void )
|
||||
{
|
||||
_GLFWthread *t;
|
||||
GLFWthread ID = -1;
|
||||
pthread_t posixID;
|
||||
|
||||
// Get current thread ID
|
||||
posixID = pthread_self();
|
||||
|
||||
// Enter critical section
|
||||
ENTER_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Loop through entire list of threads to find the matching POSIX
|
||||
// thread ID
|
||||
for( t = &_glfwThrd.First; t != NULL; t = t->Next )
|
||||
{
|
||||
if( t->PosixID == posixID )
|
||||
{
|
||||
ID = t->ID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Leave critical section
|
||||
LEAVE_THREAD_CRITICAL_SECTION
|
||||
|
||||
// Return the found GLFW thread identifier
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformCreateMutex() - Create a mutual exclusion object
|
||||
//========================================================================
|
||||
|
||||
GLFWmutex _glfwPlatformCreateMutex( void )
|
||||
{
|
||||
pthread_mutex_t *mutex;
|
||||
|
||||
// Allocate memory for mutex
|
||||
mutex = (pthread_mutex_t *) malloc( sizeof( pthread_mutex_t ) );
|
||||
if( !mutex )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialise a mutex object
|
||||
(void) pthread_mutex_init( mutex, NULL );
|
||||
|
||||
// Cast to GLFWmutex and return
|
||||
return (GLFWmutex) mutex;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformDestroyMutex() - Destroy a mutual exclusion object
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformDestroyMutex( GLFWmutex mutex )
|
||||
{
|
||||
// Destroy the mutex object
|
||||
pthread_mutex_destroy( (pthread_mutex_t *) mutex );
|
||||
|
||||
// Free memory for mutex object
|
||||
free( (void *) mutex );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformLockMutex() - Request access to a mutex
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformLockMutex( GLFWmutex mutex )
|
||||
{
|
||||
// Wait for mutex to be released
|
||||
(void) pthread_mutex_lock( (pthread_mutex_t *) mutex );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformUnlockMutex() - Release a mutex
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformUnlockMutex( GLFWmutex mutex )
|
||||
{
|
||||
// Release mutex
|
||||
pthread_mutex_unlock( (pthread_mutex_t *) mutex );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformCreateCond() - Create a new condition variable object
|
||||
//========================================================================
|
||||
|
||||
GLFWcond _glfwPlatformCreateCond( void )
|
||||
{
|
||||
pthread_cond_t *cond;
|
||||
|
||||
// Allocate memory for condition variable
|
||||
cond = (pthread_cond_t *) malloc( sizeof(pthread_cond_t) );
|
||||
if( !cond )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Initialise condition variable
|
||||
(void) pthread_cond_init( cond, NULL );
|
||||
|
||||
// Cast to GLFWcond and return
|
||||
return (GLFWcond) cond;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformDestroyCond() - Destroy a condition variable object
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformDestroyCond( GLFWcond cond )
|
||||
{
|
||||
// Destroy the condition variable object
|
||||
(void) pthread_cond_destroy( (pthread_cond_t *) cond );
|
||||
|
||||
// Free memory for condition variable object
|
||||
free( (void *) cond );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformWaitCond() - Wait for a condition to be raised
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformWaitCond( GLFWcond cond, GLFWmutex mutex,
|
||||
double timeout )
|
||||
{
|
||||
struct timeval currenttime;
|
||||
struct timespec wait;
|
||||
long dt_sec, dt_usec;
|
||||
|
||||
// Select infinite or timed wait
|
||||
if( timeout >= GLFW_INFINITY )
|
||||
{
|
||||
// Wait for condition (infinite wait)
|
||||
(void) pthread_cond_wait( (pthread_cond_t *) cond,
|
||||
(pthread_mutex_t *) mutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set timeout time, relatvie to current time
|
||||
gettimeofday( ¤ttime, NULL );
|
||||
dt_sec = (long) timeout;
|
||||
dt_usec = (long) ((timeout - (double)dt_sec) * 1000000.0);
|
||||
wait.tv_nsec = (currenttime.tv_usec + dt_usec) * 1000L;
|
||||
if( wait.tv_nsec > 1000000000L )
|
||||
{
|
||||
wait.tv_nsec -= 1000000000L;
|
||||
dt_sec ++;
|
||||
}
|
||||
wait.tv_sec = currenttime.tv_sec + dt_sec;
|
||||
|
||||
// Wait for condition (timed wait)
|
||||
(void) pthread_cond_timedwait( (pthread_cond_t *) cond,
|
||||
(pthread_mutex_t *) mutex, &wait );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformSignalCond() - Signal a condition to one waiting thread
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformSignalCond( GLFWcond cond )
|
||||
{
|
||||
// Signal condition
|
||||
(void) pthread_cond_signal( (pthread_cond_t *) cond );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformBroadcastCond() - Broadcast a condition to all waiting
|
||||
// threads
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformBroadcastCond( GLFWcond cond )
|
||||
{
|
||||
// Broadcast condition
|
||||
(void) pthread_cond_broadcast( (pthread_cond_t *) cond );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// _glfwPlatformGetNumberOfProcessors() - Return the number of processors
|
||||
// in the system.
|
||||
//========================================================================
|
||||
|
||||
int _glfwPlatformGetNumberOfProcessors( void )
|
||||
{
|
||||
int n;
|
||||
|
||||
// Get number of processors online
|
||||
_glfw_numprocessors( n );
|
||||
return n;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include <mach/mach_time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Return raw time
|
||||
//========================================================================
|
||||
|
||||
static uint64_t getRawTime( void )
|
||||
{
|
||||
return mach_absolute_time();
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Initialise timer
|
||||
//========================================================================
|
||||
|
||||
void _glfwInitTimer( void )
|
||||
{
|
||||
mach_timebase_info_data_t info;
|
||||
mach_timebase_info( &info );
|
||||
|
||||
_glfwLibrary.timer.resolution = (double) info.numer / ( info.denom * 1.0e9 );
|
||||
_glfwLibrary.timer.base = getRawTime();
|
||||
}
|
||||
|
||||
|
||||
//************************************************************************
|
||||
//**** Platform implementation functions ****
|
||||
//************************************************************************
|
||||
|
||||
//========================================================================
|
||||
// Return timer value in seconds
|
||||
//========================================================================
|
||||
|
||||
double _glfwPlatformGetTime( void )
|
||||
{
|
||||
return (double) ( getRawTime() - _glfwLibrary.timer.base ) *
|
||||
_glfwLibrary.timer.resolution;
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Set timer value in seconds
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformSetTime( double time )
|
||||
{
|
||||
_glfwLibrary.timer.base = getRawTime() -
|
||||
(uint64_t) ( time / _glfwLibrary.timer.resolution );
|
||||
}
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Put a thread to sleep for a specified amount of time
|
||||
//========================================================================
|
||||
|
||||
void _glfwPlatformSleep( double time )
|
||||
{
|
||||
if( time == 0.0 )
|
||||
{
|
||||
sched_yield();
|
||||
return;
|
||||
}
|
||||
|
||||
struct timeval currenttime;
|
||||
struct timespec wait;
|
||||
pthread_mutex_t mutex;
|
||||
pthread_cond_t cond;
|
||||
long dt_sec, dt_usec;
|
||||
|
||||
// Not all pthread implementations have a pthread_sleep() function. We
|
||||
// do it the portable way, using a timed wait for a condition that we
|
||||
// will never signal. NOTE: The unistd functions sleep/usleep suspends
|
||||
// the entire PROCESS, not a signle thread, which is why we can not
|
||||
// use them to implement glfwSleep.
|
||||
|
||||
// Set timeout time, relatvie to current time
|
||||
gettimeofday( ¤ttime, NULL );
|
||||
dt_sec = (long) time;
|
||||
dt_usec = (long) ((time - (double)dt_sec) * 1000000.0);
|
||||
wait.tv_nsec = (currenttime.tv_usec + dt_usec) * 1000L;
|
||||
if( wait.tv_nsec > 1000000000L )
|
||||
{
|
||||
wait.tv_nsec -= 1000000000L;
|
||||
dt_sec ++;
|
||||
}
|
||||
wait.tv_sec = currenttime.tv_sec + dt_sec;
|
||||
|
||||
// Initialize condition and mutex objects
|
||||
pthread_mutex_init( &mutex, NULL );
|
||||
pthread_cond_init( &cond, NULL );
|
||||
|
||||
// Do a timed wait
|
||||
pthread_mutex_lock( &mutex );
|
||||
pthread_cond_timedwait( &cond, &mutex, &wait );
|
||||
pthread_mutex_unlock( &mutex );
|
||||
|
||||
// Destroy condition and mutex objects
|
||||
pthread_mutex_destroy( &mutex );
|
||||
pthread_cond_destroy( &cond );
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,268 @@
|
||||
//========================================================================
|
||||
// GLFW - An OpenGL framework
|
||||
// Platform: Cocoa/NSOpenGL
|
||||
// API Version: 2.7
|
||||
// WWW: http://www.glfw.org/
|
||||
//------------------------------------------------------------------------
|
||||
// Copyright (c) 2009-2010 Camilla Berglund <elmindreda@elmindreda.org>
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would
|
||||
// be appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not
|
||||
// be misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
//========================================================================
|
||||
|
||||
#ifndef _platform_h_
|
||||
#define _platform_h_
|
||||
|
||||
|
||||
// This is the Mac OS X version of GLFW
|
||||
#define _GLFW_MAC_OS_X
|
||||
|
||||
#if defined(__OBJC__)
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#else
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
typedef void *id;
|
||||
#endif
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "../../include/GL/glfw.h"
|
||||
|
||||
|
||||
#ifndef GL_VERSION_3_0
|
||||
|
||||
typedef const GLubyte * (APIENTRY *PFNGLGETSTRINGIPROC) (GLenum, GLuint);
|
||||
|
||||
#endif /*GL_VERSION_3_0*/
|
||||
|
||||
|
||||
//========================================================================
|
||||
// GLFW platform specific types
|
||||
//========================================================================
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Pointer length integer
|
||||
//------------------------------------------------------------------------
|
||||
typedef intptr_t GLFWintptr;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Window structure
|
||||
//------------------------------------------------------------------------
|
||||
typedef struct _GLFWwin_struct _GLFWwin;
|
||||
|
||||
struct _GLFWwin_struct {
|
||||
|
||||
// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
|
||||
|
||||
// User callback functions
|
||||
GLFWwindowsizefun windowSizeCallback;
|
||||
GLFWwindowclosefun windowCloseCallback;
|
||||
GLFWwindowrefreshfun windowRefreshCallback;
|
||||
GLFWmousebuttonfun mouseButtonCallback;
|
||||
GLFWmouseposfun mousePosCallback;
|
||||
GLFWmousewheelfun mouseWheelCallback;
|
||||
GLFWkeyfun keyCallback;
|
||||
GLFWcharfun charCallback;
|
||||
|
||||
// User selected window settings
|
||||
int fullscreen; // Fullscreen flag
|
||||
int mouseLock; // Mouse-lock flag
|
||||
int autoPollEvents; // Auto polling flag
|
||||
int sysKeysDisabled; // System keys disabled flag
|
||||
int windowNoResize; // Resize- and maximize gadgets disabled flag
|
||||
int refreshRate; // Vertical monitor refresh rate
|
||||
|
||||
// Window status & parameters
|
||||
int opened; // Flag telling if window is opened or not
|
||||
int active; // Application active flag
|
||||
int iconified; // Window iconified flag
|
||||
int width, height; // Window width and heigth
|
||||
int accelerated; // GL_TRUE if window is HW accelerated
|
||||
|
||||
// Framebuffer attributes
|
||||
int redBits;
|
||||
int greenBits;
|
||||
int blueBits;
|
||||
int alphaBits;
|
||||
int depthBits;
|
||||
int stencilBits;
|
||||
int accumRedBits;
|
||||
int accumGreenBits;
|
||||
int accumBlueBits;
|
||||
int accumAlphaBits;
|
||||
int auxBuffers;
|
||||
int stereo;
|
||||
int samples;
|
||||
|
||||
// OpenGL extensions and context attributes
|
||||
int has_GL_SGIS_generate_mipmap;
|
||||
int has_GL_ARB_texture_non_power_of_two;
|
||||
int glMajor, glMinor, glRevision;
|
||||
int glForward, glDebug, glProfile;
|
||||
|
||||
PFNGLGETSTRINGIPROC GetStringi;
|
||||
|
||||
// ========= PLATFORM SPECIFIC PART ======================================
|
||||
|
||||
id window;
|
||||
id pixelFormat;
|
||||
id context;
|
||||
id delegate;
|
||||
unsigned int modifierFlags;
|
||||
};
|
||||
|
||||
GLFWGLOBAL _GLFWwin _glfwWin;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Library global data
|
||||
//------------------------------------------------------------------------
|
||||
GLFWGLOBAL struct {
|
||||
|
||||
// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
|
||||
|
||||
// Window opening hints
|
||||
_GLFWhints hints;
|
||||
|
||||
// Initial desktop mode
|
||||
GLFWvidmode desktopMode;
|
||||
|
||||
// ========= PLATFORM SPECIFIC PART ======================================
|
||||
|
||||
// Timer data
|
||||
struct {
|
||||
double base;
|
||||
double resolution;
|
||||
} timer;
|
||||
|
||||
// dlopen handle for dynamically-loading extension function pointers
|
||||
void *OpenGLFramework;
|
||||
|
||||
id originalMode;
|
||||
|
||||
id autoreleasePool;
|
||||
|
||||
CGEventSourceRef eventSource;
|
||||
|
||||
} _glfwLibrary;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// User input status (some of this should go in _GLFWwin)
|
||||
//------------------------------------------------------------------------
|
||||
GLFWGLOBAL struct {
|
||||
|
||||
// ========= PLATFORM INDEPENDENT MANDATORY PART =========================
|
||||
|
||||
// Mouse status
|
||||
int MousePosX, MousePosY;
|
||||
int WheelPos;
|
||||
char MouseButton[ GLFW_MOUSE_BUTTON_LAST+1 ];
|
||||
|
||||
// Keyboard status
|
||||
char Key[ GLFW_KEY_LAST+1 ];
|
||||
int LastChar;
|
||||
|
||||
// User selected settings
|
||||
int StickyKeys;
|
||||
int StickyMouseButtons;
|
||||
int KeyRepeat;
|
||||
|
||||
|
||||
// ========= PLATFORM SPECIFIC PART ======================================
|
||||
|
||||
double WheelPosFloating;
|
||||
|
||||
} _glfwInput;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Thread information
|
||||
//------------------------------------------------------------------------
|
||||
typedef struct _GLFWthread_struct _GLFWthread;
|
||||
|
||||
// Thread record (one for each thread)
|
||||
struct _GLFWthread_struct {
|
||||
|
||||
// Pointer to previous and next threads in linked list
|
||||
_GLFWthread *Previous, *Next;
|
||||
|
||||
// GLFW user side thread information
|
||||
GLFWthread ID;
|
||||
GLFWthreadfun Function;
|
||||
|
||||
// System side thread information
|
||||
pthread_t PosixID;
|
||||
};
|
||||
|
||||
// General thread information
|
||||
GLFWGLOBAL struct {
|
||||
|
||||
// Critical section lock
|
||||
pthread_mutex_t CriticalSection;
|
||||
|
||||
// Next thread ID to use (increments for every created thread)
|
||||
GLFWthread NextID;
|
||||
|
||||
// First thread in linked list (always the main thread)
|
||||
_GLFWthread First;
|
||||
|
||||
} _glfwThrd;
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Macros for encapsulating critical code sections (i.e. making parts
|
||||
// of GLFW thread safe)
|
||||
//========================================================================
|
||||
|
||||
// Define so we can use the same thread code as X11
|
||||
#define _glfw_numprocessors(n) { \
|
||||
int mib[2], ncpu; \
|
||||
size_t len = 1; \
|
||||
mib[0] = CTL_HW; \
|
||||
mib[1] = HW_NCPU; \
|
||||
n = 1; \
|
||||
if( sysctl( mib, 2, &ncpu, &len, NULL, 0 ) != -1 ) \
|
||||
{ \
|
||||
if( len > 0 ) \
|
||||
{ \
|
||||
n = ncpu; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
// Thread list management
|
||||
#define ENTER_THREAD_CRITICAL_SECTION \
|
||||
pthread_mutex_lock( &_glfwThrd.CriticalSection );
|
||||
#define LEAVE_THREAD_CRITICAL_SECTION \
|
||||
pthread_mutex_unlock( &_glfwThrd.CriticalSection );
|
||||
|
||||
|
||||
//========================================================================
|
||||
// Prototypes for platform specific internal functions
|
||||
//========================================================================
|
||||
|
||||
// Time
|
||||
void _glfwInitTimer( void );
|
||||
|
||||
// Joystick
|
||||
void _glfwInitJoysticks( void );
|
||||
void _glfwTerminateJoysticks( void );
|
||||
|
||||
#endif // _platform_h_
|
||||
Reference in New Issue
Block a user