From d0c7a7a2c497ef273045eab38cd3065ca5a3694a Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 13:49:12 +0200
Subject: [PATCH 01/50] Added TinyCThread to support directory.
---
support/tinycthread.c | 588 ++++++++++++++++++++++++++++++++++++++++++
support/tinycthread.h | 404 +++++++++++++++++++++++++++++
2 files changed, 992 insertions(+)
create mode 100644 support/tinycthread.c
create mode 100644 support/tinycthread.h
diff --git a/support/tinycthread.c b/support/tinycthread.c
new file mode 100644
index 000000000..f97d07cc0
--- /dev/null
+++ b/support/tinycthread.c
@@ -0,0 +1,588 @@
+/*
+Copyright (c) 2011 Marcus Geelnard
+
+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.
+*/
+
+/* Activate some POSIX functionality (e.g. recursive mutexes) */
+#define _GNU_SOURCE
+#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 500)
+ #undef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 500
+#endif
+
+#include "tinycthread.h"
+#include
+
+/* Platform specific includes */
+#if defined(_TTHREAD_POSIX_)
+ #include
+ #include
+ #include
+ #include
+ #include
+#elif defined(_TTHREAD_WIN32_)
+ #include
+ #include
+#endif
+
+/* Standard, good-to-have defines */
+#ifndef NULL
+ #define NULL (void*)0
+#endif
+#ifndef TRUE
+ #define TRUE 1
+#endif
+#ifndef FALSE
+ #define FALSE 0
+#endif
+
+int mtx_init(mtx_t *mtx, int type)
+{
+#if defined(_TTHREAD_WIN32_)
+ mtx->mAlreadyLocked = FALSE;
+ mtx->mRecursive = type & mtx_recursive;
+ InitializeCriticalSection(&mtx->mHandle);
+ return thrd_success;
+#else
+ int ret;
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init(&attr);
+ if (type & mtx_recursive)
+ {
+ pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ }
+ ret = pthread_mutex_init(mtx, &attr);
+ pthread_mutexattr_destroy(&attr);
+ return ret == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+void mtx_destroy(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+ DeleteCriticalSection(&mtx->mHandle);
+#else
+ pthread_mutex_destroy(mtx);
+#endif
+}
+
+int mtx_lock(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+ EnterCriticalSection(&mtx->mHandle);
+ if (!mtx->mRecursive)
+ {
+ while(mtx->mAlreadyLocked) Sleep(1000); /* Simulate deadlock... */
+ mtx->mAlreadyLocked = TRUE;
+ }
+ return thrd_success;
+#else
+ return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+int mtx_timedlock(mtx_t *mtx, const xtime *xt)
+{
+ /* FIXME! */
+ return thrd_error;
+}
+
+int mtx_trylock(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+ int ret = TryEnterCriticalSection(&mtx->mHandle) ? thrd_success : thrd_busy;
+ if ((!mtx->mRecursive) && (ret == thrd_success) && mtx->mAlreadyLocked)
+ {
+ LeaveCriticalSection(&mtx->mHandle);
+ ret = thrd_busy;
+ }
+ return ret;
+#else
+ return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
+#endif
+}
+
+int mtx_unlock(mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+ mtx->mAlreadyLocked = FALSE;
+ LeaveCriticalSection(&mtx->mHandle);
+ return thrd_success;
+#else
+ return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
+#endif
+}
+
+#if defined(_TTHREAD_WIN32_)
+#define _CONDITION_EVENT_ONE 0
+#define _CONDITION_EVENT_ALL 1
+#endif
+
+int cnd_init(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+ cond->mWaitersCount = 0;
+
+ /* Init critical section */
+ InitializeCriticalSection(&cond->mWaitersCountLock);
+
+ /* Init events */
+ cond->mEvents[_CONDITION_EVENT_ONE] = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (cond->mEvents[_CONDITION_EVENT_ONE] == NULL)
+ {
+ cond->mEvents[_CONDITION_EVENT_ALL] = NULL;
+ return thrd_error;
+ }
+ cond->mEvents[_CONDITION_EVENT_ALL] = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (cond->mEvents[_CONDITION_EVENT_ALL] == NULL)
+ {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+ cond->mEvents[_CONDITION_EVENT_ONE] = NULL;
+ return thrd_error;
+ }
+
+ return thrd_success;
+#else
+ return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+void cnd_destroy(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+ if (cond->mEvents[_CONDITION_EVENT_ONE] != NULL)
+ {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ONE]);
+ }
+ if (cond->mEvents[_CONDITION_EVENT_ALL] != NULL)
+ {
+ CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
+ }
+ DeleteCriticalSection(&cond->mWaitersCountLock);
+#else
+ pthread_cond_destroy(cond);
+#endif
+}
+
+int cnd_signal(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+ int haveWaiters;
+
+ /* Are there any waiters? */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ haveWaiters = (cond->mWaitersCount > 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we have any waiting threads, send them a signal */
+ if(haveWaiters)
+ {
+ if (SetEvent(cond->mEvents[_CONDITION_EVENT_ONE]) == 0)
+ {
+ return thrd_error;
+ }
+ }
+
+ return thrd_success;
+#else
+ return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+int cnd_broadcast(cnd_t *cond)
+{
+#if defined(_TTHREAD_WIN32_)
+ int haveWaiters;
+
+ /* Are there any waiters? */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ haveWaiters = (cond->mWaitersCount > 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we have any waiting threads, send them a signal */
+ if(haveWaiters)
+ {
+ if (SetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
+ {
+ return thrd_error;
+ }
+ }
+
+ return thrd_success;
+#else
+ return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+#if defined(_TTHREAD_WIN32_)
+static int _cnd_timedwait_win32(cnd_t *cond, mtx_t *mtx, DWORD timeout)
+{
+ int result, lastWaiter;
+
+ /* Increment number of waiters */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ ++ cond->mWaitersCount;
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* Release the mutex while waiting for the condition (will decrease
+ the number of waiters when done)... */
+ mtx_unlock(mtx);
+
+ /* Wait for either event to become signaled due to cnd_signal() or
+ cnd_broadcast() being called */
+ result = WaitForMultipleObjects(2, cond->mEvents, FALSE, timeout);
+ if (result == WAIT_TIMEOUT)
+ {
+ return thrd_timeout;
+ }
+ else if (result == (int)WAIT_FAILED)
+ {
+ return thrd_error;
+ }
+
+ /* Check if we are the last waiter */
+ EnterCriticalSection(&cond->mWaitersCountLock);
+ -- cond->mWaitersCount;
+ lastWaiter = (result == (WAIT_OBJECT_0 + _CONDITION_EVENT_ALL)) &&
+ (cond->mWaitersCount == 0);
+ LeaveCriticalSection(&cond->mWaitersCountLock);
+
+ /* If we are the last waiter to be notified to stop waiting, reset the event */
+ if (lastWaiter)
+ {
+ if (ResetEvent(cond->mEvents[_CONDITION_EVENT_ALL]) == 0)
+ {
+ return thrd_error;
+ }
+ }
+
+ /* Re-acquire the mutex */
+ mtx_lock(mtx);
+
+ return thrd_success;
+}
+#endif
+
+int cnd_wait(cnd_t *cond, mtx_t *mtx)
+{
+#if defined(_TTHREAD_WIN32_)
+ return _cnd_timedwait_win32(cond, mtx, INFINITE);
+#else
+ return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
+{
+#if defined(_TTHREAD_WIN32_)
+ xtime now;
+ DWORD delta;
+ xtime_get(&now, TIME_UTC);
+ delta = (xt->sec - now.sec) * 1000 +
+ (xt->nsec - now.nsec + 500000) / 1000000;
+ return _cnd_timedwait_win32(cond, mtx, delta);
+#else
+ struct timespec ts;
+ int ret;
+ ts.tv_sec = xt->sec;
+ ts.tv_nsec = xt->nsec;
+ ret = pthread_cond_timedwait(cond, mtx, &ts);
+ if (ret == ETIMEDOUT)
+ {
+ return thrd_timeout;
+ }
+ return ret == 0 ? thrd_success : thrd_error;
+#endif
+}
+
+
+/** Information to pass to the new thread (what to run). */
+typedef struct {
+ thrd_start_t mFunction; /**< Pointer to the function to be executed. */
+ void * mArg; /**< Function argument for the thread function. */
+} _thread_start_info;
+
+/* Thread wrapper function. */
+#if defined(_TTHREAD_WIN32_)
+unsigned WINAPI _thrd_wrapper_function(void * aArg)
+#elif defined(_TTHREAD_POSIX_)
+void * _thrd_wrapper_function(void * aArg)
+#endif
+{
+ thrd_start_t fun;
+ void *arg;
+ int res;
+#if defined(_TTHREAD_POSIX_)
+ void *pres;
+#endif
+
+ /* Get thread startup information */
+ _thread_start_info *ti = (_thread_start_info *) aArg;
+ fun = ti->mFunction;
+ arg = ti->mArg;
+
+ /* The thread is responsible for freeing the startup information */
+ free((void *)ti);
+
+ /* Call the actual client thread function */
+ res = fun(arg);
+
+#if defined(_TTHREAD_WIN32_)
+ return res;
+#else
+ pres = malloc(sizeof(int));
+ if (pres != NULL)
+ {
+ *(int*)pres = res;
+ }
+ return pres;
+#endif
+}
+
+int thrd_create(thrd_t *thr, thrd_start_t func, void *arg)
+{
+ /* Fill out the thread startup information (passed to the thread wrapper,
+ which will eventually free it) */
+ _thread_start_info* ti = (_thread_start_info*)malloc(sizeof(_thread_start_info));
+ if (ti == NULL)
+ {
+ return thrd_nomem;
+ }
+ ti->mFunction = func;
+ ti->mArg = arg;
+
+ /* Create the thread */
+#if defined(_TTHREAD_WIN32_)
+ *thr = (HANDLE)_beginthreadex(NULL, 0, _thrd_wrapper_function, (void *)ti, 0, NULL);
+#elif defined(_TTHREAD_POSIX_)
+ if(pthread_create(thr, NULL, _thrd_wrapper_function, (void *)ti) != 0)
+ {
+ *thr = 0;
+ }
+#endif
+
+ /* Did we fail to create the thread? */
+ if(!*thr)
+ {
+ free(ti);
+ return thrd_error;
+ }
+
+ return thrd_success;
+}
+
+thrd_t thrd_current(void)
+{
+#if defined(_TTHREAD_WIN32_)
+ return GetCurrentThread();
+#else
+ return pthread_self();
+#endif
+}
+
+int thrd_detach(thrd_t thr)
+{
+ /* FIXME! */
+ return thrd_error;
+}
+
+int thrd_equal(thrd_t thr0, thrd_t thr1)
+{
+#if defined(_TTHREAD_WIN32_)
+ return thr0 == thr1;
+#else
+ return pthread_equal(thr0, thr1);
+#endif
+}
+
+void thrd_exit(int res)
+{
+#if defined(_TTHREAD_WIN32_)
+ ExitThread(res);
+#else
+ void *pres = malloc(sizeof(int));
+ if (pres != NULL)
+ {
+ *(int*)pres = res;
+ }
+ pthread_exit(pres);
+#endif
+}
+
+int thrd_join(thrd_t thr, int *res)
+{
+#if defined(_TTHREAD_WIN32_)
+ if (WaitForSingleObject(thr, INFINITE) == WAIT_FAILED)
+ {
+ return thrd_error;
+ }
+ if (res != NULL)
+ {
+ DWORD dwRes;
+ GetExitCodeThread(thr, &dwRes);
+ *res = dwRes;
+ }
+#elif defined(_TTHREAD_POSIX_)
+ void *pres;
+ int ires = 0;
+ if (pthread_join(thr, &pres) != 0)
+ {
+ return thrd_error;
+ }
+ if (pres != NULL)
+ {
+ ires = *(int*)pres;
+ free(pres);
+ }
+ if (res != NULL)
+ {
+ *res = ires;
+ }
+#endif
+ return thrd_success;
+}
+
+void thrd_sleep(const xtime *xt)
+{
+ xtime now;
+#if defined(_TTHREAD_WIN32_)
+ DWORD delta;
+#else
+ long delta;
+#endif
+
+ /* Get the current time */
+ xtime_get(&now, TIME_UTC);
+
+#if defined(_TTHREAD_WIN32_)
+ /* Delta in milliseconds */
+ delta = (xt->sec - now.sec) * 1000 +
+ (xt->nsec - now.nsec + 500000) / 1000000;
+ if (delta > 0)
+ {
+ Sleep(delta);
+ }
+#else
+ /* Delta in microseconds */
+ delta = (xt->sec - now.sec) * 1000000L +
+ (xt->nsec - now.nsec + 500L) / 1000L;
+
+ /* On some systems, the usleep argument must be < 1000000 */
+ while (delta > 999999L)
+ {
+ usleep(999999);
+ delta -= 999999L;
+ }
+ if (delta > 0L)
+ {
+ usleep((useconds_t)delta);
+ }
+#endif
+}
+
+void thrd_yield(void)
+{
+#if defined(_TTHREAD_WIN32_)
+ Sleep(0);
+#else
+ sched_yield();
+#endif
+}
+
+int tss_create(tss_t *key, tss_dtor_t dtor)
+{
+#if defined(_TTHREAD_WIN32_)
+ /* FIXME: The destructor function is not supported yet... */
+ if (dtor != NULL)
+ {
+ return thrd_error;
+ }
+ *key = TlsAlloc();
+ if (*key == TLS_OUT_OF_INDEXES)
+ {
+ return thrd_error;
+ }
+#else
+ if (pthread_key_create(key, dtor) != 0)
+ {
+ return thrd_error;
+ }
+#endif
+ return thrd_success;
+}
+
+void tss_delete(tss_t key)
+{
+#if defined(_TTHREAD_WIN32_)
+ TlsFree(key);
+#else
+ pthread_key_delete(key);
+#endif
+}
+
+void *tss_get(tss_t key)
+{
+#if defined(_TTHREAD_WIN32_)
+ return TlsGetValue(key);
+#else
+ return pthread_getspecific(key);
+#endif
+}
+
+int tss_set(tss_t key, void *val)
+{
+#if defined(_TTHREAD_WIN32_)
+ if (TlsSetValue(key, val) == 0)
+ {
+ return thrd_error;
+ }
+#else
+ if (pthread_setspecific(key, val) != 0)
+ {
+ return thrd_error;
+ }
+#endif
+ return thrd_success;
+}
+
+int xtime_get(xtime *xt, int base)
+{
+ if (base == TIME_UTC)
+ {
+#if defined(_TTHREAD_WIN32_)
+ struct _timeb tb;
+ _ftime(&tb);
+ xt->sec = (time_t)tb.time;
+ xt->nsec = 1000000 * (long)tb.millitm;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ xt->sec = (time_t)tv.tv_sec;
+ xt->nsec = 1000 * (long)tv.tv_usec;
+#endif
+ return base;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
diff --git a/support/tinycthread.h b/support/tinycthread.h
new file mode 100644
index 000000000..891912235
--- /dev/null
+++ b/support/tinycthread.h
@@ -0,0 +1,404 @@
+/*
+Copyright (c) 2011 Marcus Geelnard
+
+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 _TINYCTHREAD_H_
+#define _TINYCTHREAD_H_
+
+/**
+* @file
+* @mainpage TinyCThread API Reference
+*
+* @section intro_sec Introduction
+* TinyCThread is a minimal, portable implementation of basic threading
+* classes for C.
+*
+* They closely mimic the functionality and naming of the C1X standard, and
+* should be easily replaceable with the corresponding standard variants.
+*
+* @section port_sec Portability
+* The Win32 variant uses the native Win32 API for implementing the thread
+* classes, while for other systems, the POSIX threads API (pthread) is used.
+*
+* @section misc_sec Miscellaneous
+* The following special keywords are available: #_Thread_local.
+*
+* For more detailed information, browse the different sections of this
+* documentation. A good place to start is:
+* tinycthread.h.
+*/
+
+/* Which platform are we on? */
+#if !defined(_TTHREAD_PLATFORM_DEFINED_)
+ #if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
+ #define _TTHREAD_WIN32_
+ #else
+ #define _TTHREAD_POSIX_
+ #endif
+ #define _TTHREAD_PLATFORM_DEFINED_
+#endif
+
+/* Generic includes */
+#include
+
+/* Platform specific includes */
+#if defined(_TTHREAD_POSIX_)
+ #include
+#elif defined(_TTHREAD_WIN32_)
+ #ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+ #define __UNDEF_LEAN_AND_MEAN
+ #endif
+ #include
+ #ifdef __UNDEF_LEAN_AND_MEAN
+ #undef WIN32_LEAN_AND_MEAN
+ #undef __UNDEF_LEAN_AND_MEAN
+ #endif
+#endif
+
+/** TinyCThread version (major number). */
+#define TINYCTHREAD_VERSION_MAJOR 1
+/** TinyCThread version (minor number). */
+#define TINYCTHREAD_VERSION_MINOR 0
+/** TinyCThread version (full version). */
+#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
+
+/**
+* @def _Thread_local
+* Thread local storage keyword.
+* A variable that is declared with the @c _Thread_local keyword makes the
+* value of the variable local to each thread (known as thread-local storage,
+* or TLS). Example usage:
+* @code
+* // This variable is local to each thread.
+* _Thread_local int variable;
+* @endcode
+* @note The @c _Thread_local keyword is a macro that maps to the corresponding
+* compiler directive (e.g. @c __declspec(thread)).
+* @note This directive is currently not supported on Mac OS X (it will give
+* a compiler error), since compile-time TLS is not supported in the Mac OS X
+* executable format. Also, some older versions of MinGW (before GCC 4.x) do
+* not support this directive.
+* @hideinitializer
+*/
+
+/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C1X or
+ not (the spec is still draft)... */
+#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
+ #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
+ #define _Thread_local __thread
+ #else
+ #define _Thread_local __declspec(thread)
+ #endif
+#endif
+
+/* Macros */
+#define TSS_DTOR_ITERATIONS 0
+
+/* Function return values */
+#define thrd_error 0 /**< The requested operation failed */
+#define thrd_success 1 /**< The requested operation succeeded */
+#define thrd_timeout 2 /**< The time specified in the call was reached without acquiring the requested resource */
+#define thrd_busy 3 /**< The requested operation failed because a tesource requested by a test and return function is already in use */
+#define thrd_nomem 4 /**< The requested operation failed because it was unable to allocate memory */
+
+/* Mutex types */
+#define mtx_plain 1
+#define mtx_timed 2
+#define mtx_try 4
+#define mtx_recursive 8
+
+/** Time specification */
+typedef struct {
+ time_t sec; /**< Seconds */
+ long nsec; /**< Nanoseconds */
+} xtime;
+
+/* Mutex */
+#if defined(_TTHREAD_WIN32_)
+typedef struct {
+ CRITICAL_SECTION mHandle; /* Critical section handle */
+ int mAlreadyLocked; /* TRUE if the mutex is already locked */
+ int mRecursive; /* TRUE if the mutex is recursive */
+} mtx_t;
+#else
+typedef pthread_mutex_t mtx_t;
+#endif
+
+/** Create a mutex object.
+* @param mtx A mutex object.
+* @param type Bit-mask that must have one of the following six values:
+* @li @c mtx_plain for a simple non-recursive mutex
+* @li @c mtx_timed for a non-recursive mutex that supports timeout
+* @li @c mtx_try for a non-recursive mutex that supports test and return
+* @li @c mtx_plain | @c mtx_recursive (same as @c mtx_plain, but recursive)
+* @li @c mtx_timed | @c mtx_recursive (same as @c mtx_timed, but recursive)
+* @li @c mtx_try | @c mtx_recursive (same as @c mtx_try, but recursive)
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int mtx_init(mtx_t *mtx, int type);
+
+/** Release any resources used by the given mutex.
+* @param mtx A mutex object.
+*/
+void mtx_destroy(mtx_t *mtx);
+
+/** Lock the given mutex.
+* Blocks until the given mutex can be locked. If the mutex is non-recursive, and
+* the calling thread already has a lock on the mutex, this call will block
+* forever.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int mtx_lock(mtx_t *mtx);
+
+/** NOT YET IMPLEMENTED.
+*/
+int mtx_timedlock(mtx_t *mtx, const xtime *xt);
+
+/** Try to lock the given mutex.
+* The specified mutex shall support either test and return or timeout. If the
+* mutex is already locked, the function returns without blocking.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_busy if the resource
+* requested is already in use, or @ref thrd_error if the request could not be
+* honored.
+*/
+int mtx_trylock(mtx_t *mtx);
+
+/** Unlock the given mutex.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int mtx_unlock(mtx_t *mtx);
+
+/* Condition variable */
+#if defined(_TTHREAD_WIN32_)
+typedef struct {
+ HANDLE mEvents[2]; /* Signal and broadcast event HANDLEs. */
+ unsigned int mWaitersCount; /* Count of the number of waiters. */
+ CRITICAL_SECTION mWaitersCountLock; /* Serialize access to mWaitersCount. */
+} cnd_t;
+#else
+typedef pthread_cond_t cnd_t;
+#endif
+
+/** Create a condition variable object.
+* @param cond A condition variable object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_init(cnd_t *cond);
+
+/** Release any resources used by the given condition variable.
+* @param cond A condition variable object.
+*/
+void cnd_destroy(cnd_t *cond);
+
+/** Signal a condition variable.
+* Unblocks one of the threads that are blocked on the given condition variable
+* at the time of the call. If no threads are blocked on the condition variable
+* at the time of the call, the function does nothing and return success.
+* @param cond A condition variable object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_signal(cnd_t *cond);
+
+/** Broadcast a condition variable.
+* Unblocks all of the threads that are blocked on the given condition variable
+* at the time of the call. If no threads are blocked on the condition variable
+* at the time of the call, the function does nothing and return success.
+* @param cond A condition variable object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_broadcast(cnd_t *cond);
+
+/** Wait for a condition variable to become signaled.
+* The function atomically unlocks the given mutex and endeavors to block until
+* the given condition variable is signaled by a call to cnd_signal or to
+* cnd_broadcast. When the calling thread becomes unblocked it locks the mutex
+* before it returns.
+* @param cond A condition variable object.
+* @param mtx A mutex object.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int cnd_wait(cnd_t *cond, mtx_t *mtx);
+
+/** Wait for a condition variable to become signaled.
+* The function atomically unlocks the given mutex and endeavors to block until
+* the given condition variable is signaled by a call to cnd_signal or to
+* cnd_broadcast, or until after the specified time. When the calling thread
+* becomes unblocked it locks the mutex before it returns.
+* @param cond A condition variable object.
+* @param mtx A mutex object.
+* @param xt A point in time at which the request will time out (absolute time).
+* @return @ref thrd_success upon success, or @ref thrd_timeout if the time
+* specified in the call was reached without acquiring the requested resource, or
+* @ref thrd_error if the request could not be honored.
+*/
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt);
+
+/* Thread */
+#if defined(_TTHREAD_WIN32_)
+typedef HANDLE thrd_t;
+#else
+typedef pthread_t thrd_t;
+#endif
+
+/** Thread start function.
+* Any thread that is started with the @ref thrd_create() function must be
+* started through a function of this type.
+* @param arg The thread argument (the @c arg argument of the corresponding
+* @ref thrd_create() call).
+* @return The thread return value, which can be obtained by another thread
+* by using the @ref thrd_join() function.
+*/
+typedef int (*thrd_start_t)(void *arg);
+
+/** Create a new thread.
+* @param thr Identifier of the newly created thread.
+* @param func A function pointer to the function that will be executed in
+* the new thread.
+* @param arg An argument to the thread function.
+* @return @ref thrd_success on success, or @ref thrd_nomem if no memory could
+* be allocated for the thread requested, or @ref thrd_error if the request
+* could not be honored.
+* @note A thread’s identifier may be reused for a different thread once the
+* original thread has exited and either been detached or joined to another
+* thread.
+*/
+int thrd_create(thrd_t *thr, thrd_start_t func, void *arg);
+
+/** Identify the calling thread.
+* @return The identifier of the calling thread.
+*/
+thrd_t thrd_current(void);
+
+/** NOT YET IMPLEMENTED.
+*/
+int thrd_detach(thrd_t thr);
+
+/** Compare two thread identifiers.
+* The function determines if two thread identifiers refer to the same thread.
+* @return Zero if the two thread identifiers refer to different threads.
+* Otherwise a nonzero value is returned.
+*/
+int thrd_equal(thrd_t thr0, thrd_t thr1);
+
+/** Terminate execution of the calling thread.
+* @param res Result code of the calling thread.
+*/
+void thrd_exit(int res);
+
+/** Wait for a thread to terminate.
+* The function joins the given thread with the current thread by blocking
+* until the other thread has terminated.
+* @param thr The thread to join with.
+* @param res If this pointer is not NULL, the function will store the result
+* code of the given thread in the integer pointed to by @c res.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int thrd_join(thrd_t thr, int *res);
+
+/** Put the calling thread to sleep.
+* Suspend execution of the calling thread until after the time specified by the
+* xtime object.
+* @param xt A point in time at which the thread will resume (absolute time).
+*/
+void thrd_sleep(const xtime *xt);
+
+/** Yield execution to another thread.
+* Permit other threads to run, even if the current thread would ordinarily
+* continue to run.
+*/
+void thrd_yield(void);
+
+/* Thread local storage */
+#if defined(_TTHREAD_WIN32_)
+typedef DWORD tss_t;
+#else
+typedef pthread_key_t tss_t;
+#endif
+
+/** Destructor function for a thread-specific storage.
+* @param val The value of the destructed thread-specific storage.
+*/
+typedef void (*tss_dtor_t)(void *val);
+
+/** Create a thread-specific storage.
+* @param key The unique key identifier that will be set if the function is
+* successful.
+* @param dtor Destructor function. This can be NULL.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+* @note The destructor function is not supported under Windows. If @c dtor is
+* not NULL when calling this function under Windows, the function will fail
+* and return @ref thrd_error.
+*/
+int tss_create(tss_t *key, tss_dtor_t dtor);
+
+/** Delete a thread-specific storage.
+* The function releases any resources used by the given thread-specific
+* storage.
+* @param key The key that shall be deleted.
+*/
+void tss_delete(tss_t key);
+
+/** Get the value for a thread-specific storage.
+* @param key The thread-specific storage identifier.
+* @return The value for the current thread held in the given thread-specific
+* storage.
+*/
+void *tss_get(tss_t key);
+
+/** Set the value for a thread-specific storage.
+* @param key The thread-specific storage identifier.
+* @param val The value of the thread-specific storage to set for the current
+* thread.
+* @return @ref thrd_success on success, or @ref thrd_error if the request could
+* not be honored.
+*/
+int tss_set(tss_t key, void *val);
+
+/* Timing */
+enum
+{
+ TIME_UTC = 1
+};
+
+/** Get the current time.
+* Set the xtime object to hold the current time based on the given time base.
+* @param xt Will be filled out with the current time.
+* @param base Time base (must be @c TIME_UTC).
+* @return The non-zero value @c base if the function is successful, otherwise
+* it returns zero.
+*/
+int xtime_get(xtime *xt, int base);
+
+#endif /* _TINYTHREAD_H_ */
From 9e4bc36dd84e3d84e29f7de56e8cd7e40f0c5305 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 14:13:18 +0200
Subject: [PATCH 02/50] Initial TLS implementation (Cocoa broken).
---
src/cocoa_opengl.m | 21 ++++++++++++++++++++-
src/internal.h | 2 +-
src/opengl.c | 19 +++++++++----------
src/win32_opengl.c | 28 +++++++++++++++++++++++-----
src/window.c | 5 +++--
src/x11_opengl.c | 23 ++++++++++++++++++++++-
6 files changed, 78 insertions(+), 20 deletions(-)
diff --git a/src/cocoa_opengl.m b/src/cocoa_opengl.m
index 2ffd774c9..1f1f0f23e 100644
--- a/src/cocoa_opengl.m
+++ b/src/cocoa_opengl.m
@@ -30,6 +30,13 @@
#include "internal.h"
+//========================================================================
+// The per-thread current context/window pointer
+// TODO: Implement pthreads TLS
+//========================================================================
+_GLFWwindow* _glfwCurrentWindow = NULL;
+
+
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
@@ -44,6 +51,18 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
[window->NSGL.context makeCurrentContext];
else
[NSOpenGLContext clearCurrentContext];
+
+ _glfwCurrentWindow = window;
+}
+
+
+//========================================================================
+// Return the window object whose context is current
+//========================================================================
+
+_GLFWwindow* _glfwPlatformGetCurrentContext(void)
+{
+ return _glfwCurrentWindow;
}
@@ -64,7 +83,7 @@ void _glfwPlatformSwapBuffers(_GLFWwindow* window)
void _glfwPlatformSwapInterval(int interval)
{
- _GLFWwindow* window = _glfwLibrary.currentWindow;
+ _GLFWwindow* window = _glfwCurrentWindow;
GLint sync = interval;
[window->NSGL.context setValues:&sync forParameter:NSOpenGLCPSwapInterval];
diff --git a/src/internal.h b/src/internal.h
index 89ac48b25..5ea2a815d 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -216,7 +216,6 @@ struct _GLFWlibrary
_GLFWhints hints;
_GLFWwindow* windowListHead;
- _GLFWwindow* currentWindow;
_GLFWwindow* activeWindow;
GLFWwindowsizefun windowSizeCallback;
@@ -309,6 +308,7 @@ void _glfwPlatformWaitEvents(void);
// OpenGL context management
void _glfwPlatformMakeContextCurrent(_GLFWwindow* window);
+_GLFWwindow* _glfwPlatformGetCurrentContext(void);
void _glfwPlatformSwapBuffers(_GLFWwindow* window);
void _glfwPlatformSwapInterval(int interval);
void _glfwPlatformRefreshWindowParams(_GLFWwindow* window);
diff --git a/src/opengl.c b/src/opengl.c
index 67c6f414d..dea2e387d 100644
--- a/src/opengl.c
+++ b/src/opengl.c
@@ -350,7 +350,7 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig)
GLboolean _glfwRefreshContextParams(void)
{
- _GLFWwindow* window = _glfwLibrary.currentWindow;
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (!parseGLVersion(&window->glMajor,
&window->glMinor,
@@ -417,7 +417,7 @@ GLboolean _glfwRefreshContextParams(void)
GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig)
{
- _GLFWwindow* window = _glfwLibrary.currentWindow;
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
if (window->glMajor < wndconfig->glMajor ||
(window->glMajor == wndconfig->glMajor &&
@@ -492,16 +492,15 @@ GLFWAPI void glfwMakeContextCurrent(GLFWwindow handle)
return;
}
- if (_glfwLibrary.currentWindow == window)
+ if (_glfwPlatformGetCurrentContext() == window)
return;
_glfwPlatformMakeContextCurrent(window);
- _glfwLibrary.currentWindow = window;
}
//========================================================================
-// Returns the window whose OpenGL context is current
+// Return the window object whose context is current
//========================================================================
GLFWAPI GLFWwindow glfwGetCurrentContext(void)
@@ -512,7 +511,7 @@ GLFWAPI GLFWwindow glfwGetCurrentContext(void)
return GL_FALSE;
}
- return _glfwLibrary.currentWindow;
+ return _glfwPlatformGetCurrentContext();
}
@@ -546,7 +545,7 @@ GLFWAPI void glfwSwapInterval(int interval)
return;
}
- if (!_glfwLibrary.currentWindow)
+ if (!_glfwPlatformGetCurrentContext())
{
_glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL);
return;
@@ -571,7 +570,7 @@ GLFWAPI int glfwExtensionSupported(const char* extension)
return GL_FALSE;
}
- window = _glfwLibrary.currentWindow;
+ window = _glfwPlatformGetCurrentContext();
if (!window)
{
_glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL);
@@ -632,7 +631,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname)
return NULL;
}
- if (!_glfwLibrary.currentWindow)
+ if (!_glfwPlatformGetCurrentContext())
{
_glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL);
return NULL;
@@ -660,7 +659,7 @@ GLFWAPI void glfwCopyContext(GLFWwindow hsrc, GLFWwindow hdst, unsigned long mas
src = (_GLFWwindow*) hsrc;
dst = (_GLFWwindow*) hdst;
- if (_glfwLibrary.currentWindow == dst)
+ if (_glfwPlatformGetCurrentContext() == dst)
{
_glfwSetError(GLFW_INVALID_VALUE,
"glfwCopyContext: Cannot copy OpenGL state to a current context");
diff --git a/src/win32_opengl.c b/src/win32_opengl.c
index fe1898e7b..3b30179f3 100644
--- a/src/win32_opengl.c
+++ b/src/win32_opengl.c
@@ -31,6 +31,12 @@
#include "internal.h"
+//========================================================================
+// The per-thread current context/window pointer
+//========================================================================
+__declspec(thread) _GLFWwindow* _glfwCurrentWindow = NULL;
+
+
//========================================================================
// Initialize WGL-specific extensions
// This function is called once before initial context creation, i.e. before
@@ -438,7 +444,7 @@ static GLboolean createContext(_GLFWwindow* window,
}
}
- glfwMakeContextCurrent(window);
+ _glfwPlatformMakeContextCurrent(window);
initWGLExtensions(window);
return GL_TRUE;
@@ -507,8 +513,8 @@ void _glfwDestroyContext(_GLFWwindow* window)
{
// This is duplicated from glfwDestroyWindow
// TODO: Stop duplicating code
- if (window == _glfwLibrary.currentWindow)
- glfwMakeContextCurrent(NULL);
+ if (window == _glfwCurrentWindow)
+ _glfwPlatformMakeContextCurrent(NULL);
if (window->WGL.context)
{
@@ -538,6 +544,18 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
wglMakeCurrent(window->WGL.DC, window->WGL.context);
else
wglMakeCurrent(NULL, NULL);
+
+ _glfwCurrentWindow = window;
+}
+
+
+//========================================================================
+// Return the window object whose context is current
+//========================================================================
+
+_GLFWwindow* _glfwPlatformGetCurrentContext(void)
+{
+ return _glfwCurrentWindow;
}
@@ -557,7 +575,7 @@ void _glfwPlatformSwapBuffers(_GLFWwindow* window)
void _glfwPlatformSwapInterval(int interval)
{
- _GLFWwindow* window = _glfwLibrary.currentWindow;
+ _GLFWwindow* window = _glfwCurrentWindow;
if (window->WGL.EXT_swap_control)
window->WGL.SwapIntervalEXT(interval);
@@ -572,7 +590,7 @@ int _glfwPlatformExtensionSupported(const char* extension)
{
const GLubyte* extensions;
- _GLFWwindow* window = _glfwLibrary.currentWindow;
+ _GLFWwindow* window = _glfwCurrentWindow;
if (window->WGL.GetExtensionsStringEXT != NULL)
{
diff --git a/src/window.c b/src/window.c
index df5927510..352e3ad9d 100644
--- a/src/window.c
+++ b/src/window.c
@@ -451,8 +451,9 @@ GLFWAPI void glfwDestroyWindow(GLFWwindow handle)
return;
// Clear the current context if this window's context is current
- if (window == _glfwLibrary.currentWindow)
- glfwMakeContextCurrent(NULL);
+ // TODO: Re-examine this in light of multithreading
+ if (window == _glfwPlatformGetCurrentContext())
+ _glfwPlatformMakeContextCurrent(NULL);
// Clear the active window pointer if this is the active window
if (window == _glfwLibrary.activeWindow)
diff --git a/src/x11_opengl.c b/src/x11_opengl.c
index 2a5cc4512..d7f33999c 100644
--- a/src/x11_opengl.c
+++ b/src/x11_opengl.c
@@ -37,6 +37,11 @@
// This is the only glXGetProcAddress variant not declared by glxext.h
void (*glXGetProcAddressEXT(const GLubyte* procName))();
+//========================================================================
+// The per-thread current context/window pointer
+//========================================================================
+__thread _GLFWwindow* _glfwCurrentWindow = NULL;
+
//========================================================================
// Returns the specified attribute of the specified GLXFBConfig
@@ -621,6 +626,10 @@ XVisualInfo* _glfwGetContextVisual(_GLFWwindow* window)
}
+//////////////////////////////////////////////////////////////////////////
+////// GLFW platform API //////
+//////////////////////////////////////////////////////////////////////////
+
//========================================================================
// Make the OpenGL context associated with the specified window current
//========================================================================
@@ -635,6 +644,18 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
}
else
glXMakeCurrent(_glfwLibrary.X11.display, None, NULL);
+
+ _glfwCurrentWindow = window;
+}
+
+
+//========================================================================
+// Return the window object whose context is current
+//========================================================================
+
+_GLFWwindow* _glfwPlatformGetCurrentContext(void)
+{
+ return _glfwCurrentWindow;
}
@@ -654,7 +675,7 @@ void _glfwPlatformSwapBuffers(_GLFWwindow* window)
void _glfwPlatformSwapInterval(int interval)
{
- _GLFWwindow* window = _glfwLibrary.currentWindow;
+ _GLFWwindow* window = _glfwCurrentWindow;
if (_glfwLibrary.GLX.EXT_swap_control)
{
From 14abb3c15d0eb53906b14d2cb77cdc8c9cadd9fe Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 15:04:59 +0200
Subject: [PATCH 03/50] Updated TinyCThread.
---
support/tinycthread.c | 4 ++--
support/tinycthread.h | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/support/tinycthread.c b/support/tinycthread.c
index f97d07cc0..9bee2cb55 100644
--- a/support/tinycthread.c
+++ b/support/tinycthread.c
@@ -1,5 +1,5 @@
-/*
-Copyright (c) 2011 Marcus Geelnard
+/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
diff --git a/support/tinycthread.h b/support/tinycthread.h
index 891912235..8069e3f36 100644
--- a/support/tinycthread.h
+++ b/support/tinycthread.h
@@ -1,5 +1,5 @@
-/*
-Copyright (c) 2011 Marcus Geelnard
+/* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; -*-
+Copyright (c) 2012 Marcus Geelnard
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@@ -32,7 +32,7 @@ freely, subject to the following restrictions:
* TinyCThread is a minimal, portable implementation of basic threading
* classes for C.
*
-* They closely mimic the functionality and naming of the C1X standard, and
+* They closely mimic the functionality and naming of the C11 standard, and
* should be easily replaceable with the corresponding standard variants.
*
* @section port_sec Portability
@@ -101,8 +101,7 @@ freely, subject to the following restrictions:
* @hideinitializer
*/
-/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C1X or
- not (the spec is still draft)... */
+/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 or */
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define _Thread_local __thread
@@ -402,3 +401,4 @@ enum
int xtime_get(xtime *xt, int base);
#endif /* _TINYTHREAD_H_ */
+
From 5b95715bb1dee204e603a008eaf4afd91ae4f4d2 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 15:05:18 +0200
Subject: [PATCH 04/50] Added simple silly stupid test.
---
tests/CMakeLists.txt | 5 ++-
tests/threads.c | 96 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 100 insertions(+), 1 deletion(-)
create mode 100644 tests/threads.c
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index bcad7ef54..9be1c1cdd 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -14,6 +14,8 @@ include_directories(${GLFW_SOURCE_DIR}/include
set(GETOPT ${GLFW_SOURCE_DIR}/support/getopt.h
${GLFW_SOURCE_DIR}/support/getopt.c)
+set(TINYCTHREAD ${GLFW_SOURCE_DIR}/support/tinycthread.h
+ ${GLFW_SOURCE_DIR}/support/tinycthread.c)
add_executable(clipboard clipboard.c ${GETOPT})
add_executable(defaults defaults.c)
@@ -27,6 +29,7 @@ add_executable(joysticks joysticks.c)
add_executable(modes modes.c ${GETOPT})
add_executable(peter peter.c)
add_executable(reopen reopen.c)
+add_executable(threads threads.c ${TINYCTHREAD})
add_executable(accuracy WIN32 MACOSX_BUNDLE accuracy.c)
set_target_properties(accuracy PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Accuracy")
@@ -45,7 +48,7 @@ set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
set(WINDOWS_BINARIES accuracy sharing tearing title windows)
set(CONSOLE_BINARIES clipboard defaults events fsaa fsfocus gamma glfwinfo
- iconify joysticks modes peter reopen)
+ iconify joysticks modes peter reopen threads)
if (MSVC)
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
diff --git a/tests/threads.c b/tests/threads.c
new file mode 100644
index 000000000..ba844dd75
--- /dev/null
+++ b/tests/threads.c
@@ -0,0 +1,96 @@
+//========================================================================
+// Multithreading test
+// Copyright (c) Camilla Berglund
+//
+// 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.
+//
+//========================================================================
+//
+// This test is intended to verify whether the OpenGL context part of
+// the GLFW API is able to be used from multiple threads
+//
+//========================================================================
+
+#include
+
+#include
+#include
+#include
+
+#include "tinycthread.h"
+
+static GLboolean running = GL_TRUE;
+
+static int thread_start(void* data)
+{
+ GLFWwindow window = (GLFWwindow) data;
+
+ glfwMakeContextCurrent(window);
+ glfwSwapInterval(1);
+
+ while (running)
+ {
+ const float red = (float) sin(glfwGetTime()) / 2.f + 0.5f;
+
+ glClearColor(red, 0.f, 0.f, 0.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glfwSwapBuffers(window);
+ }
+
+ glfwMakeContextCurrent(NULL);
+ return 0;
+}
+
+int main(void)
+{
+ int result;
+ GLFWwindow window;
+ thrd_t thread;
+
+ if (!glfwInit())
+ {
+ fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError()));
+ exit(EXIT_FAILURE);
+ }
+
+ window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Multithreading", NULL);
+ if (!window)
+ {
+ fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError()));
+ exit(EXIT_FAILURE);
+ }
+
+ if (thrd_create(&thread, thread_start, window) == thrd_success)
+ {
+ while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED))
+ glfwPollEvents();
+
+ running = GL_FALSE;
+ thrd_join(thread, &result);
+ }
+ else
+ {
+ fprintf(stderr, "Failed to create secondary thread\n");
+ exit(EXIT_FAILURE);
+ }
+
+ exit(EXIT_SUCCESS);
+}
+
From 3d6221c490fab8bf70ba527430a2518c821c1027 Mon Sep 17 00:00:00 2001
From: Riku Salminen
Date: Sun, 12 Aug 2012 15:57:52 +0200
Subject: [PATCH 05/50] Added support for multithreaded use of Xlib.
---
src/x11_init.c | 2 +
src/x11_window.c | 137 ++++++++++++++++++++++++-----------------------
2 files changed, 73 insertions(+), 66 deletions(-)
diff --git a/src/x11_init.c b/src/x11_init.c
index 372fc2dd5..afa9de331 100644
--- a/src/x11_init.c
+++ b/src/x11_init.c
@@ -634,6 +634,8 @@ static void terminateDisplay(void)
int _glfwPlatformInit(void)
{
+ XInitThreads();
+
if (!initDisplay())
return GL_FALSE;
diff --git a/src/x11_window.c b/src/x11_window.c
index 442e76c02..60a182871 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -468,19 +468,16 @@ static _GLFWwindow* findWindow(Window handle)
// Get and process next X event (called by _glfwPlatformPollEvents)
//========================================================================
-static void processSingleEvent(void)
+static void processSingleEvent(XEvent *event)
{
_GLFWwindow* window;
- XEvent event;
- XNextEvent(_glfwLibrary.X11.display, &event);
-
- switch (event.type)
+ switch (event->type)
{
case KeyPress:
{
// A keyboard key was pressed
- window = findWindow(event.xkey.window);
+ window = findWindow(event->xkey.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for KeyPress event\n");
@@ -488,10 +485,10 @@ static void processSingleEvent(void)
}
// Translate and report key press
- _glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_PRESS);
+ _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_PRESS);
// Translate and report character input
- _glfwInputChar(window, translateChar(&event.xkey));
+ _glfwInputChar(window, translateChar(&event->xkey));
break;
}
@@ -499,7 +496,7 @@ static void processSingleEvent(void)
case KeyRelease:
{
// A keyboard key was released
- window = findWindow(event.xkey.window);
+ window = findWindow(event->xkey.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for KeyRelease event\n");
@@ -516,15 +513,15 @@ static void processSingleEvent(void)
XPeekEvent(_glfwLibrary.X11.display, &nextEvent);
if (nextEvent.type == KeyPress &&
- nextEvent.xkey.window == event.xkey.window &&
- nextEvent.xkey.keycode == event.xkey.keycode)
+ nextEvent.xkey.window == event->xkey.window &&
+ nextEvent.xkey.keycode == event->xkey.keycode)
{
// This last check is a hack to work around key repeats
// leaking through due to some sort of time drift
// Toshiyuki Takahashi can press a button 16 times per
// second so it's fairly safe to assume that no human is
// pressing the key 50 times per second (value is ms)
- if ((nextEvent.xkey.time - event.xkey.time) < 20)
+ if ((nextEvent.xkey.time - event->xkey.time) < 20)
{
// Do not report anything for this event
break;
@@ -533,7 +530,7 @@ static void processSingleEvent(void)
}
// Translate and report key release
- _glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_RELEASE);
+ _glfwInputKey(window, translateKey(event->xkey.keycode), GLFW_RELEASE);
break;
}
@@ -541,30 +538,30 @@ static void processSingleEvent(void)
case ButtonPress:
{
// A mouse button was pressed or a scrolling event occurred
- window = findWindow(event.xbutton.window);
+ window = findWindow(event->xbutton.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for ButtonPress event\n");
return;
}
- if (event.xbutton.button == Button1)
+ if (event->xbutton.button == Button1)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS);
- else if (event.xbutton.button == Button2)
+ else if (event->xbutton.button == Button2)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_MIDDLE, GLFW_PRESS);
- else if (event.xbutton.button == Button3)
+ else if (event->xbutton.button == Button3)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_RIGHT, GLFW_PRESS);
// XFree86 3.3.2 and later translates mouse wheel up/down into
// mouse button 4 & 5 presses
- else if (event.xbutton.button == Button4)
+ else if (event->xbutton.button == Button4)
_glfwInputScroll(window, 0.0, 1.0);
- else if (event.xbutton.button == Button5)
+ else if (event->xbutton.button == Button5)
_glfwInputScroll(window, 0.0, -1.0);
- else if (event.xbutton.button == Button6)
+ else if (event->xbutton.button == Button6)
_glfwInputScroll(window, -1.0, 0.0);
- else if (event.xbutton.button == Button7)
+ else if (event->xbutton.button == Button7)
_glfwInputScroll(window, 1.0, 0.0);
break;
@@ -573,26 +570,26 @@ static void processSingleEvent(void)
case ButtonRelease:
{
// A mouse button was released
- window = findWindow(event.xbutton.window);
+ window = findWindow(event->xbutton.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for ButtonRelease event\n");
return;
}
- if (event.xbutton.button == Button1)
+ if (event->xbutton.button == Button1)
{
_glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_LEFT,
GLFW_RELEASE);
}
- else if (event.xbutton.button == Button2)
+ else if (event->xbutton.button == Button2)
{
_glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_MIDDLE,
GLFW_RELEASE);
}
- else if (event.xbutton.button == Button3)
+ else if (event->xbutton.button == Button3)
{
_glfwInputMouseClick(window,
GLFW_MOUSE_BUTTON_RIGHT,
@@ -604,7 +601,7 @@ static void processSingleEvent(void)
case EnterNotify:
{
// The cursor entered the window
- window = findWindow(event.xcrossing.window);
+ window = findWindow(event->xcrossing.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for EnterNotify event\n");
@@ -621,7 +618,7 @@ static void processSingleEvent(void)
case LeaveNotify:
{
// The cursor left the window
- window = findWindow(event.xcrossing.window);
+ window = findWindow(event->xcrossing.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for LeaveNotify event\n");
@@ -638,15 +635,15 @@ static void processSingleEvent(void)
case MotionNotify:
{
// The cursor was moved
- window = findWindow(event.xmotion.window);
+ window = findWindow(event->xmotion.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for MotionNotify event\n");
return;
}
- if (event.xmotion.x != window->X11.cursorPosX ||
- event.xmotion.y != window->X11.cursorPosY)
+ if (event->xmotion.x != window->X11.cursorPosX ||
+ event->xmotion.y != window->X11.cursorPosY)
{
// The cursor was moved and we didn't do it
int x, y;
@@ -656,17 +653,17 @@ static void processSingleEvent(void)
if (_glfwLibrary.activeWindow != window)
break;
- x = event.xmotion.x - window->X11.cursorPosX;
- y = event.xmotion.y - window->X11.cursorPosY;
+ x = event->xmotion.x - window->X11.cursorPosX;
+ y = event->xmotion.y - window->X11.cursorPosY;
}
else
{
- x = event.xmotion.x;
- y = event.xmotion.y;
+ x = event->xmotion.x;
+ y = event->xmotion.y;
}
- window->X11.cursorPosX = event.xmotion.x;
- window->X11.cursorPosY = event.xmotion.y;
+ window->X11.cursorPosX = event->xmotion.x;
+ window->X11.cursorPosY = event->xmotion.y;
window->X11.cursorCentered = GL_FALSE;
_glfwInputCursorMotion(window, x, y);
@@ -678,7 +675,7 @@ static void processSingleEvent(void)
case ConfigureNotify:
{
// The window configuration changed somehow
- window = findWindow(event.xconfigure.window);
+ window = findWindow(event->xconfigure.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for ConfigureNotify event\n");
@@ -686,12 +683,12 @@ static void processSingleEvent(void)
}
_glfwInputWindowSize(window,
- event.xconfigure.width,
- event.xconfigure.height);
+ event->xconfigure.width,
+ event->xconfigure.height);
_glfwInputWindowPos(window,
- event.xconfigure.x,
- event.xconfigure.y);
+ event->xconfigure.x,
+ event->xconfigure.y);
break;
}
@@ -699,14 +696,14 @@ static void processSingleEvent(void)
case ClientMessage:
{
// Custom client message, probably from the window manager
- window = findWindow(event.xclient.window);
+ window = findWindow(event->xclient.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for ClientMessage event\n");
return;
}
- if ((Atom) event.xclient.data.l[0] == _glfwLibrary.X11.wmDeleteWindow)
+ if ((Atom) event->xclient.data.l[0] == _glfwLibrary.X11.wmDeleteWindow)
{
// The window manager was asked to close the window, for example by
// the user pressing a 'close' window decoration button
@@ -714,17 +711,17 @@ static void processSingleEvent(void)
_glfwInputWindowCloseRequest(window);
}
else if (_glfwLibrary.X11.wmPing != None &&
- (Atom) event.xclient.data.l[0] == _glfwLibrary.X11.wmPing)
+ (Atom) event->xclient.data.l[0] == _glfwLibrary.X11.wmPing)
{
// The window manager is pinging us to make sure we are still
// responding to events
- event.xclient.window = _glfwLibrary.X11.root;
+ event->xclient.window = _glfwLibrary.X11.root;
XSendEvent(_glfwLibrary.X11.display,
- event.xclient.window,
+ event->xclient.window,
False,
SubstructureNotifyMask | SubstructureRedirectMask,
- &event);
+ event);
}
break;
@@ -733,7 +730,7 @@ static void processSingleEvent(void)
case MapNotify:
{
// The window was mapped
- window = findWindow(event.xmap.window);
+ window = findWindow(event->xmap.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for MapNotify event\n");
@@ -747,7 +744,7 @@ static void processSingleEvent(void)
case UnmapNotify:
{
// The window was unmapped
- window = findWindow(event.xmap.window);
+ window = findWindow(event->xmap.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for UnmapNotify event\n");
@@ -761,7 +758,7 @@ static void processSingleEvent(void)
case FocusIn:
{
// The window gained focus
- window = findWindow(event.xfocus.window);
+ window = findWindow(event->xfocus.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for FocusIn event\n");
@@ -779,7 +776,7 @@ static void processSingleEvent(void)
case FocusOut:
{
// The window lost focus
- window = findWindow(event.xfocus.window);
+ window = findWindow(event->xfocus.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for FocusOut event\n");
@@ -797,7 +794,7 @@ static void processSingleEvent(void)
case Expose:
{
// The window's contents was damaged
- window = findWindow(event.xexpose.window);
+ window = findWindow(event->xexpose.window);
if (window == NULL)
{
fprintf(stderr, "Cannot find GLFW window structure for Expose event\n");
@@ -821,7 +818,7 @@ static void processSingleEvent(void)
{
// The selection conversion status is available
- XSelectionEvent* request = &event.xselection;
+ XSelectionEvent* request = &event->xselection;
if (_glfwReadSelection(request))
_glfwLibrary.X11.selection.status = _GLFW_CONVERSION_SUCCEEDED;
@@ -835,7 +832,7 @@ static void processSingleEvent(void)
{
// The contents of the selection was requested
- XSelectionRequestEvent* request = &event.xselectionrequest;
+ XSelectionRequestEvent* request = &event->xselectionrequest;
XEvent response;
memset(&response, 0, sizeof(response));
@@ -860,12 +857,12 @@ static void processSingleEvent(void)
default:
{
#if defined(_GLFW_HAS_XRANDR)
- switch (event.type - _glfwLibrary.X11.RandR.eventBase)
+ switch (event->type - _glfwLibrary.X11.RandR.eventBase)
{
case RRScreenChangeNotify:
{
// Show XRandR that we really care
- XRRUpdateConfiguration(&event);
+ XRRUpdateConfiguration(event);
break;
}
}
@@ -1146,13 +1143,14 @@ void _glfwPlatformRefreshWindowParams(_GLFWwindow* window)
void _glfwPlatformPollEvents(void)
{
- _GLFWwindow* window;
-
- // Process all pending events
- while (XPending(_glfwLibrary.X11.display))
- processSingleEvent();
+ XEvent event;
+ while(XCheckMaskEvent(_glfwLibrary.X11.display, ~0, &event) ||
+ XCheckTypedEvent(_glfwLibrary.X11.display, ClientMessage, &event))
+ processSingleEvent(&event);
+#if 0
// Did the cursor move in an active window that has captured the cursor
+ _GLFWwindow* window;
window = _glfwLibrary.activeWindow;
if (window)
{
@@ -1170,8 +1168,10 @@ void _glfwPlatformPollEvents(void)
XFlush( _glfwLibrary.X11.display );
}
}
+#endif
}
+#include
//========================================================================
// Wait for new window and input events
@@ -1179,13 +1179,18 @@ void _glfwPlatformPollEvents(void)
void _glfwPlatformWaitEvents(void)
{
- XEvent event;
+ fd_set set;
+ int fd;
- // Block waiting for an event to arrive
- XNextEvent(_glfwLibrary.X11.display, &event);
- XPutBackEvent(_glfwLibrary.X11.display, &event);
+ fd = ConnectionNumber(_glfwLibrary.X11.display);
- _glfwPlatformPollEvents();
+ FD_ZERO(&set);
+ FD_SET(fd, &set);
+
+ XFlush(_glfwLibrary.X11.display);
+
+ if(select(fd+1, &set, NULL, NULL, NULL) > 0)
+ _glfwPlatformPollEvents();
}
From 208b7f0bb8ffad428b2dd901f621da36af5559f8 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:04:03 +0200
Subject: [PATCH 06/50] Formatting.
---
src/x11_window.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/x11_window.c b/src/x11_window.c
index 60a182871..2d85e0416 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -468,7 +468,7 @@ static _GLFWwindow* findWindow(Window handle)
// Get and process next X event (called by _glfwPlatformPollEvents)
//========================================================================
-static void processSingleEvent(XEvent *event)
+static void processEvent(XEvent *event)
{
_GLFWwindow* window;
@@ -1144,9 +1144,12 @@ void _glfwPlatformRefreshWindowParams(_GLFWwindow* window)
void _glfwPlatformPollEvents(void)
{
XEvent event;
- while(XCheckMaskEvent(_glfwLibrary.X11.display, ~0, &event) ||
- XCheckTypedEvent(_glfwLibrary.X11.display, ClientMessage, &event))
- processSingleEvent(&event);
+
+ while (XCheckMaskEvent(_glfwLibrary.X11.display, ~0, &event) ||
+ XCheckTypedEvent(_glfwLibrary.X11.display, ClientMessage, &event))
+ {
+ processEvent(&event);
+ }
#if 0
// Did the cursor move in an active window that has captured the cursor
From f66e6a6916c37b0459c46dedc36cd66f47f20cd3 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:05:43 +0200
Subject: [PATCH 07/50] Re-enabled cursor re-centering.
---
src/x11_window.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/x11_window.c b/src/x11_window.c
index 2d85e0416..4cf2ce5b8 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -1151,8 +1151,9 @@ void _glfwPlatformPollEvents(void)
processEvent(&event);
}
-#if 0
- // Did the cursor move in an active window that has captured the cursor
+ // Check whether the cursor has moved inside an active window that has
+ // captured the cursor (because then it needs to be re-centered)
+
_GLFWwindow* window;
window = _glfwLibrary.activeWindow;
if (window)
@@ -1171,7 +1172,6 @@ void _glfwPlatformPollEvents(void)
XFlush( _glfwLibrary.X11.display );
}
}
-#endif
}
#include
From fd125f7e54d9ed24d5a4fea55c2cb091bfa01229 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:06:22 +0200
Subject: [PATCH 08/50] Moved inclusion directive to proper location.
---
src/x11_window.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/x11_window.c b/src/x11_window.c
index 4cf2ce5b8..0a3608cb6 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -30,6 +30,8 @@
#include "internal.h"
+#include
+
#include
#include
#include
@@ -1174,8 +1176,6 @@ void _glfwPlatformPollEvents(void)
}
}
-#include
-
//========================================================================
// Wait for new window and input events
//========================================================================
From 98c1c2fbf2c483efd4a84b907d2195bcdf948bf6 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:18:59 +0200
Subject: [PATCH 09/50] Added threading support to CMake files.
---
CMakeLists.txt | 6 ++++++
tests/CMakeLists.txt | 4 ++++
2 files changed, 10 insertions(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 27a609a61..842612e87 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,12 @@ option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
find_package(OpenGL REQUIRED)
+set(CMAKE_THREAD_PREFER_PTHREADS YES)
+find_package(Threads)
+if (CMAKE_THREAD_LIBS_INIT)
+ list(APPEND glfw_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+endif()
+
#--------------------------------------------------------------------
# Enable all warnings on GCC, regardless of OS
#--------------------------------------------------------------------
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 9be1c1cdd..e2d2a825f 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -31,6 +31,10 @@ add_executable(peter peter.c)
add_executable(reopen reopen.c)
add_executable(threads threads.c ${TINYCTHREAD})
+if (BUILD_SHARED_LIBS)
+ target_link_libraries(threads ${CMAKE_THREAD_LIBS_INIT})
+endif()
+
add_executable(accuracy WIN32 MACOSX_BUNDLE accuracy.c)
set_target_properties(accuracy PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Accuracy")
From 6c449e6e8f65ade80a7628acaaf255889e6864d6 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:21:06 +0200
Subject: [PATCH 10/50] Formatting.
---
src/x11_window.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/x11_window.c b/src/x11_window.c
index 0a3608cb6..d2f471d0e 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -467,7 +467,7 @@ static _GLFWwindow* findWindow(Window handle)
//========================================================================
-// Get and process next X event (called by _glfwPlatformPollEvents)
+// Process the specified X event
//========================================================================
static void processEvent(XEvent *event)
@@ -1176,23 +1176,24 @@ void _glfwPlatformPollEvents(void)
}
}
+
//========================================================================
// Wait for new window and input events
//========================================================================
void _glfwPlatformWaitEvents(void)
{
- fd_set set;
int fd;
+ fd_set fds;
fd = ConnectionNumber(_glfwLibrary.X11.display);
- FD_ZERO(&set);
- FD_SET(fd, &set);
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
XFlush(_glfwLibrary.X11.display);
- if(select(fd+1, &set, NULL, NULL, NULL) > 0)
+ if (select(fd + 1, &fds, NULL, NULL, NULL) > 0)
_glfwPlatformPollEvents();
}
From ac3a5e28c9eca16696df93c5f5ba87e4bcdec22e Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:24:37 +0200
Subject: [PATCH 11/50] Made the leap to glfwWaitEvents.
---
tests/threads.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/threads.c b/tests/threads.c
index ba844dd75..f19fdf88f 100644
--- a/tests/threads.c
+++ b/tests/threads.c
@@ -80,7 +80,7 @@ int main(void)
if (thrd_create(&thread, thread_start, window) == thrd_success)
{
while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED))
- glfwPollEvents();
+ glfwWaitEvents();
running = GL_FALSE;
thrd_join(thread, &result);
From 4057885ac3c82ed8726e32251b31c6f10fd98d69 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 16:32:54 +0200
Subject: [PATCH 12/50] Decreased nesting in threads test.
---
tests/threads.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/tests/threads.c b/tests/threads.c
index f19fdf88f..de656e011 100644
--- a/tests/threads.c
+++ b/tests/threads.c
@@ -77,20 +77,18 @@ int main(void)
exit(EXIT_FAILURE);
}
- if (thrd_create(&thread, thread_start, window) == thrd_success)
- {
- while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED))
- glfwWaitEvents();
-
- running = GL_FALSE;
- thrd_join(thread, &result);
- }
- else
+ if (thrd_create(&thread, thread_start, window) != thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
exit(EXIT_FAILURE);
}
+ while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED))
+ glfwWaitEvents();
+
+ running = GL_FALSE;
+ thrd_join(thread, &result);
+
exit(EXIT_SUCCESS);
}
From c594bb468901fd196c72e0848152601aca6df7b3 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 12 Aug 2012 22:36:10 +0200
Subject: [PATCH 13/50] Made loop boolean volatile.
---
tests/threads.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/threads.c b/tests/threads.c
index de656e011..d78431067 100644
--- a/tests/threads.c
+++ b/tests/threads.c
@@ -36,7 +36,7 @@
#include "tinycthread.h"
-static GLboolean running = GL_TRUE;
+static volatile GLboolean running = GL_TRUE;
static int thread_start(void* data)
{
From 18a5aba8f1bf4c7b3bf722fc036b31b7223ccfcb Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Mon, 13 Aug 2012 16:03:44 +0200
Subject: [PATCH 14/50] Implemented TLS for all platforms.
---
src/cocoa_init.m | 5 +++++
src/cocoa_opengl.m | 38 +++++++++++++++++++++++++++++++++-----
src/cocoa_platform.h | 4 ++++
src/win32_opengl.c | 14 +++++++++++++-
src/x11_opengl.c | 13 ++++++++++++-
5 files changed, 67 insertions(+), 7 deletions(-)
diff --git a/src/cocoa_init.m b/src/cocoa_init.m
index 7c208b90e..3bb61c18a 100644
--- a/src/cocoa_init.m
+++ b/src/cocoa_init.m
@@ -103,6 +103,9 @@ int _glfwPlatformInit(void)
_glfwInitJoysticks();
+ if (!_glfwInitOpenGL())
+ return GL_FALSE;
+
_glfwLibrary.NS.eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
if (!_glfwLibrary.NS.eventSource)
return GL_FALSE;
@@ -143,6 +146,8 @@ int _glfwPlatformTerminate(void)
_glfwTerminateJoysticks();
+ _glfwTerminateOpenGL();
+
return GL_TRUE;
}
diff --git a/src/cocoa_opengl.m b/src/cocoa_opengl.m
index 1f1f0f23e..4d4c4299f 100644
--- a/src/cocoa_opengl.m
+++ b/src/cocoa_opengl.m
@@ -29,18 +29,46 @@
#include "internal.h"
+#include
+
//========================================================================
// The per-thread current context/window pointer
-// TODO: Implement pthreads TLS
//========================================================================
-_GLFWwindow* _glfwCurrentWindow = NULL;
+static pthread_key_t _glfwCurrentTLS;
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
+//========================================================================
+// Initialize OpenGL support
+//========================================================================
+
+int _glfwInitOpenGL(void)
+{
+ if (pthread_key_create(&_glfwCurrentTLS, NULL) != 0)
+ {
+ _glfwSetError(GLFW_PLATFORM_ERROR,
+ "Cocoa/NSGL: Failed to create context TLS");
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+
+//========================================================================
+// Terminate OpenGL support
+//========================================================================
+
+void _glfwTerminateOpenGL(void)
+{
+ pthread_key_delete(_glfwCurrentTLS);
+}
+
+
//========================================================================
// Make the OpenGL context associated with the specified window current
//========================================================================
@@ -52,7 +80,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
else
[NSOpenGLContext clearCurrentContext];
- _glfwCurrentWindow = window;
+ pthread_setspecific(_glfwCurrentTLS, window);
}
@@ -62,7 +90,7 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window)
_GLFWwindow* _glfwPlatformGetCurrentContext(void)
{
- return _glfwCurrentWindow;
+ return (_GLFWwindow*) pthread_getspecific(_glfwCurrentTLS);
}
@@ -83,7 +111,7 @@ void _glfwPlatformSwapBuffers(_GLFWwindow* window)
void _glfwPlatformSwapInterval(int interval)
{
- _GLFWwindow* window = _glfwCurrentWindow;
+ _GLFWwindow* window = _glfwPlatformGetCurrentContext();
GLint sync = interval;
[window->NSGL.context setValues:&sync forParameter:NSOpenGLCPSwapInterval];
diff --git a/src/cocoa_platform.h b/src/cocoa_platform.h
index 97e903d7b..a202c25eb 100644
--- a/src/cocoa_platform.h
+++ b/src/cocoa_platform.h
@@ -124,4 +124,8 @@ void _glfwTerminateJoysticks(void);
GLboolean _glfwSetVideoMode(int* width, int* height, int* bpp, int* refreshRate);
void _glfwRestoreVideoMode(void);
+// OpenGL support
+int _glfwInitOpenGL(void);
+void _glfwTerminateOpenGL(void);
+
#endif // _platform_h_
diff --git a/src/win32_opengl.c b/src/win32_opengl.c
index fb0ba47f8..6801e1440 100644
--- a/src/win32_opengl.c
+++ b/src/win32_opengl.c
@@ -33,10 +33,22 @@
#include
+//========================================================================
+// Thread local storage attribute macro
+//========================================================================
+#if defined(_MSC_VER)
+ #define _GLFW_TLS __declspec(thread)
+#elif defined(__GNUC__)
+ #define _GLFW_TLS __thread
+#else
+ #define _GLFW_TLS
+#endif
+
+
//========================================================================
// The per-thread current context/window pointer
//========================================================================
-__declspec(thread) _GLFWwindow* _glfwCurrentWindow = NULL;
+static _GLFW_TLS _GLFWwindow* _glfwCurrentWindow = NULL;
//========================================================================
diff --git a/src/x11_opengl.c b/src/x11_opengl.c
index d7f33999c..38a43ff0d 100644
--- a/src/x11_opengl.c
+++ b/src/x11_opengl.c
@@ -37,10 +37,21 @@
// This is the only glXGetProcAddress variant not declared by glxext.h
void (*glXGetProcAddressEXT(const GLubyte* procName))();
+
+//========================================================================
+// Thread local storage attribute macro
+//========================================================================
+#if defined(__GNUC__)
+ #define _GLFW_TLS __thread
+#else
+ #define _GLFW_TLS
+#endif
+
+
//========================================================================
// The per-thread current context/window pointer
//========================================================================
-__thread _GLFWwindow* _glfwCurrentWindow = NULL;
+static _GLFW_TLS _GLFWwindow* _glfwCurrentWindow = NULL;
//========================================================================
From 86bcfb3e4ecd72fbd59a603ebecb97a39943399b Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Mon, 13 Aug 2012 19:37:39 +0200
Subject: [PATCH 15/50] Added multiple windows to threads test.
---
tests/threads.c | 77 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 57 insertions(+), 20 deletions(-)
diff --git a/tests/threads.c b/tests/threads.c
index d78431067..6e3a6eaf9 100644
--- a/tests/threads.c
+++ b/tests/threads.c
@@ -33,25 +33,36 @@
#include
#include
#include
+#include
#include "tinycthread.h"
+typedef struct
+{
+ GLFWwindow window;
+ const char* title;
+ float r, g, b;
+ thrd_t ID;
+} Thread;
+
static volatile GLboolean running = GL_TRUE;
static int thread_start(void* data)
{
- GLFWwindow window = (GLFWwindow) data;
+ const Thread* thread = (const Thread*) data;
+
+ glfwMakeContextCurrent(thread->window);
+ assert(glfwGetCurrentContext() == thread->window);
- glfwMakeContextCurrent(window);
glfwSwapInterval(1);
while (running)
{
- const float red = (float) sin(glfwGetTime()) / 2.f + 0.5f;
+ const float v = (float) fabs(sin(glfwGetTime() * 2.f));
+ glClearColor(thread->r * v, thread->g * v, thread->b * v, 0.f);
- glClearColor(red, 0.f, 0.f, 0.f);
glClear(GL_COLOR_BUFFER_BIT);
- glfwSwapBuffers(window);
+ glfwSwapBuffers(thread->window);
}
glfwMakeContextCurrent(NULL);
@@ -60,34 +71,60 @@ static int thread_start(void* data)
int main(void)
{
- int result;
- GLFWwindow window;
- thrd_t thread;
+ int i, result;
+ Thread threads[] =
+ {
+ { NULL, "Red", 1.f, 0.f, 0.f, 0 },
+ { NULL, "Green", 0.f, 1.f, 0.f, 0 },
+ { NULL, "Blue", 0.f, 0.f, 1.f, 0 }
+ };
+ const int count = sizeof(threads) / sizeof(Thread);
if (!glfwInit())
{
- fprintf(stderr, "Failed to initialize GLFW: %s\n", glfwErrorString(glfwGetError()));
+ fprintf(stderr, "Failed to initialize GLFW: %s\n",
+ glfwErrorString(glfwGetError()));
exit(EXIT_FAILURE);
}
- window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Multithreading", NULL);
- if (!window)
+ for (i = 0; i < count; i++)
{
- fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError()));
- exit(EXIT_FAILURE);
+ threads[i].window = glfwCreateWindow(200, 200,
+ GLFW_WINDOWED,
+ threads[i].title,
+ NULL);
+ if (!threads[i].window)
+ {
+ fprintf(stderr, "Failed to open GLFW window: %s\n",
+ glfwErrorString(glfwGetError()));
+ exit(EXIT_FAILURE);
+ }
+
+ glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
+
+ if (thrd_create(&threads[i].ID, thread_start, threads + i) !=
+ thrd_success)
+ {
+ fprintf(stderr, "Failed to create secondary thread\n");
+ exit(EXIT_FAILURE);
+ }
}
- if (thrd_create(&thread, thread_start, window) != thrd_success)
+ while (running)
{
- fprintf(stderr, "Failed to create secondary thread\n");
- exit(EXIT_FAILURE);
- }
+ assert(glfwGetCurrentContext() == NULL);
- while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED))
glfwWaitEvents();
- running = GL_FALSE;
- thrd_join(thread, &result);
+ for (i = 0; i < count; i++)
+ {
+ if (glfwGetWindowParam(threads[i].window, GLFW_CLOSE_REQUESTED))
+ running = GL_FALSE;
+ }
+ }
+
+ for (i = 0; i < count; i++)
+ thrd_join(threads[i].ID, &result);
exit(EXIT_SUCCESS);
}
From 2e789e17e698d5e8cda99a7554c0c9de59dc23b2 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Mon, 13 Aug 2012 19:52:49 +0200
Subject: [PATCH 16/50] Made threads test a GUI program.
---
tests/CMakeLists.txt | 16 +++++++++-------
1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e2d2a825f..80a7b82f7 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -29,11 +29,6 @@ add_executable(joysticks joysticks.c)
add_executable(modes modes.c ${GETOPT})
add_executable(peter peter.c)
add_executable(reopen reopen.c)
-add_executable(threads threads.c ${TINYCTHREAD})
-
-if (BUILD_SHARED_LIBS)
- target_link_libraries(threads ${CMAKE_THREAD_LIBS_INIT})
-endif()
add_executable(accuracy WIN32 MACOSX_BUNDLE accuracy.c)
set_target_properties(accuracy PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Accuracy")
@@ -44,15 +39,22 @@ set_target_properties(sharing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Sharing")
add_executable(tearing WIN32 MACOSX_BUNDLE tearing.c)
set_target_properties(tearing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Tearing")
+add_executable(threads WIN32 MACOSX_BUNDLE threads.c ${TINYCTHREAD})
+set_target_properties(threads PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Threads")
+
add_executable(title WIN32 MACOSX_BUNDLE title.c)
set_target_properties(title PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Title")
add_executable(windows WIN32 MACOSX_BUNDLE windows.c)
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
-set(WINDOWS_BINARIES accuracy sharing tearing title windows)
+if (BUILD_SHARED_LIBS)
+ target_link_libraries(threads ${CMAKE_THREAD_LIBS_INIT})
+endif()
+
+set(WINDOWS_BINARIES accuracy sharing tearing threads title windows)
set(CONSOLE_BINARIES clipboard defaults events fsaa fsfocus gamma glfwinfo
- iconify joysticks modes peter reopen threads)
+ iconify joysticks modes peter reopen)
if (MSVC)
# Tell MSVC to use main instead of WinMain for Windows subsystem executables
From 12e00876d780ada3eeea476d8b575de1984e38d5 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Wed, 15 Aug 2012 20:26:09 +0200
Subject: [PATCH 17/50] Formatting.
---
tests/threads.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tests/threads.c b/tests/threads.c
index 6e3a6eaf9..35c837165 100644
--- a/tests/threads.c
+++ b/tests/threads.c
@@ -42,12 +42,12 @@ typedef struct
GLFWwindow window;
const char* title;
float r, g, b;
- thrd_t ID;
+ thrd_t id;
} Thread;
static volatile GLboolean running = GL_TRUE;
-static int thread_start(void* data)
+static int thread_main(void* data)
{
const Thread* thread = (const Thread*) data;
@@ -102,7 +102,7 @@ int main(void)
glfwSetWindowPos(threads[i].window, 200 + 250 * i, 200);
- if (thrd_create(&threads[i].ID, thread_start, threads + i) !=
+ if (thrd_create(&threads[i].id, thread_main, threads + i) !=
thrd_success)
{
fprintf(stderr, "Failed to create secondary thread\n");
@@ -124,7 +124,7 @@ int main(void)
}
for (i = 0; i < count; i++)
- thrd_join(threads[i].ID, &result);
+ thrd_join(threads[i].id, &result);
exit(EXIT_SUCCESS);
}
From 596132c3a1becceb0ba6d10991d52a85ba8f201c Mon Sep 17 00:00:00 2001
From: Riku Salminen
Date: Tue, 21 Aug 2012 21:01:57 +0300
Subject: [PATCH 18/50] Add glfwShowWindow, glfwHideWindow
Add glfwShowWindow and glfwHideWindow functions to allow explicit
control over show/hide window.
Remove platform specific show window code from _glfwPlatformCreateWindow
but call glfwShowWindow from glfwCreateWindow to avoid breaking things
(for now).
---
include/GL/glfw3.h | 2 +
src/cocoa_window.m | 20 +++++++-
src/internal.h | 2 +
src/win32_window.c | 114 +++++++++------------------------------------
src/window.c | 34 ++++++++++++++
src/x11_window.c | 26 +++++++++--
6 files changed, 101 insertions(+), 97 deletions(-)
diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index 050f0c305..79b6033ab 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -540,6 +540,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow, int* xpos, int* ypos);
GLFWAPI void glfwSetWindowPos(GLFWwindow, int xpos, int ypos);
GLFWAPI void glfwIconifyWindow(GLFWwindow window);
GLFWAPI void glfwRestoreWindow(GLFWwindow window);
+GLFWAPI void glfwShowWindow(GLFWwindow window);
+GLFWAPI void glfwHideWindow(GLFWwindow window);
GLFWAPI int glfwGetWindowParam(GLFWwindow window, int param);
GLFWAPI void glfwSetWindowUserPointer(GLFWwindow window, void* pointer);
GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow window);
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index d7764f923..db6d07b82 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -906,7 +906,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
if (!createContext(window, wndconfig, fbconfig))
return GL_FALSE;
- [window->NS.object makeKeyAndOrderFront:nil];
[window->NSGL.context setView:[window->NS.object contentView]];
if (wndconfig->mode == GLFW_FULLSCREEN)
@@ -1030,6 +1029,25 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
}
+//========================================================================
+// Show window
+//========================================================================
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ [window->NS.object makeKeyAndOrderFront:nil];
+}
+
+
+//========================================================================
+// Hide window
+//========================================================================
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ [window->NS.object orderOut:nil];
+}
+
//========================================================================
// Write back window parameters into GLFW window structure
//========================================================================
diff --git a/src/internal.h b/src/internal.h
index 89ac48b25..1bad74833 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -302,6 +302,8 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height);
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y);
void _glfwPlatformIconifyWindow(_GLFWwindow* window);
void _glfwPlatformRestoreWindow(_GLFWwindow* window);
+void _glfwPlatformShowWindow(_GLFWwindow* window);
+void _glfwPlatformHideWindow(_GLFWwindow* window);
// Event management
void _glfwPlatformPollEvents(void);
diff --git a/src/win32_window.c b/src/win32_window.c
index 77b990265..ff6941ab8 100644
--- a/src/win32_window.c
+++ b/src/win32_window.c
@@ -34,95 +34,6 @@
#include
#include
-
-//========================================================================
-// Enable/disable minimize/restore animations
-//========================================================================
-
-static int setMinMaxAnimations(int enable)
-{
- ANIMATIONINFO AI;
- int old_enable;
-
- // Get old animation setting
- AI.cbSize = sizeof(ANIMATIONINFO);
- SystemParametersInfo(SPI_GETANIMATION, AI.cbSize, &AI, 0);
- old_enable = AI.iMinAnimate;
-
- // If requested, change setting
- if (old_enable != enable)
- {
- AI.iMinAnimate = enable;
- SystemParametersInfo(SPI_SETANIMATION, AI.cbSize, &AI,
- SPIF_SENDCHANGE);
- }
-
- return old_enable;
-}
-
-
-//========================================================================
-// Focus the window and bring it to the top of the stack
-// Due to some nastiness with how XP handles SetForegroundWindow we have
-// to go through some really bizarre measures to achieve this
-//========================================================================
-
-static void setForegroundWindow(HWND hWnd)
-{
- int try_count = 0;
- int old_animate;
-
- // Try the standard approach first...
- BringWindowToTop(hWnd);
- SetForegroundWindow(hWnd);
-
- // If it worked, return now
- if (hWnd == GetForegroundWindow())
- {
- // Try to modify the system settings (since this is the foreground
- // process, we are allowed to do this)
- SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID) 0,
- SPIF_SENDCHANGE);
- return;
- }
-
- // For other Windows versions than 95 & NT4.0, the standard approach
- // may not work, so if we failed we have to "trick" Windows into
- // making our window the foureground window: Iconify and restore
- // again. It is ugly, but it seems to work (we turn off those annoying
- // zoom animations to make it look a bit better at least).
-
- // Turn off minimize/restore animations
- old_animate = setMinMaxAnimations(0);
-
- // We try this a few times, just to be on the safe side of things...
- do
- {
- // Iconify & restore
- ShowWindow(hWnd, SW_HIDE);
- ShowWindow(hWnd, SW_SHOWMINIMIZED);
- ShowWindow(hWnd, SW_SHOWNORMAL);
-
- // Try to get focus
- BringWindowToTop(hWnd);
- SetForegroundWindow(hWnd);
-
- // We do not want to keep going on forever, so we keep track of
- // how many times we tried
- try_count++;
- }
- while (hWnd != GetForegroundWindow() && try_count <= 3);
-
- // Restore the system minimize/restore animation setting
- setMinMaxAnimations(old_animate);
-
- // Try to modify the system settings (since this is now hopefully the
- // foreground process, we are probably allowed to do this)
- SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT, 0, (LPVOID) 0,
- SPIF_SENDCHANGE);
-}
-
-
//========================================================================
// Hide mouse cursor
//========================================================================
@@ -1071,9 +982,6 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
SWP_NOMOVE | SWP_NOSIZE);
}
- setForegroundWindow(window->Win32.handle);
- SetFocus(window->Win32.handle);
-
return GL_TRUE;
}
@@ -1193,6 +1101,28 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
}
+//========================================================================
+// Show or hide window
+//========================================================================
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->Win32.handle, SW_SHOWNORMAL);
+ BringWindowToTop(window->Win32.handle);
+ SetForegroundWindow(window->Win32.handle);
+ SetFocus(window->Win32.handle);
+}
+
+
+//========================================================================
+// Show or hide window
+//========================================================================
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ ShowWindow(window->Win32.handle, SW_HIDE);
+}
+
//========================================================================
// Write back window parameters into GLFW window structure
//========================================================================
diff --git a/src/window.c b/src/window.c
index 4e95129a6..efaa15729 100644
--- a/src/window.c
+++ b/src/window.c
@@ -318,6 +318,8 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
return GL_FALSE;
}
+ glfwShowWindow(window, 1); // TODO: consider if this is necessary!
+
// Cache the actual (as opposed to requested) window parameters
_glfwPlatformRefreshWindowParams(window);
@@ -623,6 +625,38 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow handle)
}
+//========================================================================
+// Window show
+//========================================================================
+
+GLFWAPI void glfwShowWindow(GLFWwindow window)
+{
+ if (!_glfwInitialized)
+ {
+ _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
+ return;
+ }
+
+ _glfwPlatformShowWindow((_GLFWwindow*)window);
+}
+
+
+//========================================================================
+// Window hide
+//========================================================================
+
+GLFWAPI void glfwHideWindow(GLFWwindow window)
+{
+ if (!_glfwInitialized)
+ {
+ _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
+ return;
+ }
+
+ _glfwPlatformHideWindow((_GLFWwindow*)window);
+}
+
+
//========================================================================
// Window un-iconification
//========================================================================
diff --git a/src/x11_window.c b/src/x11_window.c
index 442e76c02..90938ccb8 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -230,10 +230,6 @@ static GLboolean createWindow(_GLFWwindow* window,
_glfwPlatformSetWindowTitle(window, wndconfig->title);
- // Make sure the window is mapped before proceeding
- XMapWindow(_glfwLibrary.X11.display, window->X11.handle);
- XFlush(_glfwLibrary.X11.display);
-
return GL_TRUE;
}
@@ -1099,6 +1095,28 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
}
+//========================================================================
+// Show window
+//========================================================================
+
+void _glfwPlatformShowWindow(_GLFWwindow* window)
+{
+ XMapRaised(_glfwLibrary.X11.display, window->X11.handle);
+ XFlush(_glfwLibrary.X11.display);
+}
+
+
+//========================================================================
+// Hide window
+//========================================================================
+
+void _glfwPlatformHideWindow(_GLFWwindow* window)
+{
+ XUnmapWindow(_glfwLibrary.X11.display, window->X11.handle);
+ XFlush(_glfwLibrary.X11.display);
+}
+
+
//========================================================================
// Read back framebuffer parameters from the context
//========================================================================
From a2ca095b869c0c8255cf678e354f44a4aac87120 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 20:28:36 +0200
Subject: [PATCH 19/50] Renamed GLFW_WINDOW_RESIZABLE to GLFW_RESIZABLE.
This matches GLFW_ACTIVE and GLFW_ICONIFIED.
---
examples/heightmap.c | 2 +-
include/GL/glfw3.h | 14 +++++++-------
readme.html | 2 +-
src/window.c | 4 ++--
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/examples/heightmap.c b/examples/heightmap.c
index fce8b8dee..5139a4932 100644
--- a/examples/heightmap.c
+++ b/examples/heightmap.c
@@ -581,7 +581,7 @@ int main(int argc, char** argv)
exit(EXIT_FAILURE);
}
- glfwWindowHint(GLFW_WINDOW_RESIZABLE, GL_FALSE);
+ glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_OPENGL_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index 79b6033ab..5472f8b16 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -405,18 +405,18 @@ extern "C" {
#define GLFW_ACCUM_ALPHA_BITS 0x0002100A
#define GLFW_AUX_BUFFERS 0x0002100B
#define GLFW_STEREO 0x0002100C
-#define GLFW_WINDOW_RESIZABLE 0x0002100D
#define GLFW_FSAA_SAMPLES 0x0002100E
/* The following constants are used with both glfwGetWindowParam
* and glfwWindowHint
*/
-#define GLFW_OPENGL_VERSION_MAJOR 0x0002100F
-#define GLFW_OPENGL_VERSION_MINOR 0x00021010
-#define GLFW_OPENGL_FORWARD_COMPAT 0x00021011
-#define GLFW_OPENGL_DEBUG_CONTEXT 0x00021012
-#define GLFW_OPENGL_PROFILE 0x00021013
-#define GLFW_OPENGL_ROBUSTNESS 0x00021014
+#define GLFW_OPENGL_VERSION_MAJOR 0x00022000
+#define GLFW_OPENGL_VERSION_MINOR 0x00022001
+#define GLFW_OPENGL_FORWARD_COMPAT 0x00022002
+#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022003
+#define GLFW_OPENGL_PROFILE 0x00022004
+#define GLFW_OPENGL_ROBUSTNESS 0x00022005
+#define GLFW_RESIZABLE 0x00022006
/* GLFW_OPENGL_ROBUSTNESS mode tokens */
#define GLFW_OPENGL_NO_ROBUSTNESS 0x00000000
diff --git a/readme.html b/readme.html
index 39d0739b7..580e21cdd 100644
--- a/readme.html
+++ b/readme.html
@@ -296,7 +296,7 @@ version of GLFW.
Renamed glfw.h to glfw3.h to avoid conflicts with 2.x series
Renamed glfwOpenWindowHint to glfwWindowHint
Renamed GLFW_WINDOW token to GLFW_WINDOWED
- Renamed GLFW_WINDOW_NO_RESIZE to GLFW_WINDOW_RESIZABLE
+ Renamed GLFW_WINDOW_NO_RESIZE to GLFW_RESIZABLE
Renamed GLFW_BUILD_DLL to _GLFW_BUILD_DLL
Renamed version test to glfwinfo
Renamed GLFW_NO_GLU to GLFW_INCLUDE_GLU and made it disabled by default
diff --git a/src/window.c b/src/window.c
index efaa15729..81b0492c6 100644
--- a/src/window.c
+++ b/src/window.c
@@ -410,7 +410,7 @@ GLFWAPI void glfwWindowHint(int target, int hint)
case GLFW_STEREO:
_glfwLibrary.hints.stereo = hint;
break;
- case GLFW_WINDOW_RESIZABLE:
+ case GLFW_RESIZABLE:
_glfwLibrary.hints.resizable = hint;
break;
case GLFW_FSAA_SAMPLES:
@@ -705,7 +705,7 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow handle, int param)
return window->closeRequested;
case GLFW_REFRESH_RATE:
return window->refreshRate;
- case GLFW_WINDOW_RESIZABLE:
+ case GLFW_RESIZABLE:
return window->resizable;
case GLFW_OPENGL_VERSION_MAJOR:
return window->glMajor;
From 3d2722dc4c638e7c3af9fea0c58a208cee1a3944 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 20:32:44 +0200
Subject: [PATCH 20/50] Fixed broken call to glfwShowWindow.
---
src/window.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/window.c b/src/window.c
index 81b0492c6..4f8a96e68 100644
--- a/src/window.c
+++ b/src/window.c
@@ -318,7 +318,7 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
return GL_FALSE;
}
- glfwShowWindow(window, 1); // TODO: consider if this is necessary!
+ glfwShowWindow(window);
// Cache the actual (as opposed to requested) window parameters
_glfwPlatformRefreshWindowParams(window);
From 8bb5c59d2d01ccc6e1247b5680e7d962fb81de80 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 21:18:09 +0200
Subject: [PATCH 21/50] Added GLFW_VISIBLE window hint and parameter.
---
include/GL/glfw3.h | 1 +
readme.html | 1 +
src/cocoa_window.m | 16 ++++++++++++++++
src/internal.h | 4 ++++
src/win32_window.c | 6 ++++++
src/window.c | 22 +++++++++++++++++++---
src/x11_window.c | 2 ++
7 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index 5472f8b16..6f5354089 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -417,6 +417,7 @@ extern "C" {
#define GLFW_OPENGL_PROFILE 0x00022004
#define GLFW_OPENGL_ROBUSTNESS 0x00022005
#define GLFW_RESIZABLE 0x00022006
+#define GLFW_VISIBLE 0x00022007
/* GLFW_OPENGL_ROBUSTNESS mode tokens */
#define GLFW_OPENGL_NO_ROBUSTNESS 0x00000000
diff --git a/readme.html b/readme.html
index 580e21cdd..c6eedbf3a 100644
--- a/readme.html
+++ b/readme.html
@@ -283,6 +283,7 @@ version of GLFW.
Added GLFW_OPENGL_ROBUSTNESS window hint and associated strategy tokens for GL_ARB_robustness support
Added GLFW_OPENGL_REVISION window parameter to make up for removal of glfwGetGLVersion
Added GLFW_INCLUDE_GL3 macro for telling the GLFW header to include gl3.h header instead of gl.h
+ Added GLFW_VISIBLE window hint and parameter for controlling and polling window visibility
Added windows simple multi-window test program
Added sharing simple OpenGL object sharing test program
Added modes video mode enumeration and setting test program
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index db6d07b82..0d62b0fa4 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -131,6 +131,22 @@
return NSTerminateCancel;
}
+- (void)applicationDidHide:(NSNotification *)notification
+{
+ _GLFWwindow* window;
+
+ for (window = _glfwLibrary.windowListHead; window; window = window->next)
+ _glfwInputWindowVisibility(window, GL_FALSE);
+}
+
+- (void)applicationDidUnhide:(NSNotification *)notification
+{
+ _GLFWwindow* window;
+
+ for (window = _glfwLibrary.windowListHead; window; window = window->next)
+ _glfwInputWindowVisibility(window, GL_TRUE);
+}
+
@end
diff --git a/src/internal.h b/src/internal.h
index 1bad74833..8e923d50d 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -109,6 +109,7 @@ struct _GLFWhints
int auxBuffers;
GLboolean stereo;
GLboolean resizable;
+ GLboolean visible;
int samples;
int glMajor;
int glMinor;
@@ -131,6 +132,7 @@ struct _GLFWwndconfig
const char* title;
int refreshRate;
GLboolean resizable;
+ GLboolean visible;
int glMajor;
int glMinor;
GLboolean glForward;
@@ -181,6 +183,7 @@ struct _GLFWwindow
int positionX, positionY;
int mode; // GLFW_WINDOW or GLFW_FULLSCREEN
GLboolean resizable; // GL_TRUE if user may resize this window
+ GLboolean visible; // GL_TRUE if this window is visible
int refreshRate; // monitor refresh rate
void* userPointer;
@@ -338,6 +341,7 @@ void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean activated);
void _glfwInputWindowPos(_GLFWwindow* window, int x, int y);
void _glfwInputWindowSize(_GLFWwindow* window, int width, int height);
void _glfwInputWindowIconify(_GLFWwindow* window, int iconified);
+void _glfwInputWindowVisibility(_GLFWwindow* window, int visible);
void _glfwInputWindowDamage(_GLFWwindow* window);
void _glfwInputWindowCloseRequest(_GLFWwindow* window);
diff --git a/src/win32_window.c b/src/win32_window.c
index ff6941ab8..b83d504a6 100644
--- a/src/win32_window.c
+++ b/src/win32_window.c
@@ -418,6 +418,12 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
return 0;
}
+ case WM_SHOWWINDOW:
+ {
+ _glfwInputWindowVisibility(window, wParam ? GL_TRUE : GL_FALSE);
+ break;
+ }
+
case WM_SYSCOMMAND:
{
switch (wParam & 0xfff0)
diff --git a/src/window.c b/src/window.c
index 4f8a96e68..7e928cf26 100644
--- a/src/window.c
+++ b/src/window.c
@@ -82,8 +82,9 @@ void _glfwSetDefaultWindowHints(void)
_glfwLibrary.hints.glMajor = 1;
_glfwLibrary.hints.glMinor = 0;
- // The default is to allow window resizing
+ // The default is to show the window and allow window resizing
_glfwLibrary.hints.resizable = GL_TRUE;
+ _glfwLibrary.hints.visible = GL_TRUE;
}
@@ -176,6 +177,16 @@ void _glfwInputWindowIconify(_GLFWwindow* window, int iconified)
}
+//========================================================================
+// Register window visibility events
+//========================================================================
+
+void _glfwInputWindowVisibility(_GLFWwindow* window, int visible)
+{
+ window->visible = visible;
+}
+
+
//========================================================================
// Register window damage events
//========================================================================
@@ -246,6 +257,7 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
wndconfig.title = title;
wndconfig.refreshRate = Max(_glfwLibrary.hints.refreshRate, 0);
wndconfig.resizable = _glfwLibrary.hints.resizable ? GL_TRUE : GL_FALSE;
+ wndconfig.visible = _glfwLibrary.hints.visible ? GL_TRUE : GL_FALSE;
wndconfig.glMajor = _glfwLibrary.hints.glMajor;
wndconfig.glMinor = _glfwLibrary.hints.glMinor;
wndconfig.glForward = _glfwLibrary.hints.glForward ? GL_TRUE : GL_FALSE;
@@ -318,8 +330,6 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
return GL_FALSE;
}
- glfwShowWindow(window);
-
// Cache the actual (as opposed to requested) window parameters
_glfwPlatformRefreshWindowParams(window);
@@ -353,6 +363,9 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
glClear(GL_COLOR_BUFFER_BIT);
_glfwPlatformSwapBuffers(window);
+ if (wndconfig.visible)
+ glfwShowWindow(window);
+
return window;
}
@@ -413,6 +426,9 @@ GLFWAPI void glfwWindowHint(int target, int hint)
case GLFW_RESIZABLE:
_glfwLibrary.hints.resizable = hint;
break;
+ case GLFW_VISIBLE:
+ _glfwLibrary.hints.visible = hint;
+ break;
case GLFW_FSAA_SAMPLES:
_glfwLibrary.hints.samples = hint;
break;
diff --git a/src/x11_window.c b/src/x11_window.c
index 90938ccb8..b4d62605d 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -736,6 +736,7 @@ static void processSingleEvent(void)
return;
}
+ _glfwInputWindowVisibility(window, GL_TRUE);
_glfwInputWindowIconify(window, GL_FALSE);
break;
}
@@ -750,6 +751,7 @@ static void processSingleEvent(void)
return;
}
+ _glfwInputWindowVisibility(window, GL_FALSE);
_glfwInputWindowIconify(window, GL_TRUE);
break;
}
From 85576bcb453762008f9c2e609ec310f3a3f85ebd Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 21:19:30 +0200
Subject: [PATCH 22/50] Added credit.
---
readme.html | 3 +++
1 file changed, 3 insertions(+)
diff --git a/readme.html b/readme.html
index c6eedbf3a..dd80672ef 100644
--- a/readme.html
+++ b/readme.html
@@ -926,6 +926,9 @@ their skills. Special thanks go out to:
Arturo J. Pérez, for a bug fix for cursor tracking on Mac OS X 10.6 Snow
Leopard
+ Riku Salminen, for the initial implementation of
+ glfwShowWindow and glfwHideWindow
+
Douglas C. Schmidt and Irfan Pyarali, for their excellent article
Strategies for Implementing POSIX Condition Variables on Win32
From b665903e14df43f9ca0b9fa8835cabfc022b3bd4 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 21:19:33 +0200
Subject: [PATCH 23/50] Added testing of glfwShowWindow and GLFW_VISIBLE.
---
tests/windows.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/windows.c b/tests/windows.c
index 894febeb0..f4c74bfdc 100644
--- a/tests/windows.c
+++ b/tests/windows.c
@@ -55,6 +55,8 @@ int main(void)
for (i = 0; i < 4; i++)
{
+ glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
+
windows[i] = glfwCreateWindow(200, 200, GLFW_WINDOWED, titles[i], NULL);
if (!windows[i])
{
@@ -71,6 +73,7 @@ int main(void)
0.f);
glfwSetWindowPos(windows[i], 100 + (i & 1) * 300, 100 + (i >> 1) * 300);
+ glfwShowWindow(windows[i]);
}
while (running)
From 0e63488b407f4f2f1d3ae99ea7b366fa647bcdec Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 21:35:42 +0200
Subject: [PATCH 24/50] Cocoa window visibility fixes.
---
src/cocoa_window.m | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index 0d62b0fa4..35bdd9740 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -144,7 +144,10 @@
_GLFWwindow* window;
for (window = _glfwLibrary.windowListHead; window; window = window->next)
- _glfwInputWindowVisibility(window, GL_TRUE);
+ {
+ if ([window->NS.object isVisible])
+ _glfwInputWindowVisibility(window, GL_TRUE);
+ }
}
@end
@@ -1052,6 +1055,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
void _glfwPlatformShowWindow(_GLFWwindow* window)
{
[window->NS.object makeKeyAndOrderFront:nil];
+ _glfwInputWindowVisibility(window, GL_TRUE);
}
@@ -1062,6 +1066,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window)
void _glfwPlatformHideWindow(_GLFWwindow* window)
{
[window->NS.object orderOut:nil];
+ _glfwInputWindowVisibility(window, GL_FALSE);
}
//========================================================================
From f6a1bbf782a0fd3e6e460997c3cea529bb85868f Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 21 Aug 2012 21:57:13 +0200
Subject: [PATCH 25/50] Added GLFW_VISIBLE to glfwWindowParam.
---
src/window.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/window.c b/src/window.c
index 7e928cf26..2507dd5c0 100644
--- a/src/window.c
+++ b/src/window.c
@@ -723,6 +723,8 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow handle, int param)
return window->refreshRate;
case GLFW_RESIZABLE:
return window->resizable;
+ case GLFW_VISIBLE:
+ return window->visible;
case GLFW_OPENGL_VERSION_MAJOR:
return window->glMajor;
case GLFW_OPENGL_VERSION_MINOR:
From f5bfe41456d6f4bfbe4c1ac4c5eb0ef23cc545c7 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 28 Aug 2012 17:52:22 +0200
Subject: [PATCH 26/50] Moved GLFW_VISIBLE hint use to glfwinfo.
---
tests/glfwinfo.c | 2 ++
tests/windows.c | 3 ---
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c
index 90fd329ff..0019bf664 100644
--- a/tests/glfwinfo.c
+++ b/tests/glfwinfo.c
@@ -207,6 +207,8 @@ int main(int argc, char** argv)
if (strategy)
glfwWindowHint(GLFW_OPENGL_ROBUSTNESS, strategy);
+ glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
+
// We assume here that we stand a better chance of success by leaving all
// possible details of pixel format selection to GLFW
diff --git a/tests/windows.c b/tests/windows.c
index f4c74bfdc..894febeb0 100644
--- a/tests/windows.c
+++ b/tests/windows.c
@@ -55,8 +55,6 @@ int main(void)
for (i = 0; i < 4; i++)
{
- glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
-
windows[i] = glfwCreateWindow(200, 200, GLFW_WINDOWED, titles[i], NULL);
if (!windows[i])
{
@@ -73,7 +71,6 @@ int main(void)
0.f);
glfwSetWindowPos(windows[i], 100 + (i & 1) * 300, 100 + (i >> 1) * 300);
- glfwShowWindow(windows[i]);
}
while (running)
From d5ede068593638647eae61ce3984f20403927bb5 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 28 Aug 2012 21:37:07 +0200
Subject: [PATCH 27/50] Removed WS_VISIBLE from creation flags.
---
src/win32_window.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/win32_window.c b/src/win32_window.c
index 5a74955ef..13096073a 100644
--- a/src/win32_window.c
+++ b/src/win32_window.c
@@ -753,7 +753,7 @@ static int createWindow(_GLFWwindow* window,
WCHAR* wideTitle;
// Set common window styles
- dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
+ dwStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
dwExStyle = WS_EX_APPWINDOW;
// Set window style, depending on fullscreen mode
From 52c27113d3de0f02f130267bd1822403f959f028 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 2 Sep 2012 15:21:40 +0200
Subject: [PATCH 28/50] Shortened PC boolean name.
---
src/win32_platform.h | 2 +-
src/win32_time.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/win32_platform.h b/src/win32_platform.h
index 79bbbb94b..ba10039ef 100644
--- a/src/win32_platform.h
+++ b/src/win32_platform.h
@@ -191,7 +191,7 @@ typedef struct _GLFWlibraryWin32
// Timer data
struct {
- GLboolean hasPerformanceCounter;
+ GLboolean hasPC;
double resolution;
unsigned int t0_32;
__int64 t0_64;
diff --git a/src/win32_time.c b/src/win32_time.c
index 1e1d57f4d..96f7b454a 100644
--- a/src/win32_time.c
+++ b/src/win32_time.c
@@ -45,13 +45,13 @@ void _glfwInitTimer(void)
if (QueryPerformanceFrequency((LARGE_INTEGER*) &freq))
{
- _glfwLibrary.Win32.timer.hasPerformanceCounter = GL_TRUE;
+ _glfwLibrary.Win32.timer.hasPC = GL_TRUE;
_glfwLibrary.Win32.timer.resolution = 1.0 / (double) freq;
QueryPerformanceCounter((LARGE_INTEGER*) &_glfwLibrary.Win32.timer.t0_64);
}
else
{
- _glfwLibrary.Win32.timer.hasPerformanceCounter = GL_FALSE;
+ _glfwLibrary.Win32.timer.hasPC = GL_FALSE;
_glfwLibrary.Win32.timer.resolution = 0.001; // winmm resolution is 1 ms
_glfwLibrary.Win32.timer.t0_32 = _glfw_timeGetTime();
}
@@ -71,7 +71,7 @@ double _glfwPlatformGetTime(void)
double t;
__int64 t_64;
- if (_glfwLibrary.Win32.timer.hasPerformanceCounter)
+ if (_glfwLibrary.Win32.timer.hasPC)
{
QueryPerformanceCounter((LARGE_INTEGER*) &t_64);
t = (double)(t_64 - _glfwLibrary.Win32.timer.t0_64);
@@ -91,7 +91,7 @@ void _glfwPlatformSetTime(double t)
{
__int64 t_64;
- if (_glfwLibrary.Win32.timer.hasPerformanceCounter)
+ if (_glfwLibrary.Win32.timer.hasPC)
{
QueryPerformanceCounter((LARGE_INTEGER*) &t_64);
_glfwLibrary.Win32.timer.t0_64 = t_64 - (__int64) (t / _glfwLibrary.Win32.timer.resolution);
From a339098bc01b246d67ad165bcd2380ce51d666db Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 2 Sep 2012 15:22:56 +0200
Subject: [PATCH 29/50] Formatting.
---
include/GL/glfw3.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h
index 45f443398..1e90a5bce 100644
--- a/include/GL/glfw3.h
+++ b/include/GL/glfw3.h
@@ -527,11 +527,11 @@ GLFWAPI void glfwSetGammaRamp(const GLFWgammaramp* ramp);
GLFWAPI void glfwWindowHint(int target, int hint);
GLFWAPI GLFWwindow glfwCreateWindow(int width, int height, int mode, const char* title, GLFWwindow share);
GLFWAPI void glfwDestroyWindow(GLFWwindow window);
-GLFWAPI void glfwSetWindowTitle(GLFWwindow, const char* title);
-GLFWAPI void glfwGetWindowSize(GLFWwindow, int* width, int* height);
-GLFWAPI void glfwSetWindowSize(GLFWwindow, int width, int height);
-GLFWAPI void glfwGetWindowPos(GLFWwindow, int* xpos, int* ypos);
-GLFWAPI void glfwSetWindowPos(GLFWwindow, int xpos, int ypos);
+GLFWAPI void glfwSetWindowTitle(GLFWwindow window, const char* title);
+GLFWAPI void glfwGetWindowSize(GLFWwindow window, int* width, int* height);
+GLFWAPI void glfwSetWindowSize(GLFWwindow window, int width, int height);
+GLFWAPI void glfwGetWindowPos(GLFWwindow window, int* xpos, int* ypos);
+GLFWAPI void glfwSetWindowPos(GLFWwindow window, int xpos, int ypos);
GLFWAPI void glfwIconifyWindow(GLFWwindow window);
GLFWAPI void glfwRestoreWindow(GLFWwindow window);
GLFWAPI int glfwGetWindowParam(GLFWwindow window, int param);
From c03659e9c39f492f3cb876a1035331f4147e9803 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Thu, 6 Sep 2012 21:42:42 +0200
Subject: [PATCH 30/50] Updated change log and credit.
---
readme.html | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/readme.html b/readme.html
index d330d1c1c..5431eb9eb 100644
--- a/readme.html
+++ b/readme.html
@@ -286,6 +286,7 @@ version of GLFW.
Added windows simple multi-window test program
Added sharing simple OpenGL object sharing test program
Added modes video mode enumeration and setting test program
+ Added threads simple multi-threaded rendering test program
Added glfw3native.h header and platform-specific functions for explicit access to native display, window and context handles
Added glfwSetGamma, glfwSetGammaRamp and glfwGetGammaRamp functions and GLFWgammaramp type for monitor gamma ramp control
Added window parameter to glfwSwapBuffers
@@ -926,6 +927,9 @@ their skills. Special thanks go out to:
Arturo J. Pérez, for a bug fix for cursor tracking on Mac OS X 10.6 Snow
Leopard
+ Riku Salminen, for making the X11 event processing able to support
+ multi-threaded rendering
+
Douglas C. Schmidt and Irfan Pyarali, for their excellent article
Strategies for Implementing POSIX Condition Variables on Win32
From ea7ab3e01b6ba2a518de314bf378595a4d951d53 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Thu, 6 Sep 2012 23:02:33 +0200
Subject: [PATCH 31/50] Fixed broken selector signature.
---
src/cocoa_window.m | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index 5129a21fb..43576ab08 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -686,7 +686,7 @@ static GLboolean createWindow(_GLFWwindow* window,
[window->NS.object setAcceptsMouseMovedEvents:YES];
[window->NS.object center];
- if ([window->NS.object respondsToSelector:@selector(setRestorable)])
+ if ([window->NS.object respondsToSelector:@selector(setRestorable:)])
[window->NS.object setRestorable:NO];
return GL_TRUE;
From 1653541aca355917bb1b4c22c2b84278f4e80746 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Thu, 6 Sep 2012 23:03:54 +0200
Subject: [PATCH 32/50] Formatting.
---
src/cocoa_window.m | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/cocoa_window.m b/src/cocoa_window.m
index 43576ab08..14f1856c8 100644
--- a/src/cocoa_window.m
+++ b/src/cocoa_window.m
@@ -1093,7 +1093,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y)
CGPoint mainScreenOrigin = CGDisplayBounds(CGMainDisplayID()).origin;
double mainScreenHeight = CGDisplayBounds(CGMainDisplayID()).size.height;
CGPoint targetPoint = CGPointMake(globalPoint.x - mainScreenOrigin.x,
- mainScreenHeight - globalPoint.y -
+ mainScreenHeight - globalPoint.y -
mainScreenOrigin.y);
CGDisplayMoveCursorToPoint(CGMainDisplayID(), targetPoint);
}
From 8f82e02a51c7049cd6246f995dcf28c8d39ce3b2 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Thu, 6 Sep 2012 23:05:19 +0200
Subject: [PATCH 33/50] Updated credit.
---
readme.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/readme.html b/readme.html
index 5431eb9eb..497546cdf 100644
--- a/readme.html
+++ b/readme.html
@@ -907,7 +907,7 @@ their skills. Special thanks go out to:
language
Shane Liesegang, for providing a bug fix relating to Cocoa window
- restoration
+ restoration and reporting a bug on 32-bit Cocoa builds
Tristam MacDonald, for his bug reports and feedback on the Cocoa port
From 8a948753df943a162dd2ef78a33d42ca644ef466 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Thu, 6 Sep 2012 23:55:23 +0200
Subject: [PATCH 34/50] Added printing of debug context window parameter.
---
tests/glfwinfo.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c
index 52d6e0dea..9d5624000 100644
--- a/tests/glfwinfo.c
+++ b/tests/glfwinfo.c
@@ -288,6 +288,9 @@ int main(int argc, char** argv)
get_glfw_profile_name(glfwGetWindowParam(window, GLFW_OPENGL_PROFILE)));
}
+ printf("OpenGL context debug flag saved by GLFW: %s\n",
+ glfwGetWindowParam(window, GLFW_OPENGL_DEBUG_CONTEXT) ? "true" : "false");
+
printf("OpenGL context renderer string: \"%s\"\n", glGetString(GL_RENDERER));
printf("OpenGL context vendor string: \"%s\"\n", glGetString(GL_VENDOR));
From 755c2a364b2b6521011aa2a544aa204809b3e154 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Thu, 6 Sep 2012 23:57:36 +0200
Subject: [PATCH 35/50] Updated .gitignore.
---
.gitignore | 19 ++++++++++---------
1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/.gitignore b/.gitignore
index 0496a03c8..da61d802c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,13 +6,13 @@ cmake_uninstall.cmake
.DS_Store
docs/Doxyfile
src/config.h
-src/libglfw.pc
-src/libglfw.so
-src/libglfw.a
-src/libglfw.dylib
-src/glfw.lib
-src/glfw.dll
-src/glfwdll.lib
+src/glfw3.pc
+src/libglfw3.so
+src/libglfw3.a
+src/libglfw3.dylib
+src/glfw3.lib
+src/glfw3.dll
+src/glfw3dll.lib
examples/boing
examples/gears
examples/heightmap
@@ -22,8 +22,8 @@ examples/wave
examples/*.app
examples/*.exe
tests/accuracy
+tests/clipboard
tests/defaults
-tests/dynamic
tests/events
tests/fsaa
tests/fsfocus
@@ -31,11 +31,12 @@ tests/gamma
tests/glfwinfo
tests/iconify
tests/joysticks
-tests/listmodes
+tests/modes
tests/peter
tests/reopen
tests/sharing
tests/tearing
+tests/threads
tests/title
tests/windows
tests/*.app
From 8cf093a19dbae45b12d832aa542790773b34b04f Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Fri, 7 Sep 2012 01:01:17 +0200
Subject: [PATCH 36/50] Linux joystick fixes.
---
src/x11_joystick.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/x11_joystick.c b/src/x11_joystick.c
index a5700c68e..1895dc6aa 100644
--- a/src/x11_joystick.c
+++ b/src/x11_joystick.c
@@ -53,7 +53,7 @@ static int openJoystickDevice(int joy, const char* path)
char numAxes, numButtons;
int fd, version;
- fd = open(path, O_NONBLOCK);
+ fd = open(path, O_RDONLY | O_NONBLOCK);
if (fd == -1)
return GL_FALSE;
@@ -127,7 +127,7 @@ static void pollJoystickEvents(void)
if (errno == ENODEV)
_glfwLibrary.X11.joystick[i].present = GL_FALSE;
- if (result < sizeof(e))
+ if (result == -1)
break;
// We don't care if it's an init event or not
From e70ced5e05009b858956f6b04f62d1dc29f903d4 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Fri, 7 Sep 2012 02:15:54 +0200
Subject: [PATCH 37/50] Fixed bad editing in Cocoa joystick code.
---
readme.html | 2 ++
src/cocoa_joystick.m | 8 ++++----
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/readme.html b/readme.html
index 497546cdf..314c392ae 100644
--- a/readme.html
+++ b/readme.html
@@ -924,6 +924,8 @@ their skills. Special thanks go out to:
Much of the Windows code of GLFW was originally based on Jeff's
code
+ Julian Møller, for reporting a bug in the Cocoa joystick code
+
Arturo J. Pérez, for a bug fix for cursor tracking on Mac OS X 10.6 Snow
Leopard
diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m
index 7eac7f91b..04c9e9728 100644
--- a/src/cocoa_joystick.m
+++ b/src/cocoa_joystick.m
@@ -550,15 +550,15 @@ int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes)
for (i = 0; i < numaxes; i++)
{
- _glfwJoystickElement* axes =
+ _glfwJoystickElement* elements =
(_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick.axes, i);
- long readScale = axes->maxReport - axes->minReport;
+ long readScale = elements->maxReport - elements->minReport;
if (readScale == 0)
- axes[i] = axes->value;
+ axes[i] = elements->value;
else
- axes[i] = (2.0f * (axes->value - axes->minReport) / readScale) - 1.0f;
+ axes[i] = (2.0f * (elements->value - elements->minReport) / readScale) - 1.0f;
if (i & 1)
axes[i] = -axes[i];
From 4cb569b5b38dadfadfe503e7db33e852ab95165d Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Fri, 7 Sep 2012 15:27:41 +0200
Subject: [PATCH 38/50] Replaced guessing with dirent and regex.
---
src/x11_init.c | 3 ++-
src/x11_joystick.c | 49 ++++++++++++++++++++++++++++++++++------------
src/x11_platform.h | 2 +-
3 files changed, 39 insertions(+), 15 deletions(-)
diff --git a/src/x11_init.c b/src/x11_init.c
index a5277c09e..32719cbfd 100644
--- a/src/x11_init.c
+++ b/src/x11_init.c
@@ -648,7 +648,8 @@ int _glfwPlatformInit(void)
_glfwLibrary.X11.cursor = createNULLCursor();
- _glfwInitJoysticks();
+ if (!_glfwInitJoysticks())
+ return GL_FALSE;
// Start the timer
_glfwInitTimer();
diff --git a/src/x11_joystick.c b/src/x11_joystick.c
index 1895dc6aa..a383fa02d 100644
--- a/src/x11_joystick.c
+++ b/src/x11_joystick.c
@@ -37,7 +37,8 @@
#include
#include
#include
-
+#include
+#include
#include
#include
#endif // _GLFW_USE_LINUX_JOYSTICKS
@@ -171,30 +172,52 @@ static void pollJoystickEvents(void)
// Initialize joystick interface
//========================================================================
-void _glfwInitJoysticks(void)
+int _glfwInitJoysticks(void)
{
#ifdef _GLFW_USE_LINUX_JOYSTICKS
- int i, j, joy = 0;
- char path[20];
- const char* bases[] =
+ int i, joy = 0;
+ regex_t regex;
+ DIR* dir;
+ const char* directories[] =
{
- "/dev/input/js",
- "/dev/js"
+ "/dev/input",
+ "/dev"
};
- for (i = 0; i < sizeof(bases) / sizeof(bases[0]); i++)
+ if (regcomp(®ex, "^js[0-9]\\+$", 0) != 0)
{
- for (j = 0; j < 50; j++)
- {
- if (joy > GLFW_JOYSTICK_LAST)
- break;
+ _glfwSetError(GLFW_PLATFORM_ERROR, "X11: Failed to compile regex");
+ return GL_FALSE;
+ }
- sprintf(path, "%s%i", bases[i], j);
+ for (i = 0; i < sizeof(directories) / sizeof(directories[0]); i++)
+ {
+ struct dirent* entry;
+
+ dir = opendir(directories[i]);
+ if (!dir)
+ continue;
+
+ while ((entry = readdir(dir)))
+ {
+ char path[20];
+ regmatch_t match;
+
+ if (regexec(®ex, entry->d_name, 1, &match, 0) != 0)
+ continue;
+
+ snprintf(path, sizeof(path), "%s/%s", directories[i], entry->d_name);
if (openJoystickDevice(joy, path))
joy++;
}
+
+ closedir(dir);
}
+
+ regfree(®ex);
#endif // _GLFW_USE_LINUX_JOYSTICKS
+
+ return GL_TRUE;
}
diff --git a/src/x11_platform.h b/src/x11_platform.h
index 75beb745a..a6b576ed4 100644
--- a/src/x11_platform.h
+++ b/src/x11_platform.h
@@ -305,7 +305,7 @@ void _glfwSetVideoMode(int* width, int* height, int* rate);
void _glfwRestoreVideoMode(void);
// Joystick input
-void _glfwInitJoysticks(void);
+int _glfwInitJoysticks(void);
void _glfwTerminateJoysticks(void);
// Unicode support
From b4d0223faa6598b20e8e6da2153e38f1c8c32d43 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Fri, 7 Sep 2012 15:48:03 +0200
Subject: [PATCH 39/50] Formatting.
---
src/x11_joystick.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/x11_joystick.c b/src/x11_joystick.c
index a383fa02d..c1fb62be6 100644
--- a/src/x11_joystick.c
+++ b/src/x11_joystick.c
@@ -178,7 +178,7 @@ int _glfwInitJoysticks(void)
int i, joy = 0;
regex_t regex;
DIR* dir;
- const char* directories[] =
+ const char* dirs[] =
{
"/dev/input",
"/dev"
@@ -190,11 +190,11 @@ int _glfwInitJoysticks(void)
return GL_FALSE;
}
- for (i = 0; i < sizeof(directories) / sizeof(directories[0]); i++)
+ for (i = 0; i < sizeof(dirs) / sizeof(dirs[0]); i++)
{
struct dirent* entry;
- dir = opendir(directories[i]);
+ dir = opendir(dirs[i]);
if (!dir)
continue;
@@ -206,7 +206,7 @@ int _glfwInitJoysticks(void)
if (regexec(®ex, entry->d_name, 1, &match, 0) != 0)
continue;
- snprintf(path, sizeof(path), "%s/%s", directories[i], entry->d_name);
+ snprintf(path, sizeof(path), "%s/%s", dirs[i], entry->d_name);
if (openJoystickDevice(joy, path))
joy++;
}
From a49c61f1a7a062e989a6ba970353e0b0540a0fee Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sat, 8 Sep 2012 20:43:08 +0200
Subject: [PATCH 40/50] Updated TinyCThread.
---
support/tinycthread.c | 90 +++++++++++++++++++++----------------------
support/tinycthread.h | 89 ++++++++++++++++++++++++++++--------------
2 files changed, 106 insertions(+), 73 deletions(-)
diff --git a/support/tinycthread.c b/support/tinycthread.c
index 9bee2cb55..ced7cf3f2 100644
--- a/support/tinycthread.c
+++ b/support/tinycthread.c
@@ -21,13 +21,6 @@ freely, subject to the following restrictions:
distribution.
*/
-/* Activate some POSIX functionality (e.g. recursive mutexes) */
-#define _GNU_SOURCE
-#if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE < 500)
- #undef _XOPEN_SOURCE
- #define _XOPEN_SOURCE 500
-#endif
-
#include "tinycthread.h"
#include
@@ -99,9 +92,11 @@ int mtx_lock(mtx_t *mtx)
#endif
}
-int mtx_timedlock(mtx_t *mtx, const xtime *xt)
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts)
{
/* FIXME! */
+ (void)mtx;
+ (void)ts;
return thrd_error;
}
@@ -290,21 +285,21 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx)
#endif
}
-int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt)
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
{
#if defined(_TTHREAD_WIN32_)
- xtime now;
- DWORD delta;
- xtime_get(&now, TIME_UTC);
- delta = (xt->sec - now.sec) * 1000 +
- (xt->nsec - now.nsec + 500000) / 1000000;
- return _cnd_timedwait_win32(cond, mtx, delta);
+ struct timespec now;
+ if (clock_gettime(TIME_UTC, &now) == 0)
+ {
+ DWORD delta = (ts->tv_sec - now.tv_sec) * 1000 +
+ (ts->tv_nsec - now.tv_nsec + 500000) / 1000000;
+ return _cnd_timedwait_win32(cond, mtx, delta);
+ }
+ else
+ return thrd_error;
#else
- struct timespec ts;
int ret;
- ts.tv_sec = xt->sec;
- ts.tv_nsec = xt->nsec;
- ret = pthread_cond_timedwait(cond, mtx, &ts);
+ ret = pthread_cond_timedwait(cond, mtx, ts);
if (ret == ETIMEDOUT)
{
return thrd_timeout;
@@ -322,9 +317,9 @@ typedef struct {
/* Thread wrapper function. */
#if defined(_TTHREAD_WIN32_)
-unsigned WINAPI _thrd_wrapper_function(void * aArg)
+static unsigned WINAPI _thrd_wrapper_function(void * aArg)
#elif defined(_TTHREAD_POSIX_)
-void * _thrd_wrapper_function(void * aArg)
+static void * _thrd_wrapper_function(void * aArg)
#endif
{
thrd_start_t fun;
@@ -401,6 +396,7 @@ thrd_t thrd_current(void)
int thrd_detach(thrd_t thr)
{
/* FIXME! */
+ (void)thr;
return thrd_error;
}
@@ -460,9 +456,9 @@ int thrd_join(thrd_t thr, int *res)
return thrd_success;
}
-void thrd_sleep(const xtime *xt)
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining)
{
- xtime now;
+ struct timespec now;
#if defined(_TTHREAD_WIN32_)
DWORD delta;
#else
@@ -470,20 +466,21 @@ void thrd_sleep(const xtime *xt)
#endif
/* Get the current time */
- xtime_get(&now, TIME_UTC);
+ if (clock_gettime(TIME_UTC, &now) != 0)
+ return -2; // FIXME: Some specific error code?
#if defined(_TTHREAD_WIN32_)
/* Delta in milliseconds */
- delta = (xt->sec - now.sec) * 1000 +
- (xt->nsec - now.nsec + 500000) / 1000000;
+ delta = (time_point->tv_sec - now.tv_sec) * 1000 +
+ (time_point->tv_nsec - now.tv_nsec + 500000) / 1000000;
if (delta > 0)
{
Sleep(delta);
}
#else
/* Delta in microseconds */
- delta = (xt->sec - now.sec) * 1000000L +
- (xt->nsec - now.nsec + 500L) / 1000L;
+ delta = (time_point->tv_sec - now.tv_sec) * 1000000L +
+ (time_point->tv_nsec - now.tv_nsec + 500L) / 1000L;
/* On some systems, the usleep argument must be < 1000000 */
while (delta > 999999L)
@@ -496,6 +493,14 @@ void thrd_sleep(const xtime *xt)
usleep((useconds_t)delta);
}
#endif
+
+ /* We don't support waking up prematurely (yet) */
+ if (remaining)
+ {
+ remaining->tv_sec = 0;
+ remaining->tv_nsec = 0;
+ }
+ return 0;
}
void thrd_yield(void)
@@ -563,26 +568,21 @@ int tss_set(tss_t key, void *val)
return thrd_success;
}
-int xtime_get(xtime *xt, int base)
+#if defined(_TTHREAD_EMULATE_CLOCK_GETTIME_)
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts)
{
- if (base == TIME_UTC)
- {
#if defined(_TTHREAD_WIN32_)
- struct _timeb tb;
- _ftime(&tb);
- xt->sec = (time_t)tb.time;
- xt->nsec = 1000000 * (long)tb.millitm;
+ struct _timeb tb;
+ _ftime(&tb);
+ ts->tv_sec = (time_t)tb.time;
+ ts->tv_nsec = 1000000L * (long)tb.millitm;
#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- xt->sec = (time_t)tv.tv_sec;
- xt->nsec = 1000 * (long)tv.tv_usec;
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ ts->tv_sec = (time_t)tv.tv_sec;
+ ts->tv_nsec = 1000L * (long)tv.tv_usec;
#endif
- return base;
- }
- else
- {
- return 0;
- }
+ return 0;
}
+#endif // _TTHREAD_EMULATE_CLOCK_GETTIME_
diff --git a/support/tinycthread.h b/support/tinycthread.h
index 8069e3f36..1a9c805c2 100644
--- a/support/tinycthread.h
+++ b/support/tinycthread.h
@@ -57,6 +57,22 @@ freely, subject to the following restrictions:
#define _TTHREAD_PLATFORM_DEFINED_
#endif
+/* Activate some POSIX functionality (e.g. clock_gettime and recursive mutexes) */
+#if defined(_TTHREAD_POSIX_)
+ #undef _FEATURES_H
+ #if !defined(_GNU_SOURCE)
+ #define _GNU_SOURCE
+ #endif
+ #if !defined(_POSIX_C_SOURCE) || ((_POSIX_C_SOURCE - 0) < 199309L)
+ #undef _POSIX_C_SOURCE
+ #define _POSIX_C_SOURCE 199309L
+ #endif
+ #if !defined(_XOPEN_SOURCE) || ((_XOPEN_SOURCE - 0) < 500)
+ #undef _XOPEN_SOURCE
+ #define _XOPEN_SOURCE 500
+ #endif
+#endif
+
/* Generic includes */
#include
@@ -75,10 +91,42 @@ freely, subject to the following restrictions:
#endif
#endif
+/* Workaround for missing TIME_UTC: If time.h doesn't provide TIME_UTC,
+ it's quite likely that libc does not support it either. Hence, fall back to
+ the only other supported time specifier: CLOCK_REALTIME (and if that fails,
+ we're probably emulating clock_gettime anyway, so anything goes). */
+#ifndef TIME_UTC
+ #ifdef CLOCK_REALTIME
+ #define TIME_UTC CLOCK_REALTIME
+ #else
+ #define TIME_UTC 0
+ #endif
+#endif
+
+/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
+#if defined(_TTHREAD_WIN32_)
+#define _TTHREAD_EMULATE_CLOCK_GETTIME_
+/* Emulate struct timespec */
+struct _ttherad_timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#define timespec _ttherad_timespec
+
+/* Emulate clockid_t */
+typedef int _tthread_clockid_t;
+#define clockid_t _tthread_clockid_t
+
+/* Emulate clock_gettime */
+int _tthread_clock_gettime(clockid_t clk_id, struct timespec *ts);
+#define clock_gettime _tthread_clock_gettime
+#endif
+
+
/** TinyCThread version (major number). */
#define TINYCTHREAD_VERSION_MAJOR 1
/** TinyCThread version (minor number). */
-#define TINYCTHREAD_VERSION_MINOR 0
+#define TINYCTHREAD_VERSION_MINOR 1
/** TinyCThread version (full version). */
#define TINYCTHREAD_VERSION (TINYCTHREAD_VERSION_MAJOR * 100 + TINYCTHREAD_VERSION_MINOR)
@@ -101,7 +149,7 @@ freely, subject to the following restrictions:
* @hideinitializer
*/
-/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 or */
+/* FIXME: Check for a PROPER value of __STDC_VERSION__ to know if we have C11 */
#if !(defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) && !defined(_Thread_local)
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
#define _Thread_local __thread
@@ -126,12 +174,6 @@ freely, subject to the following restrictions:
#define mtx_try 4
#define mtx_recursive 8
-/** Time specification */
-typedef struct {
- time_t sec; /**< Seconds */
- long nsec; /**< Nanoseconds */
-} xtime;
-
/* Mutex */
#if defined(_TTHREAD_WIN32_)
typedef struct {
@@ -174,7 +216,7 @@ int mtx_lock(mtx_t *mtx);
/** NOT YET IMPLEMENTED.
*/
-int mtx_timedlock(mtx_t *mtx, const xtime *xt);
+int mtx_timedlock(mtx_t *mtx, const struct timespec *ts);
/** Try to lock the given mutex.
* The specified mutex shall support either test and return or timeout. If the
@@ -260,7 +302,7 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx);
* specified in the call was reached without acquiring the requested resource, or
* @ref thrd_error if the request could not be honored.
*/
-int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const xtime *xt);
+int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
/* Thread */
#if defined(_TTHREAD_WIN32_)
@@ -326,11 +368,16 @@ void thrd_exit(int res);
int thrd_join(thrd_t thr, int *res);
/** Put the calling thread to sleep.
-* Suspend execution of the calling thread until after the time specified by the
-* xtime object.
-* @param xt A point in time at which the thread will resume (absolute time).
+* Suspend execution of the calling thread.
+* @param time_point A point in time at which the thread will resume (absolute time).
+* @param remaining If non-NULL, this parameter will hold the remaining time until
+* time_point upon return. This will typically be zero, but if
+* the thread was woken up by a signal that is not ignored before
+* time_point was reached @c remaining will hold a positive
+* time.
+* @return 0 (zero) on successful sleep, or -1 if an interrupt occurred.
*/
-void thrd_sleep(const xtime *xt);
+int thrd_sleep(const struct timespec *time_point, struct timespec *remaining);
/** Yield execution to another thread.
* Permit other threads to run, even if the current thread would ordinarily
@@ -385,20 +432,6 @@ void *tss_get(tss_t key);
*/
int tss_set(tss_t key, void *val);
-/* Timing */
-enum
-{
- TIME_UTC = 1
-};
-
-/** Get the current time.
-* Set the xtime object to hold the current time based on the given time base.
-* @param xt Will be filled out with the current time.
-* @param base Time base (must be @c TIME_UTC).
-* @return The non-zero value @c base if the function is successful, otherwise
-* it returns zero.
-*/
-int xtime_get(xtime *xt, int base);
#endif /* _TINYTHREAD_H_ */
From bd70e5335207fc45e56f045f843d86bdd32601f3 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sat, 8 Sep 2012 21:08:39 +0200
Subject: [PATCH 41/50] Added missing flags for size hints.
---
readme.html | 1 +
src/x11_window.c | 13 ++++++-------
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/readme.html b/readme.html
index 314c392ae..31e9217e2 100644
--- a/readme.html
+++ b/readme.html
@@ -349,6 +349,7 @@ version of GLFW.
[X11] Bugfix: Some window properties required by the ICCCM were not set
[X11] Bugfix: Calling glXCreateContextAttribsARB with an unavailable OpenGL version caused the application to terminate with a BadMatch Xlib error
[X11] Bugfix: A synchronization point necessary for jitter-free locked cursor mode was incorrectly removed
+ [X11] Bugfix: The window size hints were not updated when calling glfwSetWindowSize on a non-resizable window
[Win32] Changed port to use Unicode mode only
[Win32] Removed explicit support for versions of Windows older than Windows XP
[Win32] Bugfix: Window activation and iconification did not work as expected
diff --git a/src/x11_window.c b/src/x11_window.c
index f219275cc..cbc28dd03 100644
--- a/src/x11_window.c
+++ b/src/x11_window.c
@@ -956,7 +956,6 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
int mode = 0, rate, sizeChanged = GL_FALSE;
- XSizeHints* sizehints;
rate = window->refreshRate;
@@ -970,14 +969,14 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
{
// Update window size restrictions to match new window size
- sizehints = XAllocSizeHints();
- sizehints->flags = 0;
+ XSizeHints* hints = XAllocSizeHints();
- sizehints->min_width = sizehints->max_width = width;
- sizehints->min_height = sizehints->max_height = height;
+ hints->flags |= (PMinSize | PMaxSize);
+ hints->min_width = hints->max_width = width;
+ hints->min_height = hints->max_height = height;
- XSetWMNormalHints(_glfwLibrary.X11.display, window->X11.handle, sizehints);
- XFree(sizehints);
+ XSetWMNormalHints(_glfwLibrary.X11.display, window->X11.handle, hints);
+ XFree(hints);
}
// Change window size before changing fullscreen mode?
From 2b946289d8922da768b317c3d9ff35e60a17b21d Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 9 Sep 2012 01:31:23 +0200
Subject: [PATCH 42/50] Added direct dependency on librt for threads test on
X11.
---
tests/CMakeLists.txt | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 80a7b82f7..11bcfe9ec 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -8,6 +8,11 @@ else()
link_libraries(${glfw_LIBRARIES})
endif()
+list(APPEND thread_LIBRARIES ${CMAKE_THREAD_LIBS_INIT})
+if (UNIX AND NOT APPLE)
+ list(APPEND thread_LIBRARIES ${RT_LIBRARY})
+endif()
+
include_directories(${GLFW_SOURCE_DIR}/include
${GLFW_SOURCE_DIR}/support
${OPENGL_INCLUDE_DIR})
@@ -49,7 +54,7 @@ add_executable(windows WIN32 MACOSX_BUNDLE windows.c)
set_target_properties(windows PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Windows")
if (BUILD_SHARED_LIBS)
- target_link_libraries(threads ${CMAKE_THREAD_LIBS_INIT})
+ target_link_libraries(threads ${thread_LIBRARIES})
endif()
set(WINDOWS_BINARIES accuracy sharing tearing threads title windows)
From 50d68c83bbbfc5fe8fdc7d26e1025ff208f40b93 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 9 Sep 2012 13:56:57 +0200
Subject: [PATCH 43/50] Fixed TinyCThread declaring timespec on OS X.
---
support/tinycthread.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/support/tinycthread.h b/support/tinycthread.h
index 1a9c805c2..18451ef91 100644
--- a/support/tinycthread.h
+++ b/support/tinycthread.h
@@ -104,14 +104,16 @@ freely, subject to the following restrictions:
#endif
/* Workaround for missing clock_gettime (most Windows compilers, afaik) */
-#if defined(_TTHREAD_WIN32_)
+#if defined(_TTHREAD_WIN32_) || defined(__APPLE_CC__)
#define _TTHREAD_EMULATE_CLOCK_GETTIME_
/* Emulate struct timespec */
+#if defined(_TTHREAD_WIN32_)
struct _ttherad_timespec {
time_t tv_sec;
long tv_nsec;
};
#define timespec _ttherad_timespec
+#endif
/* Emulate clockid_t */
typedef int _tthread_clockid_t;
From feef05f839e67e86a08095f476805b389899a84a Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Sun, 9 Sep 2012 14:22:14 +0200
Subject: [PATCH 44/50] Removed superfluous inclusion.
---
src/fullscreen.c | 6 ++----
src/window.c | 6 ++----
2 files changed, 4 insertions(+), 8 deletions(-)
diff --git a/src/fullscreen.c b/src/fullscreen.c
index f632749f7..4372d153a 100644
--- a/src/fullscreen.c
+++ b/src/fullscreen.c
@@ -32,10 +32,8 @@
#include "internal.h"
#include
-#ifdef __APPLE__
-#include
-#else
-#include
+#if _WIN32
+ #include
#endif
diff --git a/src/window.c b/src/window.c
index 6c7f5a599..c3944ead1 100644
--- a/src/window.c
+++ b/src/window.c
@@ -33,10 +33,8 @@
#include
#include
-#ifdef __APPLE__
-#include
-#else
-#include
+#if _WIN32
+ #include
#endif
From 7be55239e73c306d8fa5543ff969dda2b26cf9d2 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Mon, 10 Sep 2012 21:45:06 +0200
Subject: [PATCH 45/50] Disabled native API by default.
---
CMakeLists.txt | 8 +++++++-
src/CMakeLists.txt | 20 +++++++++++++++-----
2 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 14eaceb36..c72e00aea 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,6 +12,7 @@ set(LIB_SUFFIX "" CACHE STRING "Takes an empty string or 64. Directory where lib
option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON)
option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON)
+option(GLFW_NATIVE_API "Build the GLFW native API" OFF)
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
find_package(OpenGL REQUIRED)
@@ -259,7 +260,12 @@ configure_file(${GLFW_SOURCE_DIR}/src/config.h.in
# The src directory's CMakeLists.txt file installs the library
#--------------------------------------------------------------------
install(DIRECTORY include/GL DESTINATION include
- FILES_MATCHING PATTERN glfw3.h PATTERN glfw3native.h)
+ FILES_MATCHING PATTERN glfw3.h)
+
+if (GLFW_NATIVE_API)
+ install(DIRECTORY include/GL DESTINATION include
+ FILES_MATCHING PATTERN glfw3native.h)
+endif()
install(FILES COPYING.txt readme.html
DESTINATION share/doc/glfw-${GLFW_VERSION_FULL})
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index eaf37325f..ec5508c2f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -10,7 +10,11 @@ if (_GLFW_COCOA_NSGL)
set(glfw_HEADERS ${common_HEADERS} cocoa_platform.h)
set(glfw_SOURCES ${common_SOURCES} cocoa_clipboard.m cocoa_fullscreen.m
cocoa_gamma.c cocoa_init.m cocoa_input.m cocoa_joystick.m
- cocoa_native.m cocoa_opengl.m cocoa_time.c cocoa_window.m)
+ cocoa_opengl.m cocoa_time.c cocoa_window.m)
+
+ if (GLFW_NATIVE_API)
+ list(APPEND glfw_SOURCES cocoa_native.m)
+ endif()
# For some reason, CMake doesn't know about .m
set_source_files_properties(${glfw_SOURCES} PROPERTIES LANGUAGE C)
@@ -18,14 +22,20 @@ elseif (_GLFW_WIN32_WGL)
set(glfw_HEADERS ${common_HEADERS} win32_platform.h)
set(glfw_SOURCES ${common_SOURCES} win32_clipboard.c win32_fullscreen.c
win32_gamma.c win32_init.c win32_input.c win32_joystick.c
- win32_native.c win32_opengl.c win32_time.c win32_window.c
- win32_dllmain.c)
+ win32_opengl.c win32_time.c win32_window.c win32_dllmain.c)
+
+ if (GLFW_NATIVE_API)
+ list(APPEND glfw_SOURCES win32_native.c)
+ endif()
elseif (_GLFW_X11_GLX)
set(glfw_HEADERS ${common_HEADERS} x11_platform.h)
set(glfw_SOURCES ${common_SOURCES} x11_clipboard.c x11_fullscreen.c
x11_gamma.c x11_init.c x11_input.c x11_joystick.c
- x11_keysym2unicode.c x11_native.c x11_opengl.c x11_time.c
- x11_window.c)
+ x11_keysym2unicode.c x11_opengl.c x11_time.c x11_window.c)
+
+ if (GLFW_NATIVE_API)
+ list(APPEND glfw_SOURCES x11_native.c)
+ endif()
endif()
add_library(glfw ${glfw_SOURCES} ${glfw_HEADERS})
From d214bfdfded62ac933e4388f55597c0ab00a83e4 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 11 Sep 2012 22:23:35 +0200
Subject: [PATCH 46/50] Made defaults test window hidden.
---
tests/defaults.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/defaults.c b/tests/defaults.c
index 391b4984e..2877cfd96 100644
--- a/tests/defaults.c
+++ b/tests/defaults.c
@@ -83,6 +83,8 @@ int main(void)
exit(EXIT_FAILURE);
}
+ glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
+
window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Defaults", NULL);
if (!window)
{
From 023b816bcc3ce638bbab63fad38404d5632e5be2 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 11 Sep 2012 23:51:45 +0200
Subject: [PATCH 47/50] Disallowed hiding of fullscreen windows.
---
src/window.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/src/window.c b/src/window.c
index ab29725d1..04e4f762f 100644
--- a/src/window.c
+++ b/src/window.c
@@ -366,7 +366,7 @@ GLFWAPI GLFWwindow glfwCreateWindow(int width, int height,
glClear(GL_COLOR_BUFFER_BIT);
_glfwPlatformSwapBuffers(window);
- if (wndconfig.visible)
+ if (wndconfig.visible || mode == GLFW_FULLSCREEN)
glfwShowWindow(window);
return window;
@@ -649,15 +649,20 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow handle)
// Window show
//========================================================================
-GLFWAPI void glfwShowWindow(GLFWwindow window)
+GLFWAPI void glfwShowWindow(GLFWwindow handle)
{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return;
}
- _glfwPlatformShowWindow((_GLFWwindow*)window);
+ if (window->mode == GLFW_FULLSCREEN)
+ return;
+
+ _glfwPlatformShowWindow(window);
}
@@ -665,15 +670,20 @@ GLFWAPI void glfwShowWindow(GLFWwindow window)
// Window hide
//========================================================================
-GLFWAPI void glfwHideWindow(GLFWwindow window)
+GLFWAPI void glfwHideWindow(GLFWwindow handle)
{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+
if (!_glfwInitialized)
{
_glfwSetError(GLFW_NOT_INITIALIZED, NULL);
return;
}
- _glfwPlatformHideWindow((_GLFWwindow*)window);
+ if (window->mode == GLFW_FULLSCREEN)
+ return;
+
+ _glfwPlatformHideWindow(window);
}
From 0e2b12be4305e0636cb735839a5219b3b1065b22 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 11 Sep 2012 23:53:10 +0200
Subject: [PATCH 48/50] Corrected comment.
---
src/window.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/window.c b/src/window.c
index 04e4f762f..d4f063f58 100644
--- a/src/window.c
+++ b/src/window.c
@@ -877,7 +877,7 @@ GLFWAPI void glfwSetWindowIconifyCallback(GLFWwindowiconifyfun cbfun)
//========================================================================
-// Poll for new window and input events and close any flagged windows
+// Poll for new window and input events
//========================================================================
GLFWAPI void glfwPollEvents(void)
From e15e92b5838b06dc2835a7bff13292b0cc93a66f Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Tue, 11 Sep 2012 23:56:44 +0200
Subject: [PATCH 49/50] Fixed function grouping.
---
src/window.c | 48 ++++++++++++++++++++++++------------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/src/window.c b/src/window.c
index d4f063f58..b46065a74 100644
--- a/src/window.c
+++ b/src/window.c
@@ -645,6 +645,30 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow handle)
}
+//========================================================================
+// Window un-iconification
+//========================================================================
+
+GLFWAPI void glfwRestoreWindow(GLFWwindow handle)
+{
+ _GLFWwindow* window = (_GLFWwindow*) handle;
+
+ if (!_glfwInitialized)
+ {
+ _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
+ return;
+ }
+
+ if (!window->iconified)
+ return;
+
+ _glfwPlatformRestoreWindow(window);
+
+ if (window->mode == GLFW_FULLSCREEN)
+ _glfwPlatformRefreshWindowParams(window);
+}
+
+
//========================================================================
// Window show
//========================================================================
@@ -687,30 +711,6 @@ GLFWAPI void glfwHideWindow(GLFWwindow handle)
}
-//========================================================================
-// Window un-iconification
-//========================================================================
-
-GLFWAPI void glfwRestoreWindow(GLFWwindow handle)
-{
- _GLFWwindow* window = (_GLFWwindow*) handle;
-
- if (!_glfwInitialized)
- {
- _glfwSetError(GLFW_NOT_INITIALIZED, NULL);
- return;
- }
-
- if (!window->iconified)
- return;
-
- _glfwPlatformRestoreWindow(window);
-
- if (window->mode == GLFW_FULLSCREEN)
- _glfwPlatformRefreshWindowParams(window);
-}
-
-
//========================================================================
// Get window parameter
//========================================================================
From 64c677be9e9e8e9ab693000b99ca61ae710ef0c5 Mon Sep 17 00:00:00 2001
From: Camilla Berglund
Date: Wed, 12 Sep 2012 03:17:50 +0200
Subject: [PATCH 50/50] Renamed config macro to match convention.
---
CMakeLists.txt | 2 +-
src/config.h.in | 2 +-
src/x11_init.c | 2 +-
src/x11_joystick.c | 20 ++++++++++----------
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c72e00aea..a1ad4923f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -184,7 +184,7 @@ if (_GLFW_X11_GLX)
endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
- set(_GLFW_USE_LINUX_JOYSTICKS 1)
+ set(_GLFW_HAS_LINUX_JOYSTICKS 1)
endif()
endif()
diff --git a/src/config.h.in b/src/config.h.in
index 01d541a2b..a432d947d 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -64,7 +64,7 @@
#cmakedefine _GLFW_HAS_GLXGETPROCADDRESSEXT
// Define this to 1 if the Linux joystick API is available
-#cmakedefine _GLFW_USE_LINUX_JOYSTICKS
+#cmakedefine _GLFW_HAS_LINUX_JOYSTICKS
// The GLFW version as used by glfwGetVersionString
#define _GLFW_VERSION_FULL "@GLFW_VERSION_FULL@"
diff --git a/src/x11_init.c b/src/x11_init.c
index 32719cbfd..666866de2 100644
--- a/src/x11_init.c
+++ b/src/x11_init.c
@@ -719,7 +719,7 @@ const char* _glfwPlatformGetVersionString(void)
#if defined(_POSIX_TIMERS) && defined(_POSIX_MONOTONIC_CLOCK)
" clock_gettime"
#endif
-#if defined(_GLFW_USE_LINUX_JOYSTICKS)
+#if defined(_GLFW_HAS_LINUX_JOYSTICKS)
" Linux-joystick-API"
#else
" no-joystick-support"
diff --git a/src/x11_joystick.c b/src/x11_joystick.c
index c1fb62be6..3d2f597d9 100644
--- a/src/x11_joystick.c
+++ b/src/x11_joystick.c
@@ -30,7 +30,7 @@
#include "internal.h"
-#ifdef _GLFW_USE_LINUX_JOYSTICKS
+#ifdef _GLFW_HAS_LINUX_JOYSTICKS
#include
#include
@@ -41,7 +41,7 @@
#include
#include
#include
-#endif // _GLFW_USE_LINUX_JOYSTICKS
+#endif // _GLFW_HAS_LINUX_JOYSTICKS
//========================================================================
@@ -50,7 +50,7 @@
static int openJoystickDevice(int joy, const char* path)
{
-#ifdef _GLFW_USE_LINUX_JOYSTICKS
+#ifdef _GLFW_HAS_LINUX_JOYSTICKS
char numAxes, numButtons;
int fd, version;
@@ -97,7 +97,7 @@ static int openJoystickDevice(int joy, const char* path)
}
_glfwLibrary.X11.joystick[joy].present = GL_TRUE;
-#endif // _GLFW_USE_LINUX_JOYSTICKS
+#endif // _GLFW_HAS_LINUX_JOYSTICKS
return GL_TRUE;
}
@@ -109,7 +109,7 @@ static int openJoystickDevice(int joy, const char* path)
static void pollJoystickEvents(void)
{
-#ifdef _GLFW_USE_LINUX_JOYSTICKS
+#ifdef _GLFW_HAS_LINUX_JOYSTICKS
int i;
ssize_t result;
struct js_event e;
@@ -160,7 +160,7 @@ static void pollJoystickEvents(void)
}
}
}
-#endif // _GLFW_USE_LINUX_JOYSTICKS
+#endif // _GLFW_HAS_LINUX_JOYSTICKS
}
@@ -174,7 +174,7 @@ static void pollJoystickEvents(void)
int _glfwInitJoysticks(void)
{
-#ifdef _GLFW_USE_LINUX_JOYSTICKS
+#ifdef _GLFW_HAS_LINUX_JOYSTICKS
int i, joy = 0;
regex_t regex;
DIR* dir;
@@ -215,7 +215,7 @@ int _glfwInitJoysticks(void)
}
regfree(®ex);
-#endif // _GLFW_USE_LINUX_JOYSTICKS
+#endif // _GLFW_HAS_LINUX_JOYSTICKS
return GL_TRUE;
}
@@ -227,7 +227,7 @@ int _glfwInitJoysticks(void)
void _glfwTerminateJoysticks(void)
{
-#ifdef _GLFW_USE_LINUX_JOYSTICKS
+#ifdef _GLFW_HAS_LINUX_JOYSTICKS
int i;
for (i = 0; i <= GLFW_JOYSTICK_LAST; i++)
@@ -241,7 +241,7 @@ void _glfwTerminateJoysticks(void)
_glfwLibrary.X11.joystick[i].present = GL_FALSE;
}
}
-#endif // _GLFW_USE_LINUX_JOYSTICKS
+#endif // _GLFW_HAS_LINUX_JOYSTICKS
}