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 00000000..f97d07cc
--- /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 00000000..89191223
--- /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 2ffd774c..1f1f0f23 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 89ac48b2..5ea2a815 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 67c6f414..dea2e387 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 fe1898e7..3b30179f 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 df592751..352e3ad9 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 2a5cc451..d7f33999 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 f97d07cc..9bee2cb5 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 89191223..8069e3f3 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 bcad7ef5..9be1c1cd 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 00000000..ba844dd7
--- /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 372fc2dd..afa9de33 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 442e76c0..60a18287 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 60a18287..2d85e041 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 2d85e041..4cf2ce5b 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 4cf2ce5b..0a3608cb 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 27a609a6..842612e8 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 9be1c1cd..e2d2a825 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 0a3608cb..d2f471d0 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 ba844dd7..f19fdf88 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 f19fdf88..de656e01 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 de656e01..d7843106 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 7c208b90..3bb61c18 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 1f1f0f23..4d4c4299 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 97e903d7..a202c25e 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 fb0ba47f..6801e144 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 d7f33999..38a43ff0 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 d7843106..6e3a6eaf 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 e2d2a825..80a7b82f 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 6e3a6eaf..35c83716 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 050f0c30..79b6033a 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 d7764f92..db6d07b8 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 89ac48b2..1bad7483 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 77b99026..ff6941ab 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 4e95129a..efaa1572 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 442e76c0..90938ccb 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 fce8b8de..5139a493 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 79b6033a..5472f8b1 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 39d0739b..580e21cd 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 efaa1572..81b0492c 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 81b0492c..4f8a96e6 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 5472f8b1..6f535408 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 580e21cd..c6eedbf3 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 db6d07b8..0d62b0fa 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 1bad7483..8e923d50 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 ff6941ab..b83d504a 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 4f8a96e6..7e928cf2 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 90938ccb..b4d62605 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 c6eedbf3..dd80672e 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 894febeb..f4c74bfd 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 0d62b0fa..35bdd974 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 7e928cf2..2507dd5c 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 90fd329f..0019bf66 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 f4c74bfd..894febeb 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 5a74955e..13096073 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 79bbbb94..ba10039e 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 1e1d57f4..96f7b454 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 45f44339..1e90a5bc 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 d330d1c1..5431eb9e 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 5129a21f..43576ab0 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 43576ab0..14f1856c 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 5431eb9e..497546cd 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 52d6e0de..9d562400 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 0496a03c..da61d802 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 a5700c68..1895dc6a 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 497546cd..314c392a 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 7eac7f91..04c9e972 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 a5277c09..32719cbf 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 1895dc6a..a383fa02 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 75beb745..a6b576ed 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 a383fa02..c1fb62be 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 9bee2cb5..ced7cf3f 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 8069e3f3..1a9c805c 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 314c392a..31e9217e 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 f219275c..cbc28dd0 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 80a7b82f..11bcfe9e 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 1a9c805c..18451ef9 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 f632749f..4372d153 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 6c7f5a59..c3944ead 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 14eaceb3..c72e00ae 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 eaf37325..ec5508c2 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 391b4984..2877cfd9 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 ab29725d..04e4f762 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 04e4f762..d4f063f5 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 d4f063f5..b46065a7 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 c72e00ae..a1ad4923 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 01d541a2..a432d947 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 32719cbf..666866de 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 c1fb62be..3d2f597d 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
}