Compare commits

...

8 Commits

Author SHA1 Message Date
Alberto Mardegan
175c4e957b
Merge 7c224bcd71 into 63a7e8b7f8 2025-08-21 05:49:47 +02:00
Camilla Löwy
63a7e8b7f8 Add and update Wayland-specific notes in docs
Fixes #2746
2025-08-20 20:13:07 +02:00
Doug Binks
acb92944d4 Revert readme for "Wayland: Keyboard leave event handler now processes key repeats" 2025-08-19 11:30:52 +02:00
Camilla Löwy
7ef6efeb66 Wayland: Fix cursor position after a modal
If a modal surface like the window menu was active, clicking on the GLFW
window content area to close it would correctly emit the cursor enter
event but would not propagate the cursor position from the event.
2025-08-18 20:58:12 +02:00
Camilla Löwy
3cf9f6726d Wayland: Fix fallback decoration cursor updating
When a click through to the fallback decorations caused the end of
a modal like the window menu, the cursor shape would not be updated
until the next time the cursor moved.

This commit adds an update of the cursor for the pointer enter event for
fallback decoration surfaces, in addition to the updates at pointer
motion events.
2025-08-18 18:06:46 +02:00
Camilla Löwy
bfa1c424e5 Wayland: Fix fallback decoration menu placement
The fallback decorations would place the menu at the wrong position, by
not translating the last decoration surface position into toplevel
surface coordinates.

This also limits the menu to the caption area of the top decoration
surface, similar to how other toolkits work.
2025-08-18 18:06:46 +02:00
Alberto Mardegan
7c224bcd71 WIP: add GameCube & Wii support 2025-01-27 17:24:14 +03:00
Alberto Mardegan
bc0d63cf82 nuklear: fix big-endian image conversion
This has been submitted upstream as well.
2025-01-27 17:24:14 +03:00
30 changed files with 3015 additions and 41 deletions

View File

@ -24,8 +24,15 @@ if (DEFINED GLFW_USE_WAYLAND AND UNIX AND NOT APPLE)
"GLFW_USE_WAYLAND has been removed; delete the CMake cache and set GLFW_BUILD_WAYLAND and GLFW_BUILD_X11 instead")
endif()
IF(CMAKE_SYSTEM_NAME MATCHES "NintendoWii|NintendoGameCube")
SET(OGC ON)
ELSE()
SET(OGC OFF)
ENDIF()
cmake_dependent_option(GLFW_BUILD_WIN32 "Build support for Win32" ON "WIN32" OFF)
cmake_dependent_option(GLFW_BUILD_COCOA "Build support for Cocoa" ON "APPLE" OFF)
cmake_dependent_option(GLFW_BUILD_OGC "Build support for Nintendo GameCube/Wii" ON "OGC" OFF)
cmake_dependent_option(GLFW_BUILD_X11 "Build support for X11" ON "UNIX;NOT APPLE" OFF)
cmake_dependent_option(GLFW_BUILD_WAYLAND "Build support for Wayland" ON "UNIX;NOT APPLE" OFF)
@ -49,7 +56,7 @@ endif()
list(APPEND CMAKE_MODULE_PATH "${GLFW_SOURCE_DIR}/CMake/modules")
find_package(Threads REQUIRED)
find_package(Threads)
#--------------------------------------------------------------------
# Report backend selection

View File

@ -55,6 +55,7 @@ video tutorials.
- Jason Daly
- danhambleton
- Jarrod Davis
- decce
- Olivier Delannoy
- Paul R. Deppe
- Michael Dickens

View File

@ -134,11 +134,15 @@ information on what to include when reporting a bug.
- [Wayland] Bugfix: Ignore key repeat events when no window has keyboard focus (#2727)
- [Wayland] Bugfix: Reset key repeat timer when window destroyed (#2741,#2727)
- [Wayland] Bugfix: Memory would leak if reading a data offer failed midway
- [Wayland] Bugfix: Keyboard leave event handler now processes key repeats (#2736)
- [Wayland] Bugfix: Retrieved cursor position would be incorrect when hovering over
fallback decorations
- [Wayland] Bugfix: Fallback decorations would report scroll events
- [Wayland] Bugfix: Keyboard repeat events halted when any key is released (#2568)
- [Wayland] Bugfix: Fallback decorations would show menu at wrong position
- [Wayland] Bugfix: The cursor was not updated when clicking through from
a modal to a fallback decoration
- [Wayland] Bugfix: The cursor position was not updated when clicking through
from a modal to the content area
- [X11] Bugfix: Running without a WM could trigger an assert (#2593,#2601,#2631)
- [Null] Added Vulkan 'window' surface creation via `VK_EXT_headless_surface`
- [Null] Added EGL context creation on Mesa via `EGL_MESA_platform_surfaceless`

12
deps/nuklear.h vendored
View File

@ -12988,7 +12988,7 @@ nk_font_bake_convert(void *out_memory, int img_width, int img_height,
const void *in_memory)
{
int n = 0;
nk_rune *dst;
nk_byte *dst;
const nk_byte *src;
NK_ASSERT(out_memory);
@ -12997,10 +12997,14 @@ nk_font_bake_convert(void *out_memory, int img_width, int img_height,
NK_ASSERT(img_height);
if (!out_memory || !in_memory || !img_height || !img_width) return;
dst = (nk_rune*)out_memory;
dst = (nk_byte*)out_memory;
src = (const nk_byte*)in_memory;
for (n = (int)(img_width * img_height); n > 0; n--)
*dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
for (n = (int)(img_width * img_height); n > 0; n--) {
*dst++ = 0xff; // r
*dst++ = 0xff; // g
*dst++ = 0xff; // b
*dst++ = *src++; // a
}
}
/* -------------------------------------------------------------

28
deps/tinycthread.c vendored
View File

@ -40,6 +40,8 @@ freely, subject to the following restrictions:
#elif defined(_TTHREAD_WIN32_)
#include <process.h>
#include <sys/timeb.h>
#elif defined(_TTHREAD_OGC_)
#include <ogcsys.h>
#endif
/* Standard, good-to-have defines */
@ -60,6 +62,8 @@ int mtx_init(mtx_t *mtx, int type)
mtx->mRecursive = type & mtx_recursive;
InitializeCriticalSection(&mtx->mHandle);
return thrd_success;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
int ret;
pthread_mutexattr_t attr;
@ -78,6 +82,7 @@ void mtx_destroy(mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
DeleteCriticalSection(&mtx->mHandle);
#elif defined(_TTHREAD_OGC_)
#else
pthread_mutex_destroy(mtx);
#endif
@ -93,6 +98,8 @@ int mtx_lock(mtx_t *mtx)
mtx->mAlreadyLocked = TRUE;
}
return thrd_success;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return pthread_mutex_lock(mtx) == 0 ? thrd_success : thrd_error;
#endif
@ -116,6 +123,8 @@ int mtx_trylock(mtx_t *mtx)
ret = thrd_busy;
}
return ret;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return (pthread_mutex_trylock(mtx) == 0) ? thrd_success : thrd_busy;
#endif
@ -127,6 +136,8 @@ int mtx_unlock(mtx_t *mtx)
mtx->mAlreadyLocked = FALSE;
LeaveCriticalSection(&mtx->mHandle);
return thrd_success;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return pthread_mutex_unlock(mtx) == 0 ? thrd_success : thrd_error;;
#endif
@ -161,6 +172,8 @@ int cnd_init(cnd_t *cond)
}
return thrd_success;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return pthread_cond_init(cond, NULL) == 0 ? thrd_success : thrd_error;
#endif
@ -178,6 +191,7 @@ void cnd_destroy(cnd_t *cond)
CloseHandle(cond->mEvents[_CONDITION_EVENT_ALL]);
}
DeleteCriticalSection(&cond->mWaitersCountLock);
#elif defined(_TTHREAD_OGC_)
#else
pthread_cond_destroy(cond);
#endif
@ -203,6 +217,8 @@ int cnd_signal(cnd_t *cond)
}
return thrd_success;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
@ -228,6 +244,8 @@ int cnd_broadcast(cnd_t *cond)
}
return thrd_success;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return pthread_cond_signal(cond) == 0 ? thrd_success : thrd_error;
#endif
@ -286,6 +304,8 @@ int cnd_wait(cnd_t *cond, mtx_t *mtx)
{
#if defined(_TTHREAD_WIN32_)
return _cnd_timedwait_win32(cond, mtx, INFINITE);
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
return pthread_cond_wait(cond, mtx) == 0 ? thrd_success : thrd_error;
#endif
@ -303,6 +323,8 @@ int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts)
}
else
return thrd_error;
#elif defined(_TTHREAD_OGC_)
return thrd_error;
#else
int ret;
ret = pthread_cond_timedwait(cond, mtx, ts);
@ -324,14 +346,14 @@ typedef struct {
/* Thread wrapper function. */
#if defined(_TTHREAD_WIN32_)
static unsigned WINAPI _thrd_wrapper_function(void * aArg)
#elif defined(_TTHREAD_POSIX_)
#else
static void * _thrd_wrapper_function(void * aArg)
#endif
{
thrd_start_t fun;
void *arg;
int res;
#if defined(_TTHREAD_POSIX_)
#if defined(_TTHREAD_POSIX_) || defined(_TTHREAD_OGC_)
void *pres;
#endif
@ -394,6 +416,8 @@ thrd_t thrd_current(void)
{
#if defined(_TTHREAD_WIN32_)
return GetCurrentThread();
#elif defined(_TTHREAD_OGC_)
return LWP_GetSelf();
#else
return pthread_self();
#endif

6
deps/tinycthread.h vendored
View File

@ -51,6 +51,8 @@ freely, subject to the following restrictions:
#if !defined(_TTHREAD_PLATFORM_DEFINED_)
#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
#define _TTHREAD_WIN32_
#elif defined(GEKKO)
#define _TTHREAD_OGC_
#else
#define _TTHREAD_POSIX_
#endif
@ -80,6 +82,8 @@ freely, subject to the following restrictions:
#if defined(_TTHREAD_POSIX_)
#include <sys/time.h>
#include <pthread.h>
#elif defined(_TTHREAD_OGC_)
#include <ogcsys.h>
#elif defined(_TTHREAD_WIN32_)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
@ -313,6 +317,8 @@ int cnd_timedwait(cnd_t *cond, mtx_t *mtx, const struct timespec *ts);
/* Thread */
#if defined(_TTHREAD_WIN32_)
typedef HANDLE thrd_t;
#elif defined(_TTHREAD_OGC_)
typedef lwp_t thrd_t;
#else
typedef pthread_t thrd_t;
#endif

View File

@ -255,3 +255,7 @@ hardware gamma correction, which today is typically an approximation of sRGB
gamma. This means that setting a perfectly linear ramp, or gamma 1.0, will
produce the default (usually sRGB-like) behavior.
@note @wayland An application cannot read or modify the monitor gamma ramp. The
@ref glfwGetGammaRamp, @ref glfwSetGammaRamp and @ref glfwSetGamma functions
emit @ref GLFW_FEATURE_UNAVAILABLE.

View File

@ -893,6 +893,12 @@ int xpos, ypos;
glfwGetWindowPos(window, &xpos, &ypos);
```
@note @wayland An applications cannot know the positions of its windows or
whether one has been moved. The @ref GLFW_POSITION_X and @ref GLFW_POSITION_Y
window hints are ignored. The @ref glfwGetWindowPos and @ref glfwSetWindowPos
functions emit @ref GLFW_FEATURE_UNAVAILABLE. The window position callback will
not be called.
### Window title {#window_title}
@ -1038,6 +1044,12 @@ You can also get the current iconification state with @ref glfwGetWindowAttrib.
int iconified = glfwGetWindowAttrib(window, GLFW_ICONIFIED);
```
@note @wayland An application cannot know if any of its windows have been
iconified or restore one from iconification. The @ref glfwRestoreWindow
function can only restore windows from maximization and the iconify callback
will not be called. The [GLFW_ICONIFIED](@ref GLFW_ICONIFIED_attrib) attribute
will be false. The @ref glfwIconifyWindow function works normally.
### Window maximization {#window_maximize}

View File

@ -37,7 +37,9 @@ add_executable(triangle-opengles WIN32 MACOSX_BUNDLE triangle-opengles.c ${ICON}
add_executable(wave WIN32 MACOSX_BUNDLE wave.c ${ICON} ${GLAD_GL})
add_executable(windows WIN32 MACOSX_BUNDLE windows.c ${ICON} ${GLAD_GL})
target_link_libraries(particles Threads::Threads)
if (Threads_FOUND)
target_link_libraries(particles Threads::Threads)
endif()
if (RT_LIBRARY)
target_link_libraries(particles "${RT_LIBRARY}")
endif()

View File

@ -1342,6 +1342,7 @@ extern "C" {
#define GLFW_PLATFORM_WAYLAND 0x00060003
#define GLFW_PLATFORM_X11 0x00060004
#define GLFW_PLATFORM_NULL 0x00060005
#define GLFW_PLATFORM_OGC 0x00060006
/*! @} */
#define GLFW_DONT_CARE -1
@ -2915,8 +2916,8 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_INVALID_VALUE,
* @ref GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
*
* @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* @remark @wayland Monitor gamma is a privileged protocol, so this function
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
*
* @thread_safety This function must only be called from the main thread.
*
@ -2939,8 +2940,8 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR
* and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
*
* @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
* @remark @wayland Monitor gamma is a privileged protocol, so this function
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE while
* returning `NULL`.
*
* @pointer_lifetime The returned structure and its arrays are allocated and
@ -2983,8 +2984,8 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
*
* @remark @win32 The gamma ramp size must be 256.
*
* @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
* @remark @wayland Monitor gamma is a privileged protocol, so this function
* cannot be implemented and emits @ref GLFW_FEATURE_UNAVAILABLE.
*
* @pointer_lifetime The specified gamma ramp is copied before this function
* returns.
@ -3430,8 +3431,8 @@ GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* i
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
*
* @remark @wayland There is no way for an application to retrieve the global
* position of its windows. This function will emit @ref
* @remark @wayland Window positions are not currently part of any common
* Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE.
*
* @thread_safety This function must only be called from the main thread.
@ -3464,8 +3465,8 @@ GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks).
*
* @remark @wayland There is no way for an application to set the global
* position of its windows. This function will emit @ref
* @remark @wayland Window positions are not currently part of any common
* Wayland protocol, so this function cannot be implemented and will emit @ref
* GLFW_FEATURE_UNAVAILABLE.
*
* @thread_safety This function must only be called from the main thread.
@ -3807,10 +3808,6 @@ GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland Once a window is iconified, @ref glfwRestoreWindow wont
* be able to restore it. This is a design decision of the xdg-shell
* protocol.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_iconify
@ -3838,6 +3835,10 @@ GLFWAPI void glfwIconifyWindow(GLFWwindow* window);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR.
*
* @remark @wayland Restoring a window from maximization is not currently part
* of any common Wayland protocol, so this function can only restore windows
* from maximization.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_iconify
@ -4058,8 +4059,8 @@ GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window);
* affected by any resizing or mode switching, although you may need to update
* your viewport if the framebuffer size has changed.
*
* @remark @wayland The desired window position is ignored, as there is no way
* for an application to set this property.
* @remark @wayland Window positions are not currently part of any common
* Wayland protocol. The window position arguments are ignored.
*
* @thread_safety This function must only be called from the main thread.
*
@ -4096,8 +4097,9 @@ GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int
* errors. However, this function should not fail as long as it is passed
* valid arguments and the library has been [initialized](@ref intro_init).
*
* @remark @wayland The Wayland protocol provides no way to check whether a
* window is iconfied, so @ref GLFW_ICONIFIED always returns `GLFW_FALSE`.
* @remark @wayland Checking whether a window is iconified is not currently
* part of any common Wayland protocol, so the @ref GLFW_ICONIFIED attribute
* cannot be implemented and is always `GLFW_FALSE`.
*
* @thread_safety This function must only be called from the main thread.
*
@ -4219,8 +4221,8 @@ GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window);
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @remark @wayland This callback will never be called, as there is no way for
* an application to know its global position.
* @remark @wayland This callback will not be called. The Wayland protocol
* provides no way to be notified of when a window is moved.
*
* @thread_safety This function must only be called from the main thread.
*
@ -4395,6 +4397,10 @@ GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwi
*
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED.
*
* @remark @wayland This callback will not be called. The Wayland protocol
* provides no way to be notified of when a window is iconified, and no way to
* check whether a window is currently iconified.
*
* @thread_safety This function must only be called from the main thread.
*
* @sa @ref window_iconify

View File

@ -15,6 +15,9 @@ if (APPLE)
elseif (WIN32)
target_sources(glfw PRIVATE win32_time.h win32_thread.h win32_module.c
win32_time.c win32_thread.c)
elseif (OGC)
target_sources(glfw PRIVATE ogc_time.h ogc_thread.h ogc_module.c
ogc_time.c ogc_thread.c)
else()
target_sources(glfw PRIVATE posix_time.h posix_thread.h posix_module.c
posix_time.c posix_thread.c)
@ -57,6 +60,13 @@ if (GLFW_BUILD_WAYLAND)
wl_monitor.c wl_window.c)
endif()
if (GLFW_BUILD_OGC)
target_compile_definitions(glfw PRIVATE _GLFW_OGC)
target_sources(glfw PRIVATE ogc_platform.h ogc_init.c ogc_joystick.c
ogc_monitor.c ogc_window.c ogc_context.c
ogc_cursor.h)
endif()
if (GLFW_BUILD_X11 OR GLFW_BUILD_WAYLAND)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_sources(glfw PRIVATE linux_joystick.h linux_joystick.c)
@ -136,7 +146,9 @@ target_include_directories(glfw PUBLIC
target_include_directories(glfw PRIVATE
"${GLFW_SOURCE_DIR}/src"
"${GLFW_BINARY_DIR}/src")
target_link_libraries(glfw PRIVATE Threads::Threads)
if (Threads_FOUND)
target_link_libraries(glfw PRIVATE Threads::Threads)
endif()
if (GLFW_BUILD_WIN32)
list(APPEND glfw_PKG_LIBS "-lgdi32")
@ -213,6 +225,13 @@ if (GLFW_BUILD_X11)
target_include_directories(glfw PRIVATE "${X11_Xshape_INCLUDE_PATH}")
endif()
if (GLFW_BUILD_OGC)
include(FindPkgConfig)
pkg_check_modules(Opengx REQUIRED IMPORTED_TARGET opengl)
target_link_libraries(glfw PRIVATE PkgConfig::Opengx wiikeyboard fat)
endif()
if (UNIX AND NOT APPLE)
find_library(RT_LIBRARY rt)
mark_as_advanced(RT_LIBRARY)

View File

@ -997,5 +997,13 @@ const char* _glfwDefaultMappings[] =
"03000000120c0000100e000011010000,ZEROPLUS P4 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
"03000000120c0000101e000011010000,ZEROPLUS P4 Wired Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,",
#endif // GLFW_BUILD_LINUX_JOYSTICK
#if defined(_GLFW_OGC)
"05002bf87e0500000105000001000000,Nintendo Wiimote 1,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b4,start:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Ogc,",
"0500ea387e0500000106000001000000,Nintendo Wiimote 2,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b4,start:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Ogc,",
"0500aa397e0500000107000001000000,Nintendo Wiimote 3,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b4,start:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Ogc,",
"05006bf97e0500000108000001000000,Nintendo Wiimote 4,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b4,start:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Ogc,",
"0500b98e7e0500000305000001000000,Nintendo Wii Classic 1,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b4,start:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Ogc,",
#endif
};

View File

@ -78,5 +78,9 @@ const char* _glfwDefaultMappings[] =
#if defined(GLFW_BUILD_LINUX_JOYSTICK)
@GLFW_LINUX_MAPPINGS@
#endif // GLFW_BUILD_LINUX_JOYSTICK
#if defined(_GLFW_OGC)
"05002bf87e0500000105000001000000,Nintendo Wiimote,a:b0,b:b1,x:b2,y:b3,back:b6,guide:b4,start:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,platform:Ogc,",
#endif
};

204
src/ogc_context.c Normal file
View File

@ -0,0 +1,204 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <opengx.h>
#ifdef __wii__
#include <wiiuse/wpad.h>
#endif
#ifdef __wii__
static void drawCursorRect(_GLFWcursor* cursor)
{
short xhot = cursor->ogc.xhot;
short yhot = cursor->ogc.yhot;
u16 width = GX_GetTexObjWidth(&cursor->ogc.texobj);
u16 height = GX_GetTexObjHeight(&cursor->ogc.texobj);
GX_Begin(GX_QUADS, GX_VTXFMT0, 4);
GX_Position2s16(-xhot, -yhot);
GX_TexCoord2u8(0, 0);
GX_Position2s16(width - xhot, -yhot);
GX_TexCoord2u8(1, 0);
GX_Position2s16(width - xhot, height - yhot);
GX_TexCoord2u8(1, 1);
GX_Position2s16(-xhot, height - yhot);
GX_TexCoord2u8(0, 1);
GX_End();
}
static void drawCursor(_GLFWwindow* window)
{
Mtx44 proj;
Mtx mv;
_GLFWcursor* cursor = window->ogc.currentCursor;
if (!cursor) return;
GX_LoadTexObj(&cursor->ogc.texobj, GX_TEXMAP0);
int width = window->ogc.width;
int height = window->ogc.height;
guOrtho(proj, 0, height, 0, width, 0, 1);
GX_LoadProjectionMtx(proj, GX_ORTHOGRAPHIC);
guMtxIdentity(mv);
guMtxScaleApply(mv, mv,
width / 640.0f,
height / 480.0f, 1.0f);
if (cursor->ogc.canRotate) {
Mtx rot;
float angle;
WPADData *data = WPAD_Data(0);
angle = data->ir.angle;
guMtxRotDeg(rot, 'z', angle);
guMtxConcat(mv, rot, mv);
}
guMtxTransApply(mv, mv,
window->virtualCursorPosX,
window->virtualCursorPosY, 0);
GX_LoadPosMtxImm(mv, GX_PNMTX1);
GX_ClearVtxDesc();
GX_SetVtxDesc(GX_VA_POS, GX_DIRECT);
GX_SetVtxDesc(GX_VA_TEX0, GX_DIRECT);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S16, 0);
GX_SetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_U8, 0);
GX_SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY);
GX_SetTevOp(GX_TEVSTAGE0, GX_REPLACE);
GX_SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
GX_SetNumTevStages(1);
GX_SetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR);
GX_SetNumTexGens(1);
GX_SetCurrentMtx(GX_PNMTX1);
GX_SetZMode(GX_DISABLE, GX_ALWAYS, GX_FALSE);
GX_SetScissor(0, 0, width, height);
drawCursorRect(cursor);
GX_SetCurrentMtx(GX_PNMTX0);
GX_DrawDone();
}
#endif // __wii__
static void makeContextCurrentOgc(_GLFWwindow* window)
{
_glfwPlatformSetTls(&_glfw.contextSlot, window);
}
static GLFWglproc getProcAddressOgc(const char* procname)
{
return (GLFWglproc) ogx_get_proc_address(procname);
}
static void destroyContextOgc(_GLFWwindow* window)
{
}
static void swapBuffersOgc(_GLFWwindow* window)
{
void *xfb;
u8 mustClear, mustWait;
if (ogx_prepare_swap_buffers() < 0) return;
#ifdef __wii__
if (window->ogc.hovered &&
(window->callbacks.mouseButton || window->callbacks.cursorPos))
drawCursor(window);
#endif // __wii__
if (window->doublebuffer) {
mustClear = GX_TRUE;
mustWait = GX_TRUE;
xfb = _glfw.ogc.xfb[_glfw.ogc.fbIndex];
_glfw.ogc.fbIndex ^= 1;
} else {
mustClear = GX_FALSE;
mustWait = GX_FALSE;
xfb = _glfw.ogc.xfb[0];
}
GX_CopyDisp(xfb, mustClear);
GX_DrawDone();
GX_Flush();
VIDEO_SetNextFramebuffer(xfb);
VIDEO_Flush();
if (mustWait)
VIDEO_WaitVSync();
}
static void swapIntervalOgc(int interval)
{
// No swap interval on Ogc
}
static int extensionSupportedOgc(const char* extension)
{
const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
return strstr(extensions, extensions) != NULL;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwCreateContextOgc(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
if (ctxconfig->client == GLFW_OPENGL_ES_API)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"Ogc: OpenGL ES is not available on Ogc");
return GLFW_FALSE;
}
ogx_enable_double_buffering(fbconfig->doublebuffer);
if (fbconfig->stencilBits > 0) {
OgxStencilFlags stencilFlags = OGX_STENCIL_NONE;
if (fbconfig->stencilBits > 4) stencilFlags |= OGX_STENCIL_8BIT;
ogx_stencil_create(stencilFlags);
}
window->context.makeCurrent = makeContextCurrentOgc;
window->context.swapBuffers = swapBuffersOgc;
window->context.swapInterval = swapIntervalOgc;
window->context.extensionSupported = extensionSupportedOgc;
window->context.getProcAddress = getProcAddressOgc;
window->context.destroy = destroyContextOgc;
return GLFW_TRUE;
}

487
src/ogc_cursor.h Normal file
View File

@ -0,0 +1,487 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <gctypes.h>
typedef struct {
u16 width;
u16 height;
u8 hot_x;
u8 hot_y;
u8 bytes_per_pixel;
u8 pixel_data[];
} _GLFWcursorDataOgc;
static const _GLFWcursorDataOgc OGC_cursor_hand = {
37, 52, 11, 0, 4,
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000Q\000"
"\000\000\262\000\000\000\337\000\000\000\345\000\000\000\313\000\000\000\203\000\000\000\032\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\005"
"\000\000\000\224\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000"
"\000\000\330\000\000\000\062\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\177\000\000\000\377\000\000\000\377\026\026\026\377bbb\377ttt\377"
"<<<\377\000\000\000\377\000\000\000\377\000\000\000\334\000\000\000\030\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000%\000\000\000\364\000\000\000\377...\377\327\327"
"\327\377\377\377\377\377\377\377\377\377\373\373\373\377\177\177\177\377"
"\000\000\000\377\000\000\000\377\000\000\000\206\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000n\000\000\000\377\005\005\005\377\277\277\277\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377BBB\377\000"
"\000\000\377\000\000\000\323\000\000\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\225\000\000\000\377###\377\366\366\366\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\206\206\206\377\000\000"
"\000\377\000\000\000\356\000\000\000\033\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\231\000\000\000\377+++\377\370\370\370\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\217\217\217\377\000\000\000\377"
"\000\000\000\361\000\000\000\040\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\230\000\000\000\377***\377\367\367\367\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\215\215\215\377\000\000\000\377\000"
"\000\000\360\000\000\000\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230"
"\000\000\000\377***\377\367\367\367\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000"
"\360\000\000\000\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000"
"\000\000\377***\377\367\367\367\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\360"
"\000\000\000\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000"
"\377***\377\367\367\367\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\360\000\000"
"\000\037\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000\377"
"***\377\367\367\367\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\360\000\000\000\037"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000\377***\377"
"\367\367\367\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\360\000\000\000\037\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000\377***\377\367"
"\367\367\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\357\000\000\000\026\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000\377***\377\367\367"
"\367\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\370\000\000\000\244\000\000\000\223"
"\000\000\000e\000\000\000\032\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000\377***\377\367\367"
"\367\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\215\215\215\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
"\000\000\000\377\000\000\000\340\000\000\000Z\000\000\000\000\000\000\000\003\000\000\000\022\000\000\000\006\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000\377***\377\367"
"\367\367\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\215\215\215\377\000\000\000\377\001\001\001\377%%%\377\036\036\036"
"\377\000\000\000\377\000\000\000\377\000\000\000\373\000\000\000\244\000\000\000\310\000\000\000\341\000\000\000\320"
"\000\000\000\220\000\000\000*\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\230\000\000\000"
"\377***\377\367\367\367\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\210\210\210\377\022\022\022\377\270\270\270"
"\377\356\356\356\377\351\351\351\377\236\236\236\377\022\022\022\377\000\000\000\377"
"\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\357\000\000\000[\000\000\000"
"\030\000\000\000<\000\000\000B\000\000\000(\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\227\000\000\000\377***\377\367\367\367\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\202\202\202\377\065\065\065\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\246\246\246\377\001\001\001\377\003\003\003\377@@@\377iii\377DD"
"D\377\002\002\002\377\000\000\000\377\000\000\000\372\000\000\000\342\000\000\000\375\000\000\000\377\000\000\000\360"
"\000\000\000\264\000\000\000:\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\233\000\000\000\377***\377\367\367\367\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\203\203\203\377\061\061\061"
"\377\375\375\375\377\377\377\377\377\377\377\377\377\377\377\377\377\372"
"\372\372\377\036\036\036\377kkk\377\375\375\375\377\377\377\377\377\377\377"
"\377\377\253\253\253\377\015\015\015\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000"
"\377\000\000\000\377\000\000\000\377\000\000\000\366\000\000\000U\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\016"
"\000\000\000n\000\000\000\272\000\000\000\360\000\000\000\377***\377\367\367\367\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\203"
"\203\203\377\061\061\061\377\375\375\375\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\376\376\376\377\063\063\063\377\211\211\211\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\177\177\177\377\000\000"
"\000\377AAA\377\236\236\236\377\256\256\256\377lll\377\011\011\011\377\000\000\000\377"
"\000\000\000\360\000\000\000)\000\000\000\000\000\000\000!\000\000\000\304\000\000\000\377\000\000\000\377\000\000\000\377"
"\000\000\000\377***\377\367\367\367\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\203\203\203\377\061\061\061\377\375"
"\375\375\377\377\377\377\377\377\377\377\377\377\377\377\377\375\375\375"
"\377\061\061\061\377\203\203\203\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\304\304\304\377\011\011\011\377\327\327\327\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\247\247\247\377\006\006\006\377\000"
"\000\000\377\000\000\000\225\000\000\000\016\000\000\000\312\000\000\000\377\000\000\000\377(((\377aaa\377\067"
"\067\067\377'''\377\366\366\366\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\203\203\203\377\061\061\061\377\375"
"\375\375\377\377\377\377\377\377\377\377\377\377\377\377\377\375\375\375"
"\377\061\061\061\377\203\203\203\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\313\313\313\377\015\015\015\377\323\323\323\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377NNN\377\000\000\000"
"\377\000\000\000\324\000\000\000s\000\000\000\377\000\000\000\377fff\377\357\357\357\377\377\377"
"\377\377\244\244\244\377###\377\365\365\365\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377|||\377&&&\377\375\375"
"\375\377\377\377\377\377\377\377\377\377\377\377\377\377\375\375\375\377"
"&&&\377|||\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\306\306\306\377\001\001\001\377\317\317\317\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\200\200\200\377\000\000\000\377\000\000\000\345"
"\000\000\000\305\000\000\000\377\062\062\062\377\371\371\371\377\377\377\377\377\377\377"
"\377\377\235\235\235\377###\377\365\365\365\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\274\274\274\377\221"
"\221\221\377\376\376\376\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\376\376\376\377\221\221\221\377\274\274\274\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\342\342\340\377\200\200\200"
"\377\347\347\347\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\202\202\202\377\000\000\000\377\000\000\000\345\000\000\000\342\000\000\000\377www\377"
"\377\377\377\377\376\376\376\377\377\377\377\377\235\235\235\377!##\377\365"
"\365\365\377\377\377\377\377\374\376\376\377\374\376\376\377\374\376\376"
"\377\374\376\376\377\377\377\377\377\377\377\377\377\374\376\376\377\374"
"\376\376\377\374\376\376\377\374\376\376\377\374\376\376\377\377\377\377"
"\377\377\377\377\377\374\376\376\377\374\376\376\377\374\376\376\377\374"
"\376\376\377\377\377\377\377\377\377\377\377\377\377\377\377\374\376\376"
"\377\374\376\376\377\374\376\376\377\377\377\377\377\201\201\201\377\000\000"
"\000\377\000\000\000\345\000\000\000\346\000\000\000\377\203\203\203\377\377\377\377\377\375"
"\373\375\377\377\377\377\377\233\233\235\377!!#\377\363\363\365\377\377\377"
"\377\377\373\373\376\377\373\373\376\377\373\373\376\377\373\373\376\377"
"\373\373\376\377\373\373\376\377\373\373\376\377\373\373\375\377\373\373"
"\376\377\373\373\376\377\373\373\376\377\373\373\375\377\373\373\376\377"
"\373\373\376\377\373\373\376\377\373\373\376\377\373\373\376\377\373\373"
"\376\377\373\373\375\377\373\373\375\377\373\373\375\377\373\373\376\377"
"\373\374\376\377\377\377\377\377\201\201\201\377\000\000\000\377\000\000\000\345\000\000"
"\000\345\000\000\000\377\177\201\201\377\377\377\377\377\371\373\376\377\377\377"
"\377\377\233\233\235\377\"\"\"\377\361\363\366\377\375\377\377\377\371\373"
"\376\377\371\373\376\377\371\373\376\377\367\372\376\377\367\372\376\377"
"\371\371\376\377\371\371\376\377\371\373\376\377\371\373\376\377\371\373"
"\376\377\371\373\376\377\367\372\376\377\367\372\376\377\371\373\376\377"
"\367\372\376\377\367\372\376\377\371\373\376\377\367\372\376\377\371\373"
"\376\377\371\373\376\377\367\372\376\377\367\372\376\377\371\373\376\377"
"\377\377\377\377\177\201\201\377\000\000\000\377\000\000\000\345\000\000\000\345\000\000\000\377"
"\177\177\201\377\377\377\377\377\365\370\377\377\377\377\377\377\234\234"
"\234\377\"\"\"\377\356\361\365\377\372\375\377\377\365\370\375\377\365\370"
"\375\377\365\370\375\377\365\370\375\377\365\370\375\377\365\370\375\377"
"\365\370\375\377\365\370\375\377\365\370\375\377\365\370\375\377\365\370"
"\375\377\365\370\375\377\365\370\375\377\365\370\375\377\365\370\375\377"
"\365\370\375\377\365\370\375\377\365\370\375\377\365\370\375\377\365\370"
"\375\377\365\370\375\377\365\370\375\377\366\371\376\377\377\377\377\377"
"\177\177\201\377\000\000\000\377\000\000\000\345\000\000\000\345\000\000\000\377}\200\202\377\377"
"\377\377\377\363\366\375\377\377\377\377\377\232\234\234\377\"\"\"\377\355"
"\357\364\377\370\372\377\377\363\366\375\377\363\366\375\377\363\366\375"
"\377\363\366\375\377\363\366\375\377\363\366\375\377\363\366\375\377\363"
"\366\375\377\363\366\375\377\363\366\375\377\363\366\375\377\363\366\375"
"\377\363\366\375\377\363\366\375\377\363\366\375\377\363\366\375\377\363"
"\366\375\377\363\366\375\377\363\366\375\377\363\366\375\377\363\366\375"
"\377\363\366\375\377\364\367\376\377\377\377\377\377~\177\201\377\000\000\000\377"
"\000\000\000\345\000\000\000\345\000\000\000\377|~\201\377\377\377\377\377\357\362\374\377"
"\377\377\377\377\231\232\234\377\"\"\"\377\352\355\364\377\364\370\377\377"
"\357\362\374\377\357\364\374\377\357\364\374\377\357\364\374\377\357\362"
"\374\377\357\364\374\377\357\364\374\377\357\364\374\377\357\364\374\377"
"\357\362\374\377\357\364\374\377\357\364\374\377\357\364\374\377\357\364"
"\374\377\357\364\374\377\357\364\374\377\357\364\374\377\357\364\374\377"
"\357\364\374\377\357\364\374\377\357\362\374\377\357\364\374\377\360\363"
"\375\377\377\377\377\377|~\201\377\000\000\000\377\000\000\000\345\000\000\000\345\000\000\000\377"
"z|\201\377\377\377\377\377\353\360\374\377\375\377\377\377\230\232\235\377"
"\"\"\"\377\347\352\364\377\360\364\377\377\353\360\374\377\355\360\374\377"
"\355\360\374\377\355\360\374\377\353\360\374\377\355\360\374\377\353\360"
"\374\377\353\360\374\377\353\360\374\377\355\360\374\377\355\360\374\377"
"\355\360\374\377\355\362\374\377\355\360\374\377\353\360\374\377\353\360"
"\374\377\355\360\374\377\353\360\374\377\355\360\374\377\355\360\374\377"
"\355\360\374\377\353\360\374\377\355\362\374\377\377\377\377\377z|\201\377"
"\000\000\000\377\000\000\000\345\000\000\000\345\000\000\000\377y{\201\377\377\377\377\377\351\356"
"\372\377\373\377\377\377\220\223\230\377\026\026\026\377\344\351\363\377\353"
"\362\377\377\350\357\374\377\350\357\372\377\350\357\372\377\350\357\374"
"\377\350\357\374\377\350\357\372\377\350\357\374\377\350\357\372\377\350"
"\357\372\377\350\357\374\377\350\357\374\377\350\357\374\377\350\357\372"
"\377\350\357\372\377\350\357\372\377\350\357\374\377\350\357\374\377\350"
"\357\372\377\350\357\372\377\350\357\372\377\350\357\372\377\350\357\372"
"\377\351\360\373\377\377\377\377\377y{\201\377\000\000\000\377\000\000\000\345\000\000\000"
"\345\000\000\000\377xz\200\377\375\377\377\377\346\354\373\377\352\362\376\377"
"\304\313\325\377\226\233\243\377\343\353\370\377\345\355\374\377\345\355"
"\372\377\345\355\372\377\345\353\372\377\345\353\372\377\345\355\372\377"
"\345\355\372\377\345\353\372\377\345\353\372\377\345\353\372\377\345\355"
"\372\377\345\355\372\377\345\353\372\377\345\353\372\377\345\353\372\377"
"\345\353\372\377\345\353\372\377\345\353\372\377\345\353\372\377\345\353"
"\372\377\345\353\372\377\345\353\372\377\345\353\372\377\344\354\373\377"
"\375\377\377\377xz\200\377\000\000\000\377\000\000\000\345\000\000\000\345\000\000\000\377ux\201"
"\377\373\377\377\377\342\352\373\377\340\350\371\377\350\360\377\377\362"
"\370\377\377\341\351\373\377\341\351\372\377\341\351\372\377\341\351\372"
"\377\341\351\372\377\341\351\372\377\341\351\372\377\341\351\372\377\341"
"\351\372\377\341\351\372\377\341\351\372\377\341\351\372\377\341\351\372"
"\377\341\351\372\377\341\351\372\377\341\351\372\377\341\351\372\377\341"
"\351\372\377\341\351\372\377\341\351\372\377\341\351\372\377\341\351\372"
"\377\341\351\372\377\341\351\372\377\342\352\373\377\373\377\377\377ux\201"
"\377\000\000\000\377\000\000\000\345\000\000\000\345\000\000\000\377ty\200\377\367\375\377\377\336"
"\346\372\377\334\346\372\377\334\346\372\377\334\346\370\377\335\345\371"
"\377\335\345\371\377\335\345\371\377\335\345\371\377\335\345\371\377\335"
"\345\371\377\335\345\371\377\335\345\371\377\335\345\371\377\335\345\371"
"\377\335\345\371\377\335\345\371\377\335\345\371\377\334\346\372\377\335"
"\345\371\377\335\345\371\377\335\345\371\377\335\345\371\377\335\345\371"
"\377\335\345\371\377\335\345\371\377\334\346\372\377\335\345\371\377\335"
"\345\371\377\335\347\373\377\367\375\377\377ty\200\377\000\000\000\377\000\000\000\345"
"\000\000\000\345\000\000\000\377sx\200\377\366\373\377\377\334\344\372\377\331\344\370"
"\377\330\343\371\377\331\344\370\377\330\343\371\377\330\343\371\377\331"
"\344\370\377\331\344\370\377\331\344\370\377\331\344\370\377\330\343\371"
"\377\331\344\370\377\331\344\370\377\331\344\370\377\331\344\370\377\331"
"\344\370\377\330\343\371\377\330\343\371\377\330\343\371\377\331\344\370"
"\377\331\344\370\377\331\344\370\377\330\343\371\377\330\342\371\377\331"
"\344\370\377\331\343\370\377\331\344\370\377\331\343\370\377\334\344\370"
"\377\366\373\377\377sx\200\377\000\000\000\377\000\000\000\345\000\000\000\346\000\000\000\377QV"
"[\377\365\373\377\377\334\346\372\377\325\341\370\377\325\337\370\377\325"
"\341\370\377\325\341\370\377\325\341\370\377\325\341\370\377\325\341\370"
"\377\325\341\370\377\325\341\370\377\325\341\370\377\325\341\370\377\325"
"\341\370\377\325\341\370\377\325\341\370\377\325\341\370\377\325\341\370"
"\377\325\341\370\377\325\341\370\377\325\341\370\377\325\341\370\377\325"
"\341\370\377\325\341\370\377\325\341\370\377\325\341\370\377\325\341\370"
"\377\324\341\370\377\324\341\370\377\334\346\372\377\365\373\377\377PU\\"
"\377\000\000\000\377\000\000\000\346\000\000\000\314\000\000\000\377\012\012\014\377\254\264\301\377"
"\362\370\377\377\325\341\370\377\321\335\367\377\320\335\370\377\320\335"
"\370\377\320\335\370\377\320\335\370\377\320\335\370\377\320\335\370\377"
"\320\335\370\377\320\335\370\377\321\335\367\377\320\335\370\377\320\335"
"\370\377\320\335\370\377\320\335\370\377\320\335\370\377\321\335\367\377"
"\321\335\367\377\320\335\370\377\320\335\370\377\320\335\370\377\320\335"
"\370\377\320\335\370\377\321\335\367\377\320\335\370\377\321\335\367\377"
"\326\340\371\377\362\370\377\377\254\264\301\377\012\012\014\377\000\000\000\377\000"
"\000\000\314\000\000\000d\000\000\000\377\000\000\000\377\024\025\027\377\262\274\314\377\355\365"
"\377\377\323\336\367\377\315\334\366\377\315\334\366\377\314\333\367\377"
"\315\334\366\377\314\333\367\377\314\333\367\377\314\333\367\377\314\333"
"\367\377\316\333\367\377\314\333\367\377\314\333\367\377\315\334\366\377"
"\315\334\366\377\315\334\366\377\316\333\367\377\316\333\367\377\314\333"
"\367\377\314\333\367\377\315\334\366\377\315\334\366\377\314\333\367\377"
"\314\333\367\377\314\333\367\377\323\340\367\377\356\365\377\377\262\274"
"\314\377\024\025\027\377\000\000\000\377\000\000\000\377\000\000\000d\000\000\000\002\000\000\000\220\000\000\000"
"\377\000\000\000\377\025\027\032\377\261\273\315\377\352\362\377\377\317\333\367\377"
"\311\326\366\377\311\330\366\377\311\330\366\377\311\330\366\377\311\330"
"\366\377\311\330\366\377\311\330\366\377\311\330\366\377\311\330\366\377"
"\311\330\366\377\311\330\366\377\311\330\366\377\311\330\366\377\311\330"
"\366\377\311\330\366\377\311\330\366\377\311\330\366\377\311\330\366\377"
"\311\330\366\377\311\330\366\377\311\330\366\377\317\333\367\377\352\362"
"\377\377\261\271\315\377\025\027\032\377\000\000\000\377\000\000\000\377\000\000\000\220\000\000\000"
"\002\000\000\000\000\000\000\000\002\000\000\000\224\000\000\000\377\000\000\000\377\025\030\032\377\257\272\320"
"\377\346\356\377\377\313\330\366\377\305\325\365\377\305\324\365\377\305"
"\324\365\377\305\325\365\377\305\324\365\377\305\324\365\377\305\325\365"
"\377\305\325\365\377\305\324\365\377\305\325\365\377\305\325\365\377\305"
"\324\365\377\305\325\365\377\305\325\365\377\305\325\365\377\305\325\365"
"\377\305\325\365\377\305\324\365\377\305\324\365\377\313\332\366\377\346"
"\356\377\377\257\272\320\377\025\027\032\377\000\000\000\377\000\000\000\377\000\000\000\224\000"
"\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\004\000\000\000\235\000\000\000\377\000\000\000\377\031\032"
"\034\377\267\304\335\377\327\345\377\377\307\326\365\377\302\322\365\377\302"
"\322\365\377\302\322\365\377\302\322\365\377\302\322\365\377\302\322\365"
"\377\302\322\365\377\302\322\365\377\302\322\365\377\302\322\365\377\302"
"\322\365\377\302\322\365\377\302\322\365\377\302\322\365\377\302\322\365"
"\377\302\322\365\377\302\322\365\377\305\326\367\377\327\343\377\377\267"
"\304\335\377\031\032\034\377\000\000\000\377\000\000\000\377\000\000\000\235\000\000\000\004\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\006\000\000\000\241\000\000\000\377\000\000\000\377GJV\377"
"\327\345\377\377\311\330\367\377\275\317\365\377\276\317\365\377\276\320"
"\365\377\276\320\365\377\276\320\365\377\276\320\365\377\276\320\365\377"
"\276\320\365\377\276\320\365\377\276\320\365\377\276\320\365\377\276\320"
"\365\377\276\320\365\377\276\320\365\377\276\320\365\377\276\320\365\377"
"\275\317\365\377\311\330\367\377\326\345\377\377GJV\377\000\000\000\377\000\000\000\377"
"\000\000\000\241\000\000\000\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\011\000\000\000\313\000\000\000\377\015\015\017\377\270\305\341\377\312\334\374"
"\377\271\315\364\377\272\314\364\377\272\316\364\377\272\316\364\377\272"
"\316\364\377\272\316\364\377\272\316\364\377\272\316\364\377\272\316\364"
"\377\272\316\364\377\272\316\364\377\272\316\364\377\272\316\364\377\272"
"\316\364\377\272\316\364\377\272\316\364\377\271\316\364\377\312\334\374"
"\377\270\305\341\377\015\015\017\377\000\000\000\377\000\000\000\313\000\000\000\011\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000s\000\000"
"\000\377\004\004\006\377\254\270\324\377\311\332\376\377\267\313\364\377\270\312"
"\363\377\270\314\363\377\270\314\363\377\270\314\363\377\270\314\363\377"
"\270\312\363\377\270\312\363\377\270\314\363\377\270\314\363\377\270\314"
"\363\377\270\314\363\377\270\312\363\377\270\314\363\377\270\314\363\377"
"\270\314\363\377\267\313\364\377\311\332\376\377\254\270\324\377\004\004\006\377"
"\000\000\000\377\000\000\000s\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000a\000\000\000\377\005\005\007\377\253\270\324\377\306\332"
"\376\377\263\310\363\377\264\311\363\377\264\311\363\377\264\311\363\377"
"\264\311\363\377\264\311\363\377\264\311\364\377\264\311\364\377\264\311"
"\363\377\264\311\363\377\264\311\363\377\264\311\363\377\264\311\363\377"
"\264\311\363\377\264\311\364\377\264\311\364\377\263\310\363\377\306\332"
"\376\377\253\270\324\377\005\005\007\377\000\000\000\377\000\000\000a\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000d\000\000\000\377"
"\005\005\007\377\255\274\332\377\306\330\376\377\261\306\363\377\262\307\362\377"
"\262\307\362\377\262\307\362\377\262\307\362\377\262\307\362\377\262\307"
"\362\377\262\307\362\377\262\307\362\377\262\307\362\377\262\307\362\377"
"\262\307\362\377\262\307\362\377\262\307\362\377\262\307\362\377\262\307"
"\362\377\261\306\363\377\306\330\376\377\255\274\332\377\005\005\007\377\000\000\000"
"\377\000\000\000d\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000W\000\000\000\377\002\002\002\377\205\220\251\377\341\354\377"
"\377\313\333\377\377\311\333\377\377\311\333\377\377\311\333\377\377\311"
"\333\377\377\311\333\377\377\311\333\377\377\311\333\377\377\311\333\377"
"\377\311\333\377\377\310\332\377\377\311\333\377\377\311\333\377\377\311"
"\333\377\377\310\332\377\377\310\332\377\377\313\333\377\377\340\354\377"
"\377\205\220\251\377\002\002\002\377\000\000\000\377\000\000\000W\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\034\000\000\000\354"
"\000\000\000\377\020\022\025\377RZi\377]ev\377Zdt\377Zdt\377[ct\377[ct\377Zdt\377"
"Zdt\377Zdt\377[ct\377[ct\377Zds\377[ct\377[ct\377Zdt\377[cr\377Zds\377]e"
"v\377RZi\377\020\022\025\377\000\000\000\377\000\000\000\354\000\000\000\034\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000f\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377"
"\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000"
"\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000"
"\000\377\000\000\000\377\000\000\000f\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000R\000\000\000\275\000"
"\000\000\344\000\000\000\345\000\000\000\344\000\000\000\344\000\000\000\344\000\000\000\344\000\000\000\344\000\000"
"\000\344\000\000\000\344\000\000\000\344\000\000\000\344\000\000\000\344\000\000\000\344\000\000\000\344\000\000\000"
"\344\000\000\000\344\000\000\000\344\000\000\000\345\000\000\000\344\000\000\000\275\000\000\000R\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
};
static const _GLFWcursorDataOgc OGC_cursor_arrow = {
24, 31, 0, 0, 4,
"\002\002\002\337\000\000\000\224\000\000\000\007\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377"
"\005\005\005\321\000\000\000$\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377ddd\377\037\037\037\373\003\003\003\364"
"\000\000\000V\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\361\361\361\377VVV\376\000\000\000\377"
"\002\002\002\243\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377\377\377\377\377\377\377\241"
"\241\241\377\007\007\007\375\005\005\005\322\000\000\000%\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\315\315\315\377!!!\373\003\003\003\365\000\000\000Y\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\362\362\362\377"
"WWW\376\000\000\000\377\002\002\002\243\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\377\225\225\225\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\241\241\241\377\007\007\007\375\005"
"\005\005\331\000\000\000+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\316\316\316\377!!!\373\003\003\003\365\000\000\000Z"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\362\362\362\377XXX\376\000\000\000\377\002\002\002\243\000\000\000"
"\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\377\225\225\225\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\375\375\377\377\373\374\376\377\235\236\240\377\007\007\007\374\005"
"\005\005\331\000\000\000+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\377\225\225\225\377\377\377\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\375\375\377\377"
"\373\374\376\377\371\373\376\377\367\371\376\377\366\370\375\377\305\310"
"\314\377\037!\"\373\003\003\003\366\000\000\000[\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377\377\377\377\377\377"
"\377\377\377\377\377\377\377\377\377\375\375\377\377\373\374\376\377\371"
"\373\376\377\367\371\376\377\366\370\375\377\364\367\375\377\362\365\375"
"\377\360\364\374\377\342\347\357\377QSW\376\000\000\000\377\002\002\002\243\000\000\000\012"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\225\225\225\377\377\377"
"\377\377\377\377\377\377\375\375\377\377\373\374\376\377\371\373\376\377"
"\367\371\376\377\366\370\375\377\364\367\375\377\362\365\375\377\360\364"
"\374\377\356\363\374\377\354\362\374\377\353\360\374\377\351\357\373\377"
"\222\226\236\377\007\007\007\374\004\005\005\331\000\000\000+\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\377\225\225\225\377\375\375\377\377\373\374\376\377\371\373\376"
"\377\367\371\376\377\366\370\375\377\364\367\375\377\362\365\375\377\360"
"\364\374\377\356\363\374\377\354\362\374\377\353\360\374\377\351\357\373"
"\377\347\356\373\377\345\354\373\377\343\353\372\377\275\303\321\377#%'\373"
"\003\003\003\366\000\000\000[\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\223\223\224\377\371\373"
"\376\377\367\371\376\377\366\370\375\377\364\367\375\377\362\365\375\377"
"\360\364\374\377\356\363\374\377\354\362\374\377\353\360\374\377\351\357"
"\373\377\347\356\373\377\345\354\373\377\343\353\372\377\342\352\372\377"
"\340\350\372\377\336\347\371\377\321\332\354\377LOW\376\000\000\000\377\002\002\002\243"
"\000\000\000\012\000\000\000\000\000\000\000\377\220\221\224\377\366\370\375\377\364\367\375\377"
"\362\365\375\377\360\364\374\377\356\363\374\377\354\362\374\377\353\360"
"\374\377\351\357\373\377\347\356\373\377\345\354\373\377\343\353\372\377"
"\342\352\372\377\340\350\372\377\336\347\371\377\334\346\371\377\332\344"
"\371\377\330\343\370\377\327\342\370\377\206\215\235\377\006\006\007\374\004\004\005"
"\332\000\000\000,\000\000\000\377\217\220\224\377\362\365\375\377\360\364\374\377\356"
"\363\374\377\354\361\374\377\353\360\374\377\351\357\373\377\347\356\373"
"\377\345\354\373\377\343\353\372\377\342\352\372\377\340\350\372\377\336"
"\347\371\377\334\346\371\377\332\344\371\377\330\343\370\377\327\342\370"
"\377\325\340\370\377\323\337\370\377\321\336\367\377pw\206\377\000\000\000\377"
"\001\001\001\347\000\000\000\377\214\217\223\377\356\363\374\377\354\361\374\377\353"
"\360\374\377\351\357\373\377\347\356\373\377\345\354\373\377\343\353\372"
"\377\342\352\372\377\340\350\372\377\336\347\371\377\334\346\371\377\332"
"\344\371\377\330\343\370\377\327\342\370\377\325\340\370\377\323\337\370"
"\377\321\336\367\377\225\236\261\377,/\065\374\000\000\000\377\004\004\005\316\000\000\000F"
"\000\000\000\377\212\215\223\377\353\360\374\377\351\357\373\377\347\356\373\377"
"\345\354\373\377\343\353\372\377\342\352\372\377\340\350\372\377\336\347"
"\371\377\334\346\371\377\332\344\371\377\330\343\370\377\327\342\370\377"
"\325\340\370\377\323\337\370\377\321\336\367\377\236\250\275\377\062\065<\374"
"\000\000\000\377\002\004\004\323\000\000\000U\000\000\000\001\000\000\000\000\000\000\000\377\210\214\223\377\347"
"\356\373\377\345\354\373\377\343\353\372\377\342\352\372\377\340\350\372"
"\377\336\347\371\377\334\346\371\377\332\344\371\377\330\343\370\377\327"
"\342\370\377\325\340\370\377\323\337\370\377\321\336\367\377\230\241\265"
"\377,/\064\374\000\000\000\377\002\004\004\323\000\000\000U\000\000\000\001\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\377\206\212\223\377\343\353\372\377\341\352\372\377\340\350\372\377"
"\336\347\371\377\334\346\371\377\332\344\371\377\330\343\370\377\327\342"
"\370\377\325\340\370\377\323\337\370\377\321\336\367\377\317\334\367\377"
"DHQ\374\000\000\000\377\004\004\004\314\000\000\000J\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\377\203\211\222\377\340\350\372\377\336\347\371\377\334"
"\346\371\377\332\344\371\377\330\343\370\377\327\342\370\377\325\340\370"
"\377\323\337\370\377\321\336\367\377\317\334\367\377\315\333\367\377\314"
"\332\366\377JOZ\376\002\002\003\362\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\202\207\221\377\334\346\371\377\332\344"
"\371\377\330\343\370\377\327\342\370\377\325\340\370\377\323\337\370\377"
"\321\336\367\377\316\333\366\377\315\333\367\377\314\332\366\377\312\330"
"\366\377\310\327\366\377\250\266\320\377\002\002\002\376\000\000\000r\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\177\205\221\377\330\343"
"\370\377\327\342\370\377\325\340\370\377\323\337\370\377\321\336\367\377"
"\223\234\257\377),\062\374\036\040$\374\306\324\361\377\310\327\366\377\306"
"\326\365\377\304\324\365\377\303\323\365\377FLX\376\003\003\004\354\000\000\000\012\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377~\204\221\377\325"
"\340\370\377\323\337\370\377\321\336\367\377\222\233\256\377)-\063\374\000\000"
"\000\377\002\004\004\321\000\000\000\376y\203\226\377\304\324\365\377\303\323\365\377\301"
"\322\364\377\277\320\364\377\242\261\321\377\001\002\002\376\000\000\000s\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377{\202\221\377\321\336\367\377"
"\222\233\256\377),\062\374\000\000\000\377\004\004\005\313\000\000\000I\000\000\000\000\001\001\003\263\026"
"\030\034\373\275\316\357\377\277\320\364\377\275\317\364\377\273\316\364\377"
"\271\314\363\377CJY\376\003\003\004\354\000\000\000\012\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\377INW\377)+\061\373\000\000\000\377\004\004\004\312\000\000\000H\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\062\000\000\000\376t\177\225\377\273\316\364\377\271\314\363"
"\377\270\313\363\377\212\232\271\377(,\066\375\000\000\000\377\000\000\000F\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\004\004\004\311\000\000\000H\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001\003\003\262\025\027\034\373\264\307"
"\356\377\212\232\271\377.\063>\374\000\000\000\377\004\004\005\330\000\000\000V\000\000\000\001\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000t\000\000\000G\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\062\000\000\000\376\032\035$\375"
"\000\000\000\377\004\004\005\327\000\000\000V\000\000\000\002\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\002\003\003\247\004\004\005\325\000\000\000U\000\000\000\002\000\000"
"\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",
};

161
src/ogc_init.c Normal file
View File

@ -0,0 +1,161 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(_GLFW_OGC)
#include <assert.h>
#include <fat.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiikeyboard/keyboard.h>
#include <wiiuse/wpad.h>
#define FIFO_SIZE (256*1024)
char _glfwUnimplementedFmt[] = "Ogc: the platform does not support %s";
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwConnectOgc(int platformID, _GLFWplatform* platform)
{
const _GLFWplatform ogc =
{
.platformID = GLFW_PLATFORM_OGC,
.init = _glfwInitOgc,
.terminate = _glfwTerminateOgc,
.getCursorPos = _glfwGetCursorPosOgc,
.setCursorPos = _glfwSetCursorPosOgc,
.setCursorMode = _glfwSetCursorModeOgc,
.setRawMouseMotion = _glfwSetRawMouseMotionOgc,
.rawMouseMotionSupported = _glfwRawMouseMotionSupportedOgc,
.createCursor = _glfwCreateCursorOgc,
.createStandardCursor = _glfwCreateStandardCursorOgc,
.destroyCursor = _glfwDestroyCursorOgc,
.setCursor = _glfwSetCursorOgc,
.getScancodeName = _glfwGetScancodeNameOgc,
.getKeyScancode = _glfwGetKeyScancodeOgc,
.setClipboardString = _glfwSetClipboardStringOgc,
.getClipboardString = _glfwGetClipboardStringOgc,
.initJoysticks = _glfwInitJoysticksOgc,
.terminateJoysticks = _glfwTerminateJoysticksOgc,
.pollJoystick = _glfwPollJoystickOgc,
.getMappingName = _glfwGetMappingNameOgc,
.updateGamepadGUID = _glfwUpdateGamepadGUIDOgc,
.freeMonitor = _glfwFreeMonitorOgc,
.getMonitorPos = _glfwGetMonitorPosOgc,
.getMonitorContentScale = _glfwGetMonitorContentScaleOgc,
.getMonitorWorkarea = _glfwGetMonitorWorkareaOgc,
.getVideoModes = _glfwGetVideoModesOgc,
.getVideoMode = _glfwGetVideoModeOgc,
.getGammaRamp = _glfwGetGammaRampOgc,
.setGammaRamp = _glfwSetGammaRampOgc,
.createWindow = _glfwCreateWindowOgc,
.destroyWindow = _glfwDestroyWindowOgc,
.setWindowTitle = _glfwSetWindowTitleOgc,
.setWindowIcon = _glfwSetWindowIconOgc,
.getWindowPos = _glfwGetWindowPosOgc,
.setWindowPos = _glfwSetWindowPosOgc,
.getWindowSize = _glfwGetWindowSizeOgc,
.setWindowSize = _glfwSetWindowSizeOgc,
.setWindowSizeLimits = _glfwSetWindowSizeLimitsOgc,
.setWindowAspectRatio = _glfwSetWindowAspectRatioOgc,
.getFramebufferSize = _glfwGetFramebufferSizeOgc,
.getWindowFrameSize = _glfwGetWindowFrameSizeOgc,
.getWindowContentScale = _glfwGetWindowContentScaleOgc,
.iconifyWindow = _glfwIconifyWindowOgc,
.restoreWindow = _glfwRestoreWindowOgc,
.maximizeWindow = _glfwMaximizeWindowOgc,
.showWindow = _glfwShowWindowOgc,
.hideWindow = _glfwHideWindowOgc,
.requestWindowAttention = _glfwRequestWindowAttentionOgc,
.focusWindow = _glfwFocusWindowOgc,
.setWindowMonitor = _glfwSetWindowMonitorOgc,
.windowFocused = _glfwWindowFocusedOgc,
.windowIconified = _glfwWindowIconifiedOgc,
.windowVisible = _glfwWindowVisibleOgc,
.windowMaximized = _glfwWindowMaximizedOgc,
.windowHovered = _glfwWindowHoveredOgc,
.framebufferTransparent = _glfwFramebufferTransparentOgc,
.getWindowOpacity = _glfwGetWindowOpacityOgc,
.setWindowResizable = _glfwSetWindowResizableOgc,
.setWindowDecorated = _glfwSetWindowDecoratedOgc,
.setWindowFloating = _glfwSetWindowFloatingOgc,
.setWindowOpacity = _glfwSetWindowOpacityOgc,
.setWindowMousePassthrough = _glfwSetWindowMousePassthroughOgc,
.pollEvents = _glfwPollEventsOgc,
.waitEvents = _glfwWaitEventsOgc,
.waitEventsTimeout = _glfwWaitEventsTimeoutOgc,
.postEmptyEvent = _glfwPostEmptyEventOgc,
.getEGLPlatform = _glfwGetEGLPlatformOgc,
.getEGLNativeDisplay = _glfwGetEGLNativeDisplayOgc,
.getEGLNativeWindow = _glfwGetEGLNativeWindowOgc,
.getRequiredInstanceExtensions = _glfwGetRequiredInstanceExtensionsOgc,
.getPhysicalDevicePresentationSupport = _glfwGetPhysicalDevicePresentationSupportOgc,
.createWindowSurface = _glfwCreateWindowSurfaceOgc
};
*platform = ogc;
return GLFW_TRUE;
}
int _glfwInitOgc(void)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__);
VIDEO_Init();
void *fifoBuffer = MEM_K0_TO_K1(memalign(32, FIFO_SIZE));
memset(fifoBuffer, 0, FIFO_SIZE);
GX_Init(fifoBuffer, FIFO_SIZE);
fatInitDefault();
PAD_Init();
KEYBOARD_Init(NULL);
#ifdef __wii__
WPAD_Init();
WPAD_SetDataFormat(WPAD_CHAN_ALL, WPAD_FMT_BTNS_ACC_IR);
WPAD_SetVRes(WPAD_CHAN_ALL, 640, 480);
#endif
_glfwCreateMonitorOgc();
return GLFW_TRUE;
}
void _glfwTerminateOgc(void)
{
_glfwTerminateEGL();
_glfwTerminateOSMesa();
}
#endif // _GLFW_OGC

417
src/ogc_joystick.c Normal file
View File

@ -0,0 +1,417 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(_GLFW_OGC)
#include <ogc/lwp_watchdog.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __wii__
#include <wiiuse/wpad.h>
#endif
#define MAX_FAILED_GC_READS 10
#define MAX_GC_AXES 6
#define MAX_GC_BUTTONS 8
#define MAX_GC_HATS 1
/* PAD_ScanPads() returns 0 if no joystick is connected, but also if querying
* the hardware failed for whatever reason. This can occasionally happen at
* runtime; so, we want to ignore these events and only report the joystick
* disconnection if PAD_ScanPads() consistently returns 0.
*
* This function returns true if the scanPads value is reliable.
*/
static GLFWbool readGCJoysticks(u32 *scanPads)
{
static GLFWbool lastReadFailed = GLFW_FALSE;
static u64 firstDisconnectedTimestamp = 0;
u32 currScanPads;
u64 timestamp;
currScanPads = PAD_ScanPads();
if (currScanPads == 0) {
timestamp = gettime();
if (lastReadFailed) {
if (ticks_to_millisecs(timestamp - firstDisconnectedTimestamp) < 500)
return GLFW_FALSE;
} else {
firstDisconnectedTimestamp = timestamp;
lastReadFailed = GLFW_TRUE;
return GLFW_FALSE;
}
} else {
lastReadFailed = GLFW_FALSE;
}
*scanPads = currScanPads;
return GLFW_TRUE;
}
static void readGCJoystick(_GLFWjoystick* js)
{
u32 id = js->ogc.id;
u16 btns = PAD_ButtonsHeld(id);
js->buttons[0] = btns & PAD_BUTTON_A ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[1] = btns & PAD_BUTTON_B ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[2] = btns & PAD_BUTTON_X ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[3] = btns & PAD_BUTTON_Y ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[4] = btns & PAD_TRIGGER_L ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[5] = btns & PAD_TRIGGER_R ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[6] = btns & PAD_TRIGGER_Z ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[7] = btns & PAD_BUTTON_START ? GLFW_PRESS : GLFW_RELEASE;
js->axes[0] = PAD_StickX(id) / 100.0;
js->axes[1] = PAD_StickY(id) / 100.0;
js->axes[2] = PAD_SubStickX(id) / 100.0;
js->axes[3] = PAD_SubStickY(id) / 100.0;
js->axes[4] = PAD_TriggerL(id) / 200.0;
js->axes[5] = PAD_TriggerR(id) / 200.0;
unsigned char hat = 0;
if (btns & PAD_BUTTON_UP) hat |= GLFW_HAT_UP;
if (btns & PAD_BUTTON_DOWN) hat |= GLFW_HAT_DOWN;
if (btns & PAD_BUTTON_LEFT) hat |= GLFW_HAT_LEFT;
if (btns & PAD_BUTTON_RIGHT) hat |= GLFW_HAT_RIGHT;
_glfwInputJoystickHat(js, 0, hat);
}
/* CRC algorithm used by SDL */
static uint16_t crc16_for_byte(uint8_t r)
{
uint16_t crc = 0;
int i;
for (i = 0; i < 8; ++i) {
crc = ((crc ^ r) & 1 ? 0xA001 : 0) ^ crc >> 1;
r >>= 1;
}
return crc;
}
uint16_t SDL_crc16(uint16_t crc, const void *data, size_t len)
{
/* As an optimization we can precalculate a 256 entry table for each byte */
size_t i;
for (i = 0; i < len; ++i) {
crc = crc16_for_byte((uint8_t)crc ^ ((const uint8_t *)data)[i]) ^ crc >> 8;
}
return crc;
}
static _GLFWjoystick* addJoystick(int deviceId,
const char *name, const char* guid,
int axisCount, int buttonCount, int hatCount)
{
fprintf(stderr, "Add controller %d %s\n", deviceId, name);
_GLFWjoystick* js =
_glfwAllocJoystick(name, guid,
axisCount, buttonCount, hatCount);
js->ogc.id = deviceId;
_glfw.ogcjs.joystickIndex[deviceId] = js - _glfw.joysticks;
_glfwInputJoystick(js, GLFW_CONNECTED);
return js;
}
static void addGCJoystick(int deviceId)
{
char name[16], guid[33];
uint16_t nameCrc;
sprintf(name, "Gamecube %d", deviceId);
nameCrc = SDL_crc16(0, name, strlen(name));
sprintf(guid, "0000%02x%02x7e050000000%d000001000000",
nameCrc & 0xff, nameCrc >> 8, deviceId + 1);
addJoystick(deviceId, name, guid,
MAX_GC_AXES, MAX_GC_BUTTONS, MAX_GC_HATS);
}
#ifdef __wii__
static inline float readAxis(uint8_t pos, uint8_t center, uint8_t min, uint8_t max)
{
if (pos < center) {
return (pos - center) / (float)(center - min);
} else {
return (pos - center) / (float)(max - center);
}
}
static void readJoystickAxes(_GLFWjoystick* js, int index, const joystick_t *data)
{
js->axes[index] = readAxis(data->pos.x, data->center.x, data->min.x, data->max.x);
js->axes[index + 1] = readAxis(data->pos.y, data->center.y, data->min.y, data->max.y);
}
static inline float clampUnity(float value)
{
if (value < -1.0f) return -1.0f;
if (value > 1.0f) return 1.0f;
return value;
}
static void readOrientationAxes(_GLFWjoystick* js, int index, const orient_t *data)
{
/* Orientation fields range from -180 to 180 (they are measured in
* degrees), but in order to use them as joystick axes it's more reasonable
* to limit their range to -90/90. */
js->axes[index] = clampUnity(-data->pitch / 90.0f);
js->axes[index + 1] = clampUnity(data->roll / 90.0f);
js->axes[index + 2] = clampUnity(data->yaw / 90.0f);
}
static void readWiimote(_GLFWjoystick* js)
{
u32 id = js->ogc.id - MAX_GC_JOYSTICKS;
WPADData *data = WPAD_Data(id);
u32 btns = data->btns_h | data->btns_d;
unsigned char hat = 0;
GLFWbool readWiimote = GLFW_FALSE;
GLFWbool wiimotePointer = GLFW_FALSE;
int wiimoteFirstAxis = 0;
if (js->ogc.expansion == EXP_NUNCHUK) {
js->buttons[7] = btns & WPAD_NUNCHUK_BUTTON_Z ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[8] = btns & WPAD_NUNCHUK_BUTTON_C ? GLFW_PRESS : GLFW_RELEASE;
/* When a nunchuk is connected, we report its joystick as the first two axes,
* followed by three axes from the wiimote orientation, followed by
* three axes from the nunchuk orientation. */
readJoystickAxes(js, 0, &data->exp.nunchuk.js);
readWiimote = GLFW_TRUE;
wiimotePointer = GLFW_TRUE;
wiimoteFirstAxis = 2;
readOrientationAxes(js, wiimoteFirstAxis + 3, &data->exp.nunchuk.orient);
} else if (js->ogc.expansion == EXP_CLASSIC) {
if (btns & WPAD_CLASSIC_BUTTON_LEFT) hat |= GLFW_HAT_LEFT;
if (btns & WPAD_CLASSIC_BUTTON_RIGHT) hat |= GLFW_HAT_RIGHT;
if (btns & WPAD_CLASSIC_BUTTON_UP) hat |= GLFW_HAT_UP;
if (btns & WPAD_CLASSIC_BUTTON_DOWN) hat |= GLFW_HAT_DOWN;
js->buttons[0] = btns & WPAD_CLASSIC_BUTTON_A ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[1] = btns & WPAD_CLASSIC_BUTTON_B ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[2] = btns & WPAD_CLASSIC_BUTTON_X ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[3] = btns & WPAD_CLASSIC_BUTTON_Y ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[4] = btns & WPAD_CLASSIC_BUTTON_FULL_L ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[5] = btns & WPAD_CLASSIC_BUTTON_FULL_R ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[6] = btns & WPAD_CLASSIC_BUTTON_ZL ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[7] = btns & WPAD_CLASSIC_BUTTON_ZR ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[8] = btns & WPAD_CLASSIC_BUTTON_MINUS ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[9] = btns & WPAD_CLASSIC_BUTTON_PLUS ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[10] = btns & WPAD_CLASSIC_BUTTON_HOME ? GLFW_PRESS : GLFW_RELEASE;
readJoystickAxes(js, 0, &data->exp.classic.ljs);
readJoystickAxes(js, 2, &data->exp.classic.rjs);
} else if (js->ogc.expansion == EXP_NONE) {
readWiimote = GLFW_TRUE;
wiimotePointer = data->ir.valid;
}
if (readWiimote) {
if (wiimotePointer) {
if (btns & WPAD_BUTTON_LEFT) hat |= GLFW_HAT_LEFT;
if (btns & WPAD_BUTTON_RIGHT) hat |= GLFW_HAT_RIGHT;
if (btns & WPAD_BUTTON_UP) hat |= GLFW_HAT_UP;
if (btns & WPAD_BUTTON_DOWN) hat |= GLFW_HAT_DOWN;
} else {
if (btns & WPAD_BUTTON_LEFT) hat |= GLFW_HAT_DOWN;
if (btns & WPAD_BUTTON_RIGHT) hat |= GLFW_HAT_UP;
if (btns & WPAD_BUTTON_UP) hat |= GLFW_HAT_LEFT;
if (btns & WPAD_BUTTON_DOWN) hat |= GLFW_HAT_RIGHT;
}
js->buttons[0] = btns & WPAD_BUTTON_1 ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[1] = btns & WPAD_BUTTON_2 ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[2] = btns & WPAD_BUTTON_A ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[3] = btns & WPAD_BUTTON_B ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[4] = btns & WPAD_BUTTON_MINUS ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[5] = btns & WPAD_BUTTON_PLUS ? GLFW_PRESS : GLFW_RELEASE;
js->buttons[6] = btns & WPAD_BUTTON_HOME ? GLFW_PRESS : GLFW_RELEASE;
readOrientationAxes(js, wiimoteFirstAxis, &data->orient);
}
_glfwInputJoystickHat(js, 0, hat);
/* On the Wii, let's close the window when the HOME button is pressed,
* since that's the default behaviour for homebrew applications. The close
* event can anyway be overridden in the application, if this behaviour is
* not desired. */
if (btns & WPAD_BUTTON_HOME && _glfw.windowListHead) {
_glfwInputWindowCloseRequest(_glfw.windowListHead);
}
}
static void addWiimote(int deviceId, uint8_t expansion)
{
char name[64], guid[40];
uint16_t nameCrc;
int axisCount, buttonCount, hatCount;
/* These counters are for the bare Wiimote */
axisCount = 3;
buttonCount = 7;
hatCount = 1;
char *name_ptr = name;
name_ptr += sprintf(name_ptr, "Wiimote %d", deviceId - MAX_GC_JOYSTICKS);
switch (expansion) {
case WPAD_EXP_NUNCHUK:
strcpy(name_ptr, " + Nunchuk");
axisCount += 5;
buttonCount += 2;
break;
case WPAD_EXP_CLASSIC:
strcpy(name_ptr, " + Classic");
axisCount = 4;
buttonCount = 11;
hatCount = 1;
break;
case WPAD_EXP_GUITARHERO3:
strcpy(name_ptr, " + Guitar Hero 3");
break;
case WPAD_EXP_WIIBOARD:
strcpy(name_ptr, " + Balance board");
break;
}
nameCrc = SDL_crc16(0, name, strlen(name));
sprintf(guid, "0500%02x%02x7e0500000%d0%d000001000000",
nameCrc & 0xff, nameCrc >> 8, expansion + 1, deviceId + 1);
_GLFWjoystick *js = addJoystick(deviceId, name, guid,
axisCount, buttonCount, hatCount);
js->ogc.expansion = expansion;
}
#endif /* __wii__ */
static void removeJoystick(int deviceId)
{
_GLFWjoystick* js = JOYSTICK_FROM_DEVICE(deviceId);
_glfwInputJoystick(js, GLFW_DISCONNECTED);
_glfwFreeJoystick(js);
_glfw.ogcjs.joystickIndex[deviceId] = -1;
fprintf(stderr, "Removed controller %d\n", deviceId);
}
static GLFWbool updateJoysticks()
{
u32 scanPads = 0;
if (_glfw.joysticksInitialized && readGCJoysticks(&scanPads)) {
for (int i = 0; i < MAX_GC_JOYSTICKS; i++) {
GLFWbool connected = !!(scanPads & (1 << i));
int joystickIndex = JOYSTICK_INDEX_FROM_DEVICE(i);
GLFWbool wasConnected = joystickIndex >= 0 ?
_glfw.joysticks[joystickIndex].connected : GLFW_FALSE;
if (connected != wasConnected) {
if (connected) {
addGCJoystick(i);
joystickIndex = JOYSTICK_INDEX_FROM_DEVICE(i);
} else {
removeJoystick(i);
}
}
if (connected)
readGCJoystick(&_glfw.joysticks[joystickIndex]);
}
}
#ifdef __wii__
/* The WPAD data is also used for the mouse, so we read it even if
* joysticks haven't been initialized */
WPAD_ReadPending(WPAD_CHAN_ALL, NULL);
if (_glfw.joysticksInitialized) {
for (int i = 0; i < MAX_WIIMOTES; i++) {
int deviceId = i + MAX_GC_JOYSTICKS;
int joystickIndex = JOYSTICK_INDEX_FROM_DEVICE(deviceId);
WPADData *data = WPAD_Data(i);
/* Ignore all reads where an error occurred */
if (data->err != WPAD_ERR_NONE) continue;
GLFWbool connected = data->data_present != 0;
uint8_t expansion = data->data_present & WPAD_DATA_EXPANSION ?
data->exp.type : EXP_NONE;
GLFWbool wasConnected = joystickIndex >= 0 ?
_glfw.joysticks[joystickIndex].connected : GLFW_FALSE;
uint8_t hadExpansion = joystickIndex >= 0 ?
_glfw.joysticks[joystickIndex].ogc.expansion : EXP_NONE;
if (connected != wasConnected || expansion != hadExpansion) {
if (wasConnected) {
removeJoystick(deviceId);
}
if (connected) {
addWiimote(deviceId, expansion);
joystickIndex = JOYSTICK_INDEX_FROM_DEVICE(deviceId);
}
}
if (connected)
readWiimote(&_glfw.joysticks[joystickIndex]);
}
}
#endif
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPollJoysticksOgc(void)
{
return updateJoysticks();
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwInitJoysticksOgc(void)
{
/* Hardware initialization done in ogc_init.c, since we want it to happen
* ASAP */
for (int i = 0; i < MAX_JOYSTICKS; i++) {
_glfw.ogcjs.joystickIndex[i] = -1;
}
return GLFW_TRUE;
}
void _glfwTerminateJoysticksOgc(void)
{
// TODO
}
GLFWbool _glfwPollJoystickOgc(_GLFWjoystick* js, int mode)
{
updateJoysticks();
return js->connected;
}
const char* _glfwGetMappingNameOgc(void)
{
return "Ogc";
}
void _glfwUpdateGamepadGUIDOgc(char* guid)
{
}
#endif // _GLFW_OGC

64
src/ogc_joystick.h Normal file
View File

@ -0,0 +1,64 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// 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.
//
//========================================================================
#define GLFW_OGC_JOYSTICK_STATE _GLFWjoystickOgc ogc;
#define GLFW_OGC_LIBRARY_JOYSTICK_STATE _GLFWlibraryJoystickOgc ogcjs;
#define MAX_GC_JOYSTICKS 4
#ifdef __wii__
#define MAX_WIIMOTES 4
#else
#define MAX_WIIMOTES 0
#endif
#define MAX_JOYSTICKS (MAX_GC_JOYSTICKS + MAX_WIIMOTES)
// Ogc-specific joystick data
//
typedef struct _GLFWjoystickOgc
{
int id;
uint8_t expansion;
} _GLFWjoystickOgc;
typedef struct _GLFWlibraryJoystickOgc
{
char joystickIndex[MAX_JOYSTICKS];
} _GLFWlibraryJoystickOgc;
#define JOYSTICK_INDEX_FROM_DEVICE(deviceId) \
((int)_glfw.ogcjs.joystickIndex[deviceId])
#define JOYSTICK_FROM_DEVICE(deviceId) \
(&_glfw.joysticks[JOYSTICK_INDEX_FROM_DEVICE(deviceId)])
GLFWbool _glfwPollJoysticksOgc(void);
GLFWbool _glfwInitJoysticksOgc(void);
void _glfwTerminateJoysticksOgc(void);
GLFWbool _glfwPollJoystickOgc(_GLFWjoystick* js, int mode);
const char* _glfwGetMappingNameOgc(void);
void _glfwUpdateGamepadGUIDOgc(char* guid);

50
src/ogc_module.c Normal file
View File

@ -0,0 +1,50 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(GLFW_BUILD_OGC_MODULE)
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void* _glfwPlatformLoadModule(const char* path)
{
return NULL;
}
void _glfwPlatformFreeModule(void* module)
{
}
GLFWproc _glfwPlatformGetModuleSymbol(void* module, const char* name)
{
return NULL;
}
#endif // GLFW_BUILD_OGC_MODULE

248
src/ogc_monitor.c Normal file
View File

@ -0,0 +1,248 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(_GLFW_OGC)
#include <ogc/color.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_OGC_MODES 4 /* - VIDEO_GetPreferredMode()
- 240p progressive mode
- 480p progressive mode
- 528p PAL progressive mode
*/
static GXRModeObj *s_videoModes[MAX_OGC_MODES + 1]; // +1 for the NULL entry
// Inverse of the VI_TVMODE macro
#define VI_FORMAT_FROM_MODE(tvmode) (tvmode >> 2)
static void setupXfb(_GLFWmonitor* monitor)
{
if (_glfw.ogc.xfb[0]) {
free(MEM_K1_TO_K0(_glfw.ogc.xfb[0]));
_glfw.ogc.xfb[0] = NULL;
}
if (_glfw.ogc.xfb[1]) {
free(MEM_K1_TO_K0(_glfw.ogc.xfb[1]));
_glfw.ogc.xfb[1] = NULL;
}
if (!_glfw.ogc.xfb[0]) {
_glfw.ogc.xfb[0] =
MEM_K0_TO_K1(SYS_AllocateFramebuffer(monitor->ogc.ogcMode));
}
if (monitor->window && monitor->window->doublebuffer) {
_glfw.ogc.xfb[1] =
MEM_K0_TO_K1(SYS_AllocateFramebuffer(monitor->ogc.ogcMode));
}
_glfw.ogc.fbIndex = 0;
}
static void ogcVideoModeToGlfw(const GXRModeObj *in, GLFWvidmode *out)
{
out->width = in->fbWidth;
out->height = in->efbHeight;
out->redBits = out->greenBits = out->blueBits = 8;
u32 format = VI_FORMAT_FROM_MODE(in->viTVMode);
switch (format) {
case VI_DEBUG:
case VI_NTSC:
case VI_EURGB60:
case VI_MPAL:
out->refreshRate = 60;
break;
case VI_PAL:
case VI_DEBUG_PAL:
out->refreshRate = 50;
break;
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
void _glfwCreateMonitorOgc()
{
_GLFWmonitor* monitor = _glfwAllocMonitor("", 0, 0);
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_FIRST);
}
void _glfwSetVideoModeOgc(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{
int i;
const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
fprintf(stderr, "%s:%d %s chosen %dx%d window %p\n", __FILE__, __LINE__, __func__,
best->width, best->height, monitor->window);
for (i = 0; i < monitor->modeCount; i++) {
GLFWvidmode tmp;
ogcVideoModeToGlfw(s_videoModes[i], &tmp);
if (_glfwCompareVideoModes(best, &tmp) == 0)
break;
}
/* In the unlikely case that this is not one of our modes, just pick our
* preferred one */
if (i >= monitor->modeCount) i = 0;
GXRModeObj *vmode = s_videoModes[i];
monitor->ogc.currentMode = i;
monitor->ogc.ogcMode = vmode;
setupXfb(monitor);
VIDEO_Configure(vmode);
VIDEO_ClearFrameBuffer(vmode, _glfw.ogc.xfb[0], COLOR_BLACK);
VIDEO_SetNextFramebuffer(_glfw.ogc.xfb[0]);
VIDEO_SetBlack(FALSE);
VIDEO_Flush();
VIDEO_WaitVSync();
if (vmode->viTVMode & VI_NON_INTERLACE) VIDEO_WaitVSync();
float yscale = GX_GetYScaleFactor(vmode->efbHeight, vmode->xfbHeight);
GX_SetDispCopyYScale(yscale);
GX_SetDispCopySrc(0, 0, vmode->fbWidth, vmode->efbHeight);
GX_SetDispCopyDst(vmode->fbWidth, vmode->xfbHeight);
GX_SetCopyFilter(vmode->aa, vmode->sample_pattern, GX_TRUE, vmode->vfilter);
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwFreeMonitorOgc(_GLFWmonitor* monitor)
{
}
void _glfwGetMonitorPosOgc(_GLFWmonitor* monitor, int* xpos, int* ypos)
{
if (xpos)
*xpos = 0;
if (ypos)
*ypos = 0;
}
void _glfwGetMonitorContentScaleOgc(_GLFWmonitor* monitor,
float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.0f;
if (yscale)
*yscale = 1.0f;
}
void _glfwGetMonitorWorkareaOgc(_GLFWmonitor* monitor,
int* xpos, int* ypos,
int* width, int* height)
{
if (xpos)
*xpos = 0;
if (ypos)
*ypos = 0;
if (width)
*width = monitor->modes[monitor->ogc.currentMode].width;
if (height)
*height = monitor->modes[monitor->ogc.currentMode].height;
}
GLFWvidmode* _glfwGetVideoModesOgc(_GLFWmonitor* monitor, int* found)
{
int i, count;
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__);
i = 0;
s_videoModes[i++] = VIDEO_GetPreferredMode(NULL);
/* Add more video modes, depending on the TV mode of the preferred mode
* (NTSC, PAL, etc.) */
switch (VI_FORMAT_FROM_MODE(s_videoModes[0]->viTVMode))
{
case VI_DEBUG:
case VI_NTSC:
s_videoModes[i++] = &TVNtsc240Ds;
s_videoModes[i++] = &TVNtsc480Prog;
break;
case VI_MPAL:
s_videoModes[i++] = &TVMpal240Ds;
s_videoModes[i++] = &TVMpal480Prog;
break;
case VI_EURGB60:
s_videoModes[i++] = &TVEurgb60Hz240Ds;
s_videoModes[i++] = &TVEurgb60Hz480Prog;
s_videoModes[i++] = &TVPal528Prog;
break;
case VI_PAL:
case VI_DEBUG_PAL:
s_videoModes[i++] = &TVPal264Ds;
s_videoModes[i++] = &TVPal576ProgScale; // EFB height is 480
s_videoModes[i++] = &TVPal528Prog;
break;
default:
return NULL;
}
s_videoModes[i] = NULL;
GLFWvidmode* modes = _glfw_calloc(i, sizeof(GLFWvidmode));
count = i;
for (int i = 0; i < count; i++)
{
ogcVideoModeToGlfw(s_videoModes[i], &modes[i]);
}
*found = count;
return modes;
}
GLFWbool _glfwGetVideoModeOgc(_GLFWmonitor* monitor, GLFWvidmode* mode)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__);
*mode = monitor->modes[monitor->ogc.currentMode];
return GLFW_TRUE;
}
GLFWbool _glfwGetGammaRampOgc(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"gamma ramp");
return GLFW_FALSE;
}
void _glfwSetGammaRampOgc(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"gamma ramp");
}
#endif // _GLFW_OGC

252
src/ogc_platform.h Normal file
View File

@ -0,0 +1,252 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <ogc/gx.h>
#include <ogc/system.h>
#include <ogc/video.h>
#define GLFW_OGC_WINDOW_STATE _GLFWwindowOgc ogc;
#define GLFW_OGC_LIBRARY_WINDOW_STATE _GLFWlibraryOgc ogc;
#define GLFW_OGC_MONITOR_STATE _GLFWmonitorOgc ogc;
#define GLFW_OGC_CURSOR_STATE _GLFWcursorOgc ogc;
extern char _glfwUnimplementedFmt[];
#if 0
typedef struct ogc_cursor_theme* (* PFN_ogc_cursor_theme_load)(const char*, int, struct ogc_shm*);
typedef void (* PFN_ogc_cursor_theme_destroy)(struct ogc_cursor_theme*);
typedef struct ogc_cursor* (* PFN_ogc_cursor_theme_get_cursor)(struct ogc_cursor_theme*, const char*);
typedef struct ogc_buffer* (* PFN_ogc_cursor_image_get_buffer)(struct ogc_cursor_image*);
#define ogc_cursor_theme_load _glfw.ogc.cursor.theme_load
#define ogc_cursor_theme_destroy _glfw.ogc.cursor.theme_destroy
#define ogc_cursor_theme_get_cursor _glfw.ogc.cursor.theme_get_cursor
#define ogc_cursor_image_get_buffer _glfw.ogc.cursor.image_get_buffer
typedef struct ogc_egl_window* (* PFN_ogc_egl_window_create)(struct ogc_surface*, int, int);
typedef void (* PFN_ogc_egl_window_destroy)(struct ogc_egl_window*);
typedef void (* PFN_ogc_egl_window_resize)(struct ogc_egl_window*, int, int, int, int);
#define ogc_egl_window_create _glfw.ogc.egl.window_create
#define ogc_egl_window_destroy _glfw.ogc.egl.window_destroy
#define ogc_egl_window_resize _glfw.ogc.egl.window_resize
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
typedef int (* PFN_xkb_keymap_key_get_syms_by_level)(struct xkb_keymap*,xkb_keycode_t,xkb_layout_index_t,xkb_level_index_t,const xkb_keysym_t**);
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
typedef xkb_layout_index_t (* PFN_xkb_state_key_get_layout)(struct xkb_state*,xkb_keycode_t);
typedef int (* PFN_xkb_state_mod_index_is_active)(struct xkb_state*,xkb_mod_index_t,enum xkb_state_component);
typedef uint32_t (* PFN_xkb_keysym_to_utf32)(xkb_keysym_t);
typedef int (* PFN_xkb_keysym_to_utf8)(xkb_keysym_t, char*, size_t);
#define xkb_context_new _glfw.ogc.xkb.context_new
#define xkb_context_unref _glfw.ogc.xkb.context_unref
#define xkb_keymap_new_from_string _glfw.ogc.xkb.keymap_new_from_string
#define xkb_keymap_unref _glfw.ogc.xkb.keymap_unref
#define xkb_keymap_mod_get_index _glfw.ogc.xkb.keymap_mod_get_index
#define xkb_keymap_key_repeats _glfw.ogc.xkb.keymap_key_repeats
#define xkb_keymap_key_get_syms_by_level _glfw.ogc.xkb.keymap_key_get_syms_by_level
#define xkb_state_new _glfw.ogc.xkb.state_new
#define xkb_state_unref _glfw.ogc.xkb.state_unref
#define xkb_state_key_get_syms _glfw.ogc.xkb.state_key_get_syms
#define xkb_state_update_mask _glfw.ogc.xkb.state_update_mask
#define xkb_state_key_get_layout _glfw.ogc.xkb.state_key_get_layout
#define xkb_state_mod_index_is_active _glfw.ogc.xkb.state_mod_index_is_active
#define xkb_keysym_to_utf32 _glfw.ogc.xkb.keysym_to_utf32
#define xkb_keysym_to_utf8 _glfw.ogc.xkb.keysym_to_utf8
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
#define xkb_compose_table_new_from_locale _glfw.ogc.xkb.compose_table_new_from_locale
#define xkb_compose_table_unref _glfw.ogc.xkb.compose_table_unref
#define xkb_compose_state_new _glfw.ogc.xkb.compose_state_new
#define xkb_compose_state_unref _glfw.ogc.xkb.compose_state_unref
#define xkb_compose_state_feed _glfw.ogc.xkb.compose_state_feed
#define xkb_compose_state_get_status _glfw.ogc.xkb.compose_state_get_status
#define xkb_compose_state_get_one_sym _glfw.ogc.xkb.compose_state_get_one_sym
#endif
// Ogc-specific per-window data
//
typedef struct _GLFWwindowOgc
{
int width, height;
GLFWbool maximized;
GLFWbool activated;
GLFWbool fullscreen;
GLFWbool hovered;
GLFWbool transparent;
GLFWbool scaleFramebuffer;
struct ogc_surface* surface;
struct ogc_callback* callback;
_GLFWcursor* currentCursor;
double cursorPosX, cursorPosY;
char* appId;
} _GLFWwindowOgc;
// Ogc-specific global data
//
typedef struct _GLFWlibraryOgc
{
void * xfb[2];
int fbIndex;
struct ogc_cursor_theme* cursorTheme;
struct ogc_cursor_theme* cursorThemeHiDPI;
struct ogc_surface* cursorSurface;
const char* cursorPreviousName;
int cursorTimerfd;
uint32_t serial;
uint32_t pointerEnterSerial;
int keyRepeatTimerfd;
int32_t keyRepeatRate;
int32_t keyRepeatDelay;
int keyRepeatScancode;
char* clipboardString;
short int keycodes[256];
short int scancodes[GLFW_KEY_LAST + 1];
char keynames[GLFW_KEY_LAST + 1][5];
_GLFWwindow* pointerFocus;
_GLFWwindow* keyboardFocus;
} _GLFWlibraryOgc;
// Ogc-specific per-monitor data
//
typedef struct _GLFWmonitorOgc
{
int currentMode;
GXRModeObj* ogcMode;
} _GLFWmonitorOgc;
// Ogc-specific per-cursor data
//
typedef struct _GLFWcursorOgc
{
GXTexObj texobj;
short xhot, yhot;
GLFWbool canRotate;
} _GLFWcursorOgc;
GLFWbool _glfwConnectOgc(int platformID, _GLFWplatform* platform);
int _glfwInitOgc(void);
void _glfwTerminateOgc(void);
void _glfwCreateMonitorOgc(void);
void _glfwSetVideoModeOgc(_GLFWmonitor* monitor, const GLFWvidmode* desired);
GLFWbool _glfwCreateContextOgc(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);
GLFWbool _glfwCreateWindowOgc(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig);
void _glfwDestroyWindowOgc(_GLFWwindow* window);
void _glfwSetWindowTitleOgc(_GLFWwindow* window, const char* title);
void _glfwSetWindowIconOgc(_GLFWwindow* window, int count, const GLFWimage* images);
void _glfwGetWindowPosOgc(_GLFWwindow* window, int* xpos, int* ypos);
void _glfwSetWindowPosOgc(_GLFWwindow* window, int xpos, int ypos);
void _glfwGetWindowSizeOgc(_GLFWwindow* window, int* width, int* height);
void _glfwSetWindowSizeOgc(_GLFWwindow* window, int width, int height);
void _glfwSetWindowSizeLimitsOgc(_GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight);
void _glfwSetWindowAspectRatioOgc(_GLFWwindow* window, int numer, int denom);
void _glfwGetFramebufferSizeOgc(_GLFWwindow* window, int* width, int* height);
void _glfwGetWindowFrameSizeOgc(_GLFWwindow* window, int* left, int* top, int* right, int* bottom);
void _glfwGetWindowContentScaleOgc(_GLFWwindow* window, float* xscale, float* yscale);
void _glfwIconifyWindowOgc(_GLFWwindow* window);
void _glfwRestoreWindowOgc(_GLFWwindow* window);
void _glfwMaximizeWindowOgc(_GLFWwindow* window);
void _glfwShowWindowOgc(_GLFWwindow* window);
void _glfwHideWindowOgc(_GLFWwindow* window);
void _glfwRequestWindowAttentionOgc(_GLFWwindow* window);
void _glfwFocusWindowOgc(_GLFWwindow* window);
void _glfwSetWindowMonitorOgc(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate);
GLFWbool _glfwWindowFocusedOgc(_GLFWwindow* window);
GLFWbool _glfwWindowIconifiedOgc(_GLFWwindow* window);
GLFWbool _glfwWindowVisibleOgc(_GLFWwindow* window);
GLFWbool _glfwWindowMaximizedOgc(_GLFWwindow* window);
GLFWbool _glfwWindowHoveredOgc(_GLFWwindow* window);
GLFWbool _glfwFramebufferTransparentOgc(_GLFWwindow* window);
void _glfwSetWindowResizableOgc(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowDecoratedOgc(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetWindowFloatingOgc(_GLFWwindow* window, GLFWbool enabled);
float _glfwGetWindowOpacityOgc(_GLFWwindow* window);
void _glfwSetWindowOpacityOgc(_GLFWwindow* window, float opacity);
void _glfwSetWindowMousePassthroughOgc(_GLFWwindow* window, GLFWbool enabled);
void _glfwSetRawMouseMotionOgc(_GLFWwindow* window, GLFWbool enabled);
GLFWbool _glfwRawMouseMotionSupportedOgc(void);
void _glfwPollEventsOgc(void);
void _glfwWaitEventsOgc(void);
void _glfwWaitEventsTimeoutOgc(double timeout);
void _glfwPostEmptyEventOgc(void);
void _glfwGetCursorPosOgc(_GLFWwindow* window, double* xpos, double* ypos);
void _glfwSetCursorPosOgc(_GLFWwindow* window, double xpos, double ypos);
void _glfwSetCursorModeOgc(_GLFWwindow* window, int mode);
const char* _glfwGetScancodeNameOgc(int scancode);
int _glfwGetKeyScancodeOgc(int key);
GLFWbool _glfwCreateCursorOgc(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot);
GLFWbool _glfwCreateStandardCursorOgc(_GLFWcursor* cursor, int shape);
void _glfwDestroyCursorOgc(_GLFWcursor* cursor);
void _glfwSetCursorOgc(_GLFWwindow* window, _GLFWcursor* cursor);
void _glfwSetClipboardStringOgc(const char* string);
const char* _glfwGetClipboardStringOgc(void);
EGLenum _glfwGetEGLPlatformOgc(EGLint** attribs);
EGLNativeDisplayType _glfwGetEGLNativeDisplayOgc(void);
EGLNativeWindowType _glfwGetEGLNativeWindowOgc(_GLFWwindow* window);
void _glfwGetRequiredInstanceExtensionsOgc(char** extensions);
GLFWbool _glfwGetPhysicalDevicePresentationSupportOgc(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily);
VkResult _glfwCreateWindowSurfaceOgc(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface);
void _glfwFreeMonitorOgc(_GLFWmonitor* monitor);
void _glfwGetMonitorPosOgc(_GLFWmonitor* monitor, int* xpos, int* ypos);
void _glfwGetMonitorContentScaleOgc(_GLFWmonitor* monitor, float* xscale, float* yscale);
void _glfwGetMonitorWorkareaOgc(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height);
GLFWvidmode* _glfwGetVideoModesOgc(_GLFWmonitor* monitor, int* count);
GLFWbool _glfwGetVideoModeOgc(_GLFWmonitor* monitor, GLFWvidmode* mode);
GLFWbool _glfwGetGammaRampOgc(_GLFWmonitor* monitor, GLFWgammaramp* ramp);
void _glfwSetGammaRampOgc(_GLFWmonitor* monitor, const GLFWgammaramp* ramp);
void _glfwAddOutputOgc(uint32_t name, uint32_t version);
void _glfwUpdateBufferScaleFromOutputsOgc(_GLFWwindow* window);

237
src/ogc_thread.c Normal file
View File

@ -0,0 +1,237 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(GLFW_BUILD_OGC_THREAD)
#include <assert.h>
#include <ogcsys.h>
#include <string.h>
#define MAX_THREADS 32
#define INITIAL_STORAGE_CAPACITY 64
#define INCREMENT_STORAGE_CAPACITY 64
typedef struct _GLFWthreadStorageOgc {
size_t capacity;
size_t used;
void *data[0]; /* Array of pointers to the stored data element */
} _GLFWthreadStorageOgc;
#define RESERVED_PTR ((void*)0x1)
typedef struct _GLFWthreadMapOgc {
lwp_t threadId;
_GLFWthreadStorageOgc *storage;
} _GLFWthreadMapOgc;
static _GLFWthreadMapOgc threadMap[MAX_THREADS];
static mutex_t threadMapMutex = 0; // TODO initialize!
static _GLFWthreadMapOgc *storageEntryForThread()
{
lwp_t currentThreadId = LWP_GetSelf();
/* We are not creating entries here and only our thread can modify our
* entry, so we don't need to lock the mutex here. */
for (int i = 0; i < MAX_THREADS; i++) {
_GLFWthreadMapOgc *entry = &threadMap[i];
if (entry->threadId == currentThreadId) {
return entry;
}
}
return NULL;
}
static inline _GLFWthreadStorageOgc *storageForThread()
{
_GLFWthreadMapOgc *entry = storageEntryForThread();
return entry ? entry->storage : NULL;
}
static _GLFWthreadMapOgc *createStorageEntryForThread()
{
size_t initialSize = sizeof(_GLFWthreadStorageOgc) +
INITIAL_STORAGE_CAPACITY * sizeof(void*);
_GLFWthreadStorageOgc *storage = _glfw_calloc(1, initialSize);
if (!storage) {
_glfwInputError(GLFW_OUT_OF_MEMORY,
"OGC: Failed to allocate TLS data");
return NULL;
}
storage->capacity = INITIAL_STORAGE_CAPACITY;
storage->used = 0;
if (!LWP_MutexLock(threadMapMutex)) {
_glfw_free(storage);
_glfwInputError(GLFW_PLATFORM_ERROR,
"OGC: Failed to lock TLS mutex");
return NULL;
}
_GLFWthreadMapOgc *entry = NULL;
lwp_t currentThreadId = LWP_GetSelf();
for (int i = 0; i < MAX_THREADS; i++) {
entry = &threadMap[i];
if (!entry->threadId) {
entry->threadId = currentThreadId;
entry->storage = storage;
break;
}
}
if (entry->threadId != currentThreadId) {
// We didn't find a free slot
entry = NULL;
}
LWP_MutexUnlock(threadMapMutex);
return entry;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwPlatformCreateTls(_GLFWtls* tls)
{
assert(tls->ogc.allocated == GLFW_FALSE);
_GLFWthreadMapOgc *entry = storageEntryForThread();
if (!entry) {
entry = createStorageEntryForThread();
if (!entry) {
// The error has already been logged
return GLFW_FALSE;
}
}
_GLFWthreadStorageOgc *storage = entry->storage;
if (storage->used >= storage->capacity) {
size_t newSize = sizeof(_GLFWthreadStorageOgc) +
(storage->capacity + INCREMENT_STORAGE_CAPACITY) * sizeof(void*);
storage = _glfw_realloc(storage, newSize);
if (!storage) {
_glfwInputError(GLFW_OUT_OF_MEMORY,
"OGC: Failed to reallocate TLS data");
return GLFW_FALSE;
}
// No need to lock the map, since we are changing our own thread's
// entry
entry->storage = storage;
storage->capacity += INCREMENT_STORAGE_CAPACITY;
}
// Find the first free entry in the TLS data
int index = -1;
for (int i = 0; i < storage->capacity; i++) {
if (!storage->data[i]) {
index = i;
break;
}
}
/* We know that storage->capacity > storage->used, so there must be free
* slots */
assert(index >= 0);
storage->data[index] = RESERVED_PTR;
storage->used++;
tls->ogc.index = index;
tls->ogc.allocated = GLFW_TRUE;
return GLFW_TRUE;
}
void _glfwPlatformDestroyTls(_GLFWtls* tls)
{
if (tls->ogc.allocated) {
_GLFWthreadMapOgc *entry = storageEntryForThread();
if (entry) {
assert(entry->storage->capacity > tls->ogc.index);
assert(entry->storage->used > 0);
entry->storage->data[tls->ogc.index] = NULL;
entry->storage->used--;
}
}
memset(tls, 0, sizeof(_GLFWtls));
}
void* _glfwPlatformGetTls(_GLFWtls* tls)
{
assert(tls->ogc.allocated == GLFW_TRUE);
_GLFWthreadMapOgc *entry = storageEntryForThread();
void *ptr = entry->storage->data[tls->ogc.index];
return ptr == RESERVED_PTR ? NULL : ptr;
}
void _glfwPlatformSetTls(_GLFWtls* tls, void* value)
{
assert(tls->posix.allocated == GLFW_TRUE);
_GLFWthreadMapOgc *entry = storageEntryForThread();
entry->storage->data[tls->ogc.index] = value;
}
GLFWbool _glfwPlatformCreateMutex(_GLFWmutex* mutex)
{
assert(mutex->ogc.allocated == GLFW_FALSE);
if (LWP_MutexInit(&mutex->ogc.handle, false) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR, "OGC: Failed to create mutex");
return GLFW_FALSE;
}
return mutex->ogc.allocated = GLFW_TRUE;
}
void _glfwPlatformDestroyMutex(_GLFWmutex* mutex)
{
if (mutex->ogc.allocated)
LWP_MutexDestroy(mutex->ogc.handle);
memset(mutex, 0, sizeof(_GLFWmutex));
}
void _glfwPlatformLockMutex(_GLFWmutex* mutex)
{
assert(mutex->ogc.allocated == GLFW_TRUE);
LWP_MutexLock(mutex->ogc.handle);
}
void _glfwPlatformUnlockMutex(_GLFWmutex* mutex)
{
assert(mutex->ogc.allocated == GLFW_TRUE);
LWP_MutexUnlock(mutex->ogc.handle);
}
void _glfwThreadInitMutexOgc()
{
LWP_MutexInit(&threadMapMutex, false);
}
#endif // GLFW_BUILD_OGC_THREAD

49
src/ogc_thread.h Normal file
View File

@ -0,0 +1,49 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include <ogc/mutex.h>
#define GLFW_OGC_TLS_STATE _GLFWtlsOgc ogc;
#define GLFW_OGC_MUTEX_STATE _GLFWmutexOgc ogc;
// POSIX-specific thread local storage data
//
typedef struct _GLFWtlsOgc
{
GLFWbool allocated;
int index;
} _GLFWtlsOgc;
// POSIX-specific mutex data
//
typedef struct _GLFWmutexOgc
{
GLFWbool allocated;
mutex_t handle;
} _GLFWmutexOgc;
void _glfwThreadInitMutexOgc();

52
src/ogc_time.c Normal file
View File

@ -0,0 +1,52 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would
// be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such, and must not
// be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source
// distribution.
//
//========================================================================
#include "internal.h"
#if defined(GLFW_BUILD_OGC_TIMER)
#include <ogc/lwp_watchdog.h>
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
void _glfwPlatformInitTimer(void)
{
}
uint64_t _glfwPlatformGetTimerValue(void)
{
return gettime();
}
uint64_t _glfwPlatformGetTimerFrequency(void)
{
return secs_to_ticks(1);
}
#endif // GLFW_BUILD_OGC_TIMER

28
src/ogc_time.h Normal file
View File

@ -0,0 +1,28 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// 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.
//
//========================================================================
#define GLFW_OGC_LIBRARY_TIMER_STATE

564
src/ogc_window.c Normal file
View File

@ -0,0 +1,564 @@
//========================================================================
// GLFW 3.5 OGC - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2024 Alberto Mardegan <info@mardy.it>
//
// 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.
//
//========================================================================
#define _GNU_SOURCE
#include "internal.h"
#if defined(_GLFW_OGC)
#include "ogc_cursor.h"
#include <assert.h>
#include <errno.h>
#include <malloc.h>
#include <opengx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wiikeyboard/keyboard.h>
#ifdef __wii__
#include <wiiuse/wpad.h>
#endif
static void keysym_to_utf8(uint16_t symbol, char *utf8)
{
/* ignore private symbols, used by wiikeyboard for special keys */
if ((symbol >= 0xE000 && symbol <= 0xF8FF) || symbol == 0xFFFF)
return;
/* convert UCS-2 to UTF-8 */
if (symbol < 0x80) {
utf8[0] = symbol;
} else if (symbol < 0x800) {
utf8[0] = 0xC0 | (symbol >> 6);
utf8[1] = 0x80 | (symbol & 0x3F);
} else {
utf8[0] = 0xE0 | (symbol >> 12);
utf8[1] = 0x80 | ((symbol >> 6) & 0x3F);
utf8[2] = 0x80 | (symbol & 0x3F);
}
}
static void acquireMonitor(_GLFWwindow* window)
{
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, __func__);
if (!window->monitor) {
window->monitor = _glfw.monitors[0];
}
_glfwInputMonitorWindow(window->monitor, window);
_glfwSetVideoModeOgc(window->monitor, &window->videoMode);
}
static void releaseMonitor(_GLFWwindow* window)
{
if (window->monitor->window != window)
return;
_glfwInputMonitorWindow(window->monitor, NULL);
}
/* Convert the RGBA pixels to the 4x4 tile ARGB texture used by GX */
static void setPixelToTextureARGB(char *texture, u32 offset, u32 color)
{
*(u16*)(texture + offset) = color >> 16;
*(u16*)(texture + offset + 32) = color;
}
static void setPixelToTextureRGBA(char *texture, u32 offset, u32 color)
{
setPixelToTextureARGB(texture, offset, (color << 24) | (color >> 8));
}
static void pixelsToTextureARGB(const void *pixels, s16 width, s16 height,
s16 pitch, void *texture)
{
s16 tex_pitch = (width + 3) / 4 * 4;
int row, col;
for (row = 0; row < height; row++) {
int y = row;
u32 *src = (u32 *)((u8 *)pixels + pitch * row);
for (col = 0; col < width; col++) {
int x = col;
u32 offset = (((y >> 2) << 4) * tex_pitch) +
((x >> 2) << 6) + (((y % 4 << 2) + x % 4) << 1);
setPixelToTextureRGBA(texture, offset, *src++);
}
}
}
static void* createRGBAtexture(const GLFWimage* image)
{
u32 textureSize;
void *texels;
textureSize = GX_GetTexBufferSize(image->width, image->height, GX_TF_RGBA8,
GX_FALSE, 0);
texels = memalign(32, textureSize);
if (!texels) {
_glfwInputError(GLFW_OUT_OF_MEMORY,
"OGC: Failed to allocate cursor texture");
return NULL;
}
pixelsToTextureARGB(image->pixels, image->width, image->height,
image->width * 4, texels);
DCStoreRange(texels, textureSize);
return texels;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
GLFWbool _glfwCreateWindowOgc(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
fprintf(stderr, "%s:%d %s %p\n", __FILE__, __LINE__, __func__, window);
acquireMonitor(window);
window->ogc.width = window->monitor->ogc.ogcMode->fbWidth;
window->ogc.height = window->monitor->ogc.ogcMode->efbHeight;
if (ctxconfig->client != GLFW_NO_API)
{
ogx_initialize();
if (!_glfwCreateContextOgc(window, ctxconfig, fbconfig))
return GLFW_FALSE;
if (!_glfwRefreshContextAttribs(window, ctxconfig))
return GLFW_FALSE;
}
/* Set the default Wii cursor */
GLFWcursor *cursor = glfwCreateStandardCursor(GLFW_POINTING_HAND_CURSOR);
_glfwSetCursorOgc(window, (_GLFWcursor*) cursor);
return GLFW_TRUE;
}
void _glfwDestroyWindowOgc(_GLFWwindow* window)
{
if (window->monitor)
releaseMonitor(window);
}
void _glfwSetWindowTitleOgc(_GLFWwindow* window, const char* title)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the window title");
}
void _glfwSetWindowIconOgc(_GLFWwindow* window,
int count, const GLFWimage* images)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the window icon");
}
void _glfwGetWindowPosOgc(_GLFWwindow* window, int* xpos, int* ypos)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"getting the window position");
}
void _glfwSetWindowPosOgc(_GLFWwindow* window, int xpos, int ypos)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the window position");
}
void _glfwGetWindowSizeOgc(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->ogc.width;
if (height)
*height = window->ogc.height;
}
void _glfwSetWindowSizeOgc(_GLFWwindow* window, int width, int height)
{
fprintf(stderr, "%s:%d %s %dx%d\n", __FILE__, __LINE__, __func__, width, height);
if (window->monitor)
{
}
else
{
_glfwInputWindowDamage(window);
}
}
void _glfwSetWindowSizeLimitsOgc(_GLFWwindow* window,
int minwidth, int minheight,
int maxwidth, int maxheight)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the size limits");
}
void _glfwSetWindowAspectRatioOgc(_GLFWwindow* window, int numer, int denom)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the aspect ratio");
}
void _glfwGetFramebufferSizeOgc(_GLFWwindow* window, int* width, int* height)
{
if (width)
*width = window->monitor->ogc.ogcMode->fbWidth;
if (height)
*height = window->monitor->ogc.ogcMode->efbHeight;;
}
void _glfwGetWindowFrameSizeOgc(_GLFWwindow* window,
int* left, int* top,
int* right, int* bottom)
{
*left = *top = *right = *bottom = 0;
}
void _glfwGetWindowContentScaleOgc(_GLFWwindow* window,
float* xscale, float* yscale)
{
if (xscale)
*xscale = 1.0f;
if (yscale)
*yscale = 1.0f;
}
void _glfwIconifyWindowOgc(_GLFWwindow* window)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"iconifying the window");
}
void _glfwRestoreWindowOgc(_GLFWwindow* window)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"restoring the window");
}
void _glfwMaximizeWindowOgc(_GLFWwindow* window)
{
}
void _glfwShowWindowOgc(_GLFWwindow* window)
{
}
void _glfwHideWindowOgc(_GLFWwindow* window)
{
}
void _glfwRequestWindowAttentionOgc(_GLFWwindow* window)
{
}
void _glfwFocusWindowOgc(_GLFWwindow* window)
{
}
void _glfwSetWindowMonitorOgc(_GLFWwindow* window,
_GLFWmonitor* monitor,
int xpos, int ypos,
int width, int height,
int refreshRate)
{
}
GLFWbool _glfwWindowFocusedOgc(_GLFWwindow* window)
{
return GLFW_TRUE;
}
GLFWbool _glfwWindowIconifiedOgc(_GLFWwindow* window)
{
return GLFW_FALSE;
}
GLFWbool _glfwWindowVisibleOgc(_GLFWwindow* window)
{
return GLFW_TRUE;
}
GLFWbool _glfwWindowMaximizedOgc(_GLFWwindow* window)
{
return GLFW_TRUE;
}
GLFWbool _glfwWindowHoveredOgc(_GLFWwindow* window)
{
return window->ogc.hovered;
}
GLFWbool _glfwFramebufferTransparentOgc(_GLFWwindow* window)
{
return GLFW_FALSE;
}
void _glfwSetWindowResizableOgc(_GLFWwindow* window, GLFWbool enabled)
{
}
void _glfwSetWindowDecoratedOgc(_GLFWwindow* window, GLFWbool enabled)
{
}
void _glfwSetWindowFloatingOgc(_GLFWwindow* window, GLFWbool enabled)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"making a window floating");
}
void _glfwSetWindowMousePassthroughOgc(_GLFWwindow* window, GLFWbool enabled)
{
}
float _glfwGetWindowOpacityOgc(_GLFWwindow* window)
{
return 1.f;
}
void _glfwSetWindowOpacityOgc(_GLFWwindow* window, float opacity)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the window opacity");
}
void _glfwSetRawMouseMotionOgc(_GLFWwindow* window, GLFWbool enabled)
{
}
GLFWbool _glfwRawMouseMotionSupportedOgc(void)
{
return GLFW_FALSE;
}
#ifdef __wii__
static void handleWiimoteCursorOgc(_GLFWwindow* window)
{
WPADData *data = WPAD_Data(0);
float x, y;
GLFWbool mouseActive = !!data->ir.valid;
if (mouseActive != window->ogc.hovered) {
window->ogc.hovered = mouseActive;
_glfwInputCursorEnter(window, mouseActive);
}
if (!mouseActive) return;
x = data->ir.x * window->ogc.width / data->ir.vres[0];
y = data->ir.y * window->ogc.height / data->ir.vres[1];
_glfwInputCursorPos(window, x, y);
if (data->btns_d & WPAD_BUTTON_A)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_PRESS, 0);
if (data->btns_u & WPAD_BUTTON_A)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_1, GLFW_RELEASE, 0);
if (data->btns_d & WPAD_BUTTON_B)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_2, GLFW_PRESS, 0);
if (data->btns_u & WPAD_BUTTON_B)
_glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_2, GLFW_RELEASE, 0);
}
#endif
void _glfwPollEventsOgc(void)
{
//fprintf(stderr, "Polling for events %d\n", 0);
GLFWbool hasEvents = GLFW_FALSE;
if (_glfwPollJoysticksOgc()) {
hasEvents = GLFW_TRUE;
#ifdef __wii__
/* Use the first wiimote as mouse */
if (_glfw.windowListHead)
handleWiimoteCursorOgc(_glfw.windowListHead);
#endif
}
}
void _glfwWaitEventsOgc(void)
{
// TODO: check if events were produced or sleep?
_glfwPollEventsOgc();
}
void _glfwWaitEventsTimeoutOgc(double timeout)
{
// TODO: check if events were produced or sleep?
_glfwPollEventsOgc();
}
void _glfwPostEmptyEventOgc(void)
{
}
void _glfwGetCursorPosOgc(_GLFWwindow* window, double* xpos, double* ypos)
{
if (xpos)
*xpos = window->virtualCursorPosX;
if (ypos)
*ypos = window->virtualCursorPosY;
}
void _glfwSetCursorPosOgc(_GLFWwindow* window, double x, double y)
{
_glfwInputError(GLFW_FEATURE_UNAVAILABLE, _glfwUnimplementedFmt,
"setting the cursor position");
}
void _glfwSetCursorModeOgc(_GLFWwindow* window, int mode)
{
// TODO
}
const char* _glfwGetScancodeNameOgc(int scancode)
{
static char name[10];
name[0] = name[1] = '\0';
switch (scancode) {
case KS_Return: name[0] = '\n'; break;
case KS_Escape: return "ESC";
default:
keysym_to_utf8(scancode, name);
}
return name;
}
int _glfwGetKeyScancodeOgc(int key)
{
return _glfw.ogc.scancodes[key];
}
GLFWbool _glfwCreateCursorOgc(_GLFWcursor* cursor,
const GLFWimage* image,
int xhot, int yhot)
{
void* texels = createRGBAtexture(image);
if (!texels) return GLFW_FALSE;
cursor->ogc.xhot = xhot;
cursor->ogc.yhot = yhot;
GX_InvalidateTexAll();
GX_InitTexObj(&cursor->ogc.texobj, texels,
image->width, image->height,
GX_TF_RGBA8, GX_CLAMP, GX_CLAMP, GX_FALSE);
GX_InitTexObjLOD(&cursor->ogc.texobj, GX_LINEAR, GX_LINEAR,
0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1);
return GLFW_TRUE;
}
GLFWbool _glfwCreateStandardCursorOgc(_GLFWcursor* cursor, int shape)
{
const _GLFWcursorDataOgc* cd = NULL;
switch (shape)
{
case GLFW_ARROW_CURSOR:
cd = &OGC_cursor_arrow;
break;
case GLFW_POINTING_HAND_CURSOR:
cd = &OGC_cursor_hand;
break;
default:
return GLFW_FALSE;
}
GLFWimage image = {
cd->width, cd->height, cd->pixel_data
};
return _glfwCreateCursorOgc(cursor, &image,
cd->hot_x, cd->hot_y);
}
void _glfwDestroyCursorOgc(_GLFWcursor* cursor)
{
void *data = GX_GetTexObjData(&cursor->ogc.texobj);
if (data != 0)
free(MEM_PHYSICAL_TO_K0(data));
}
void _glfwSetCursorOgc(_GLFWwindow* window, _GLFWcursor* cursor)
{
window->ogc.currentCursor = cursor;
}
void _glfwSetClipboardStringOgc(const char* string)
{
}
const char* _glfwGetClipboardStringOgc(void)
{
return NULL;
}
EGLenum _glfwGetEGLPlatformOgc(EGLint** attribs)
{
return EGL_PLATFORM_ANGLE_ANGLE;
}
EGLNativeDisplayType _glfwGetEGLNativeDisplayOgc(void)
{
return EGL_DEFAULT_DISPLAY;
}
EGLNativeWindowType _glfwGetEGLNativeWindowOgc(_GLFWwindow* window)
{
return 0;
}
void _glfwGetRequiredInstanceExtensionsOgc(char** extensions)
{
}
GLFWbool _glfwGetPhysicalDevicePresentationSupportOgc(VkInstance instance,
VkPhysicalDevice device,
uint32_t queuefamily)
{
return GLFW_FALSE;
}
VkResult _glfwCreateWindowSurfaceOgc(VkInstance instance,
_GLFWwindow* window,
const VkAllocationCallbacks* allocator,
VkSurfaceKHR* surface)
{
return VK_ERROR_EXTENSION_NOT_PRESENT;
}
#endif // _GLFW_OGC

View File

@ -56,6 +56,9 @@ static const struct
#if defined(_GLFW_X11)
{ GLFW_PLATFORM_X11, _glfwConnectX11 },
#endif
#if defined(_GLFW_OGC)
{ GLFW_PLATFORM_OGC, _glfwConnectOgc },
#endif
};
GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
@ -68,6 +71,7 @@ GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
desiredID != GLFW_PLATFORM_COCOA &&
desiredID != GLFW_PLATFORM_WAYLAND &&
desiredID != GLFW_PLATFORM_X11 &&
desiredID != GLFW_PLATFORM_OGC &&
desiredID != GLFW_PLATFORM_NULL)
{
_glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", desiredID);

View File

@ -29,6 +29,8 @@
defined(GLFW_BUILD_WIN32_MODULE) || \
defined(GLFW_BUILD_WIN32_THREAD) || \
defined(GLFW_BUILD_COCOA_TIMER) || \
defined(GLFW_BUILD_OGC_MODULE) || \
defined(GLFW_BUILD_OGC_THREAD) || \
defined(GLFW_BUILD_POSIX_TIMER) || \
defined(GLFW_BUILD_POSIX_MODULE) || \
defined(GLFW_BUILD_POSIX_THREAD) || \
@ -90,6 +92,16 @@
#define GLFW_GLX_LIBRARY_CONTEXT_STATE
#endif
#if defined(_GLFW_OGC)
#include "ogc_platform.h"
#define GLFW_EXPOSE_NATIVE_OGC
#else
#define GLFW_OGC_WINDOW_STATE
#define GLFW_OGC_MONITOR_STATE
#define GLFW_OGC_CURSOR_STATE
#define GLFW_OGC_LIBRARY_WINDOW_STATE
#endif
#include "null_joystick.h"
#if defined(_GLFW_WIN32)
@ -106,6 +118,13 @@
#define GLFW_COCOA_LIBRARY_JOYSTICK_STATE
#endif
#if defined(_GLFW_OGC)
#include "ogc_joystick.h"
#else
#define GLFW_OGC_JOYSTICK_STATE
#define GLFW_OGC_LIBRARY_JOYSTICK_STATE
#endif
#if (defined(_GLFW_X11) || defined(_GLFW_WAYLAND)) && defined(__linux__)
#define GLFW_BUILD_LINUX_JOYSTICK
#endif
@ -123,6 +142,7 @@
GLFW_WAYLAND_WINDOW_STATE \
GLFW_X11_WINDOW_STATE \
GLFW_NULL_WINDOW_STATE \
GLFW_OGC_WINDOW_STATE \
#define GLFW_PLATFORM_MONITOR_STATE \
GLFW_WIN32_MONITOR_STATE \
@ -130,6 +150,7 @@
GLFW_WAYLAND_MONITOR_STATE \
GLFW_X11_MONITOR_STATE \
GLFW_NULL_MONITOR_STATE \
GLFW_OGC_MONITOR_STATE \
#define GLFW_PLATFORM_CURSOR_STATE \
GLFW_WIN32_CURSOR_STATE \
@ -137,11 +158,13 @@
GLFW_WAYLAND_CURSOR_STATE \
GLFW_X11_CURSOR_STATE \
GLFW_NULL_CURSOR_STATE \
GLFW_OGC_CURSOR_STATE \
#define GLFW_PLATFORM_JOYSTICK_STATE \
GLFW_WIN32_JOYSTICK_STATE \
GLFW_COCOA_JOYSTICK_STATE \
GLFW_LINUX_JOYSTICK_STATE
GLFW_LINUX_JOYSTICK_STATE \
GLFW_OGC_JOYSTICK_STATE \
#define GLFW_PLATFORM_LIBRARY_WINDOW_STATE \
GLFW_WIN32_LIBRARY_WINDOW_STATE \
@ -149,11 +172,13 @@
GLFW_WAYLAND_LIBRARY_WINDOW_STATE \
GLFW_X11_LIBRARY_WINDOW_STATE \
GLFW_NULL_LIBRARY_WINDOW_STATE \
GLFW_OGC_LIBRARY_WINDOW_STATE \
#define GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE \
GLFW_WIN32_LIBRARY_JOYSTICK_STATE \
GLFW_COCOA_LIBRARY_JOYSTICK_STATE \
GLFW_LINUX_LIBRARY_JOYSTICK_STATE
GLFW_LINUX_LIBRARY_JOYSTICK_STATE \
GLFW_OGC_LIBRARY_JOYSTICK_STATE \
#define GLFW_PLATFORM_CONTEXT_STATE \
GLFW_WGL_CONTEXT_STATE \
@ -167,6 +192,8 @@
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_THREAD
#elif defined(_GLFW_OGC)
#define GLFW_BUILD_OGC_THREAD
#else
#define GLFW_BUILD_POSIX_THREAD
#endif
@ -179,12 +206,18 @@
#include "posix_thread.h"
#define GLFW_PLATFORM_TLS_STATE GLFW_POSIX_TLS_STATE
#define GLFW_PLATFORM_MUTEX_STATE GLFW_POSIX_MUTEX_STATE
#elif defined(GLFW_BUILD_OGC_THREAD)
#include "ogc_thread.h"
#define GLFW_PLATFORM_TLS_STATE GLFW_OGC_TLS_STATE
#define GLFW_PLATFORM_MUTEX_STATE GLFW_OGC_MUTEX_STATE
#endif
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_TIMER
#elif defined(__APPLE__)
#define GLFW_BUILD_COCOA_TIMER
#elif defined(_GLFW_OGC)
#define GLFW_BUILD_OGC_TIMER
#else
#define GLFW_BUILD_POSIX_TIMER
#endif
@ -198,10 +231,15 @@
#elif defined(GLFW_BUILD_POSIX_TIMER)
#include "posix_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_POSIX_LIBRARY_TIMER_STATE
#elif defined(GLFW_BUILD_OGC_TIMER)
#include "ogc_time.h"
#define GLFW_PLATFORM_LIBRARY_TIMER_STATE GLFW_OGC_LIBRARY_TIMER_STATE
#endif
#if defined(_WIN32)
#define GLFW_BUILD_WIN32_MODULE
#elif defined(__wii__) || defined(__gamecube)
#define GLFW_BUILD_OGC_MODULE
#else
#define GLFW_BUILD_POSIX_MODULE
#endif

View File

@ -405,13 +405,19 @@ static void handleFallbackDecorationButton(_GLFWwindow* window,
}
else if (button == BTN_RIGHT)
{
if (window->wl.xdg.toplevel)
{
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
window->wl.cursorPosX,
window->wl.cursorPosY);
}
if (!window->wl.xdg.toplevel)
return;
if (window->wl.fallback.focus != window->wl.fallback.top.surface)
return;
if (ypos < GLFW_BORDER_SIZE)
return;
xdg_toplevel_show_window_menu(window->wl.xdg.toplevel,
_glfw.wl.seat, serial,
xpos,
ypos - GLFW_CAPTION_HEIGHT - GLFW_BORDER_SIZE);
}
}
@ -1532,11 +1538,21 @@ static void pointerHandleEnter(void* userData,
window->wl.hovered = GLFW_TRUE;
_glfwSetCursorWayland(window, window->wl.currentCursor);
_glfwInputCursorEnter(window, GLFW_TRUE);
if (window->cursorMode != GLFW_CURSOR_DISABLED)
{
window->wl.cursorPosX = wl_fixed_to_double(sx);
window->wl.cursorPosY = wl_fixed_to_double(sy);
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY);
}
}
else
{
if (window->wl.fallback.decorations)
{
window->wl.fallback.focus = surface;
updateFallbackDecorationCursor(window, sx, sy);
}
}
}

View File

@ -41,8 +41,10 @@ add_executable(title WIN32 MACOSX_BUNDLE title.c ${GLAD_GL})
add_executable(triangle-vulkan WIN32 triangle-vulkan.c ${GLAD_VULKAN})
add_executable(window WIN32 MACOSX_BUNDLE window.c ${GLAD_GL})
target_link_libraries(empty Threads::Threads)
target_link_libraries(threads Threads::Threads)
if (Threads_FOUND)
target_link_libraries(empty Threads::Threads)
target_link_libraries(threads Threads::Threads)
endif()
if (RT_LIBRARY)
target_link_libraries(empty "${RT_LIBRARY}")
target_link_libraries(threads "${RT_LIBRARY}")