diff --git a/.gitignore b/.gitignore index 84636a0a..f52d0637 100644 --- a/.gitignore +++ b/.gitignore @@ -101,3 +101,4 @@ tests/triangle-vulkan tests/window tests/windows +.vscode \ No newline at end of file diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json deleted file mode 100644 index 82b56bcb..00000000 --- a/.vscode/c_cpp_properties.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "configurations": [ - { - "name": "Win32", - "includePath": [ - "${workspaceFolder}/**", - "\\\\wsl.localhost\\Ubuntu\\usr\\ppc-amigaos\\SDK" - ], - "defines": [ - "_DEBUG", - "UNICODE", - "_UNICODE" - ], - "windowsSdkVersion": "10.0.19041.0", - "compilerPath": "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Tools\\MSVC\\14.29.30133\\bin\\Hostx64\\x64\\cl.exe", - "cStandard": "c17", - "cppStandard": "c++17", - "intelliSenseMode": "windows-msvc-x64" - } - ], - "version": 4 -} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json deleted file mode 100644 index eb437ae1..00000000 --- a/.vscode/settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "files.associations": { - "internal.h": "c", - "platform.h": "c", - "xutility": "c", - "gl.h": "c" - } -} \ No newline at end of file diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8773f4cf..51c0e1fe 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -236,6 +236,10 @@ extern "C" { #endif #include + #elif defined(__amigaos4__) && defined(GL4ES) + + #include + #else /*__APPLE__*/ #include diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6f3762d5..806b5ab6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,6 +70,10 @@ endif() if (GLFW_BUILD_WAYLAND) include(CheckIncludeFiles) include(CheckFunctionExists) + check_include_files(xkbcommon/xkbcommon-compose.h HAVE_XKBCOMMON_COMPOSE_H) + if (HAVE_XKBCOMMON_COMPOSE_H) + target_compile_definitions(glfw PRIVATE HAVE_XKBCOMMON_COMPOSE_H) + endif() check_function_exists(memfd_create HAVE_MEMFD_CREATE) if (HAVE_MEMFD_CREATE) target_compile_definitions(glfw PRIVATE HAVE_MEMFD_CREATE) @@ -179,7 +183,7 @@ if (GLFW_BUILD_WAYLAND) wayland-client>=0.2.7 wayland-cursor>=0.2.7 wayland-egl>=0.2.7 - xkbcommon>=0.5.0) + xkbcommon) target_include_directories(glfw PRIVATE ${Wayland_INCLUDE_DIRS}) diff --git a/src/os4_context.c b/src/os4_context.c index 5dc297aa..956915f3 100644 --- a/src/os4_context.c +++ b/src/os4_context.c @@ -36,6 +36,7 @@ #include #define GETPROCADDRESS getProcAddressGL #else +extern void *aglGetProcAddress(const char *name); enum CreateContextTags { OGLES2_CCT_MIN=(1UL<<31), OGLES2_CCT_WINDOW, @@ -51,6 +52,10 @@ enum CreateContextTags { OGLES2_CCT_CONTEXT_FOR_MODEID, OGLES2_CCT_RESIZE_VIEWPORT, OGLES2_CCT_DEBUG_SHADER_LOG, + OGLES2_CCT_SPIRV_OPLINES, + OGLES2_CCT_SPIRV_OPLINES_OFFSET, + OGLES2_CCT_SPIRV_OPTIMIZE, + OGLES2_CCT_SHARE_WITH, }; typedef int GLint; typedef int GLsizei; @@ -82,7 +87,6 @@ static void makeContextCurrentGL(_GLFWwindow* window) static void destroyContextGL(_GLFWwindow* window) { if (window->context.gl.glContext) { - printf("Destroying context %p for window handle %p\n", window->context.gl.glContext, window->os4.handle); aglDestroyContext(window->context.gl.glContext); } window->context.gl.glContext = NULL; @@ -134,6 +138,12 @@ GLFWbool _glfwCreateContextGL(_GLFWwindow* window, dprintf("accumAlphaBits=%d\n", fbconfig->accumAlphaBits); dprintf("auxBuffers=%d\n", fbconfig->auxBuffers); + void *sharedContext = NULL; + if (ctxconfig->share != NULL) { + sharedContext = ctxconfig->share->context.gl.glContext; + } + + dprintf("sharedContext = %p\n", sharedContext); struct TagItem contextparams[] = { {OGLES2_CCT_WINDOW, (ULONG)window->os4.handle}, @@ -141,10 +151,12 @@ GLFWbool _glfwCreateContextGL(_GLFWwindow* window, {OGLES2_CCT_STENCIL, fbconfig->stencilBits}, {OGLES2_CCT_VSYNC, 0}, {OGLES2_CCT_RESIZE_VIEWPORT, TRUE}, + {OGLES2_CCT_SHARE_WITH, sharedContext}, {TAG_DONE, 0} }; window->context.gl.glContext = (void *)aglCreateContext2(&errCode, contextparams); + dprintf("firstContext = %p\n", window->context.gl.glContext); /* Set the context as current */ if (window->context.gl.glContext) { @@ -155,7 +167,7 @@ GLFWbool _glfwCreateContextGL(_GLFWwindow* window, window->os4.handle = NULL; return GLFW_FALSE; } - printf("Creating context %p for window handle %p\n", window->context.gl.glContext, window->os4.handle); + dprintf("Creating context %p for window handle %p\n", window->context.gl.glContext, window->os4.handle); window->context.makeCurrent = makeContextCurrentGL; window->context.swapBuffers = swapBuffersGL; diff --git a/src/os4_init.c b/src/os4_init.c index 7f0cee5a..93791bdf 100644 --- a/src/os4_init.c +++ b/src/os4_init.c @@ -45,9 +45,6 @@ struct Library *IntuitionBase = NULL; struct KeymapIFace *IKeymap = NULL; struct Library *KeymapBase = NULL; -struct UtilityIFace *IUtility = NULL; -struct Library *UtilityBase = NULL; - struct Library *AIN_Base = NULL; struct AIN_IFace *IAIN = NULL; @@ -173,13 +170,6 @@ static int loadLibraries(void) return 0; } - // Utility.library - UtilityBase = openLib("utility.library", MIN_LIB_VERSION, (struct Interface **)&IUtility); - if (!UtilityBase) - { - return 0; - } - // Workbench.library WorkbenchBase = openLib("workbench.library", MIN_LIB_VERSION, (struct Interface **)&IWorkbench); if (!WorkbenchBase) @@ -221,7 +211,6 @@ static int loadLibraries(void) static void closeLibraries(void) { - printf("close libraries\n"); if (ITextClip) { IExec->DropInterface((struct Interface *)ITextClip); } @@ -309,18 +298,6 @@ static void closeLibraries(void) IExec->CloseLibrary(KeymapBase); KeymapBase = NULL; } - - // Close utility.library - if (IUtility) - { - IExec->DropInterface((struct Interface *)IUtility); - IUtility = NULL; - } - if (UtilityBase) - { - IExec->CloseLibrary((struct Library *)UtilityBase); - UtilityBase = NULL; - } } static void createKeyTables(void) @@ -521,6 +498,9 @@ GLFWbool _glfwConnectOS4(int platformID, _GLFWplatform *platform) _glfwWaitEventsOS4, _glfwWaitEventsTimeoutOS4, _glfwPostEmptyEventOS4, + _glfwGetEGLPlatformOS4, + _glfwGetEGLNativeDisplayOS4, + _glfwGetEGLNativeWindowOS4, _glfwGetRequiredInstanceExtensionsOS4, _glfwGetPhysicalDevicePresentationSupportOS4, _glfwCreateWindowSurfaceOS4, diff --git a/src/os4_joystick.c b/src/os4_joystick.c index 188b9b2f..eef1a150 100644 --- a/src/os4_joystick.c +++ b/src/os4_joystick.c @@ -28,6 +28,256 @@ #include "internal.h" +#include +#include + +static struct Library *GLFW_AIN_Base; +static struct AIN_IFace *GLFW_IAIN; + +/* + * Convert AmigaInput hat data to GLFW hat data. + */ +static inline int +AMIGAINPUT_MapHatData(int hat_data) +{ + switch (hat_data) { + case 1: return GLFW_HAT_UP; + case 2: return GLFW_HAT_RIGHT_UP; + case 3: return GLFW_HAT_RIGHT; + case 4: return GLFW_HAT_RIGHT_DOWN; + case 5: return GLFW_HAT_DOWN; + case 6: return GLFW_HAT_LEFT_DOWN; + case 7: return GLFW_HAT_LEFT; + case 8: return GLFW_HAT_LEFT_UP; + default: return GLFW_HAT_CENTERED; + } +} + +static void +AMIGAINPUT_Close(_GLFWjoystick * joystick) +{ + dprintf("Closing joystick #%d (AI ID=%ld)\n", joystick->os4js.instance_id, joystick->os4js.joystickList[joystick->os4js.instance_id].id); + if (joystick->os4js.hwdata) { +#if OLDSDK + GLFW_IAIN->AIN_ReleaseDevice(joystick->os4js.hwdata->context, joystick->os4js.hwdata->handle); +#else + GLFW_IAIN->ReleaseDevice(joystick->os4js.hwdata->context, joystick->os4js.hwdata->handle); +#endif + + _glfw_free(joystick->os4js.hwdata); + joystick->os4js.hwdata = NULL; + } +} + +/* Function to open a joystick for use. + The joystick to open is specified by the index field of the joystick. + This should fill the buttonCount and axisCount fields of the joystick structure. + It returns 0, or -1 if there is an error. + */ +static int +AMIGAINPUT_Open(_GLFWjoystick * joysticks, int device_index) +{ + _GLFWjoystick * joystick = joysticks + device_index; + AIN_DeviceHandle *handle; + AIN_DeviceID id = joystick->os4js.joystickList[joystick->os4js.instance_id].id; + +#if OLDSDK + handle = GLFW_IAIN->AIN_ObtainDevice(_glfw.os4js.joystickContext, id); +#else + handle = GLFW_IAIN->ObtainDevice(_glfw.os4js.joystickContext, id); +#endif + + printf("Opening joystick #%ld (AI ID=%ld)\n", joystick->os4js.instance_id, id); + + if (handle) { + joystick->os4js.hwdata = _glfw_calloc(1, sizeof(struct joystick_hwdata)); + + if (joystick->os4js.hwdata) { + struct joystick_hwdata *hwdata = joystick->os4js.hwdata; + unsigned int num_axes = 0; + unsigned int num_buttons = 0; + unsigned int num_hats = 0; + TEXT tmpstr[32]; + uint32 tmpoffset; + + int i; + BOOL result = TRUE; + + joystick->os4js.hwdata->handle = handle; + joystick->os4js.hwdata->context = _glfw.os4js.joystickContext; + + strncpy(joystick->name, joystick->os4js.joystickList[joystick->os4js.instance_id].name, sizeof(joystick->name) - 1); + + /* Query number of axes, buttons and hats the device has */ +#if OLDSDK + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_NUMAXES, 0, &num_axes, 4); + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_NUMBUTTONS, 0, &num_buttons, 4); + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_NUMHATS, 0, &num_hats, 4); +#else + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_NUMAXES, 0, &num_axes, 4); + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_NUMBUTTONS, 0, &num_buttons, 4); + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_NUMHATS, 0, &num_hats, 4); +#endif + + printf ("Found %d axes, %d buttons, %d hats\n", num_axes, num_buttons, num_hats); + + joystick->axisCount = num_axes < MAX_AXES ? num_axes : MAX_AXES; + joystick->buttonCount = num_buttons < MAX_BUTTONS ? num_buttons : MAX_BUTTONS; + joystick->hatCount = num_hats < MAX_HATS ? num_hats : MAX_HATS; + + // Ensure all axis names are null terminated + for (i = 0; i < MAX_AXES; i++) + joystick->os4js.hwdata->axisName[i][0] = 0; + + /* Query offsets in ReadDevice buffer for axes' data */ + for (i = 0; i < joystick->axisCount; i++) { +#if OLDSDK + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_AXIS_OFFSET, i, &(hwdata->axisBufferOffset[i]), 4); + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_AXISNAME, i, &(hwdata->axisName[i][0]), 32 ); +#else + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_AXIS_OFFSET, i, &(hwdata->axisBufferOffset[i]), 4); + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_AXISNAME, i, &(hwdata->axisName[i][0]), 32 ); +#endif + } + + // Sort the axes so that X and Y come first + for (i = 0; i < joystick->axisCount; i++) { + if ( ( strcasecmp( &joystick->os4js.hwdata->axisName[i][0], "X-Axis" ) == 0 ) && ( i != 0 ) ) { + // Back up the zero position axis data + tmpoffset = joystick->os4js.hwdata->axisBufferOffset[0]; + strlcpy( tmpstr, joystick->os4js.hwdata->axisName[0], 32 ); + + // Move this one to zero + joystick->os4js.hwdata->axisBufferOffset[0] = joystick->os4js.hwdata->axisBufferOffset[i]; + strlcpy( joystick->os4js.hwdata->axisName[0], joystick->os4js.hwdata->axisName[i], 32 ); + + // Put the old 0 here + joystick->os4js.hwdata->axisBufferOffset[i] = tmpoffset; + strlcpy( joystick->os4js.hwdata->axisName[i], tmpstr, 32 ); + + continue; + } + + if ( ( strcasecmp( &joystick->os4js.hwdata->axisName[i][0], "Y-Axis" ) == 0 ) && ( i != 1 ) ) { + // Back up the position 1 axis data + tmpoffset = joystick->os4js.hwdata->axisBufferOffset[1]; + strlcpy( tmpstr, joystick->os4js.hwdata->axisName[1], 32 ); + + // Move this one to position 1 + joystick->os4js.hwdata->axisBufferOffset[1] = joystick->os4js.hwdata->axisBufferOffset[i]; + strlcpy( joystick->os4js.hwdata->axisName[1], joystick->os4js.hwdata->axisName[i], 32 ); + + // Put the old 1 here + joystick->os4js.hwdata->axisBufferOffset[i] = tmpoffset; + strlcpy( joystick->os4js.hwdata->axisName[i], tmpstr, 32 ); + + continue; + } + } + + /* Query offsets in ReadDevice buffer for buttons' data */ + for (i = 0; i < joystick->buttonCount; i++) { +#if OLDSDK + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_BUTTON_OFFSET, i, &(joystick->os4js.hwdata->buttonBufferOffset[i]), 4); +#else + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_BUTTON_OFFSET, i, &(joystick->os4js.hwdata->buttonBufferOffset[i]), 4); +#endif + } + + /* Query offsets in ReadDevice buffer for hats' data */ + for (i = 0; i < joystick->hatCount; i++) { +#if OLDSDK + result = result && GLFW_IAIN->AIN_Query(joystick->os4js.hwdata->context, id, AINQ_HAT_OFFSET, i, &(hwdata->hatBufferOffset[i]), 4); +#else + result = result && GLFW_IAIN->Query(joystick->os4js.hwdata->context, id, AINQ_HAT_OFFSET, i, &(hwdata->hatBufferOffset[i]), 4); +#endif + } + + if (result) { + char guid[33]; + // Generate a joystick GUID that matches the SDL 2.0.5+ one + sprintf(guid, "78696e707574%02x000000000000000000", handle->DeviceID & 0xff); + _glfwAllocJoystick(joystick->name, guid, joystick->axisCount, joystick->buttonCount, joystick->hatCount); + + printf("Successful\n"); + return 0; + } + } + +#if OLDSDK + GLFW_IAIN->AIN_ReleaseDevice (_glfw.os4js.joystickContext, handle); +#else + GLFW_IAIN->ReleaseDevice (_glfw.os4js.joystickContext, handle); +#endif + } + + printf("Failed\n"); + + return GLFW_FALSE; +} + +/* + * Callback to enumerate joysticks + */ +static BOOL +AMIGAINPUT_EnumerateJoysticks(AIN_Device *device, void *UserData) +{ + APTR context = ((struct enumPacket *)UserData)->context; + uint32 *count = ((struct enumPacket *)UserData)->count; + struct joystick *joy = &((struct enumPacket *)UserData)->joyList[*count]; + + BOOL result = FALSE; + + if (*count < MAX_JOYSTICKS) { + printf("ENUMJOY: id=%ld, type=%ld, axes=%ld, buttons=%ld\n", + *count, + (int32)device->Type, + (int32)device->NumAxes, + (int32)device->NumButtons); + + if (device->Type == AINDT_JOYSTICK) { + /* AmigaInput can report devices even when there's no + * physical stick present. We take some steps to try and + * ignore such bogus devices. + * + * First, check whether we have a useful number of axes and buttons + */ + if ((device->NumAxes > 0) && (device->NumButtons > 0)) { + /* Then, check whether we can actually obtain the device + */ +#if OLDSDK + AIN_DeviceHandle *handle = GLFW_IAIN->AIN_ObtainDevice (context, device->DeviceID); +#else + AIN_DeviceHandle *handle = GLFW_IAIN->ObtainDevice (context, device->DeviceID); +#endif + + if (handle) { + /* Okay. This appears to be a valid device. We'll report it to GLFW. + */ + joy->id = device->DeviceID; + joy->name = _glfw_strdup(device->DeviceName); + + printf("Found joystick #%d (AI ID=%ld) '%s'\n", *count, joy->id, joy->name); + + (*count)++; + +#if OLDSDK + GLFW_IAIN->AIN_ReleaseDevice (context, handle); +#else + GLFW_IAIN->ReleaseDevice (context, handle); +#endif + + result = TRUE; + } + else + printf("Failed to obtain joystick '%s' (AI ID=%ld) - ignoring.\n", device->DeviceName, device->DeviceID); + } + else + printf("Joystick '%s' (AI ID=%ld) has no axes/buttons - ignoring.\n", device->DeviceName, device->DeviceID); + } + } + return result; +} ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// @@ -35,21 +285,151 @@ GLFWbool _glfwInitJoysticksOS4(void) { - return GLFW_TRUE; + printf("_glfwInitJoysticksOS4\n"); + GLFW_AIN_Base = IExec->OpenLibrary("AmigaInput.library", 51); + + if (GLFW_AIN_Base) { + GLFW_IAIN = (struct AIN_IFace *) IExec->GetInterface(GLFW_AIN_Base, "main", 1, NULL); + + if (!GLFW_IAIN) { + IExec->CloseLibrary(GLFW_AIN_Base); + return GLFW_FALSE; + } +#if OLDSDK + _glfw.os4js.joystickContext = GLFW_IAIN->AIN_CreateContext(1, NULL); +#else + _glfw.os4js.joystickContext = GLFW_IAIN->CreateContext(1, NULL); +#endif + if (_glfw.os4js.joystickContext) { + struct enumPacket packet = { + _glfw.os4js.joystickContext, + &_glfw.os4js.joystickCount, + &_glfw.os4js.joystickList[0] + }; + +#if OLDSDK + BOOL result = GLFW_IAIN->AIN_EnumDevices(_glfw.os4js.joystickContext, AMIGAINPUT_EnumerateJoysticks, &packet); +#else + BOOL result = GLFW_IAIN->EnumDevices(_glfw.os4js.joystickContext, AMIGAINPUT_EnumerateJoysticks, &packet); +#endif + printf("EnumDevices returned %d\n", result); + printf("Found %d joysticks\n", _glfw.os4js.joystickCount); + + if (result) { + /* + + NOTE: AI doesn't seem to handle hotplugged/removed joysticks very well. + Report only devices detected at startup to GLFW. + + */ + int i; + + for (i = 0; i < _glfw.os4js.joystickCount; i++) { + printf("Add joystick %d\n", i); + AMIGAINPUT_Open(_glfw.joysticks, i); + } + } + return GLFW_TRUE; + } + } else { + printf("Failed to open AmigaInput.library\n"); + } + + return GLFW_FALSE; } void _glfwTerminateJoysticksOS4(void) { + printf("_glfwTerminateJoysticksOS4\n"); + uint32 i; + + for (i = 0; i < _glfw.os4js.joystickCount; i++) { + printf("_glfw_free joystickList[i].name\n"); + AMIGAINPUT_Close(_glfw.joysticks + i); + _glfw_free((char *)_glfw.os4js.joystickList[i].name); + } + + _glfw.os4js.joystickCount = 0; + + if (_glfw.os4js.joystickContext) { + printf("AIN_DeleteContext\n"); +#if OLDSDK + GLFW_IAIN->AIN_DeleteContext(_glfw.os4js.joystickContext); +#else + GLFW_IAIN->DeleteContext(_glfw.os4js.joystickContext); +#endif + _glfw.os4js.joystickContext = NULL; + } + + IExec->DropInterface((void *) GLFW_IAIN); + IExec->CloseLibrary(GLFW_AIN_Base); } -int _glfwPollJoystickOS4(_GLFWjoystick* js, int mode) -{ +int _glfwPollJoystickOS4(_GLFWjoystick* joystick, int mode) +{ + struct joystick_hwdata *hwdata = joystick->os4js.hwdata; + void *buffer; + + //printf("Called %p\n", hwdata); + + /* + * Poll device for data + */ +#if OLDSDK + if (hwdata && GLFW_IAIN->AIN_ReadDevice(hwdata->context, hwdata->handle, &buffer)) +#else + if (hwdata && GLFW_IAIN->ReadDevice(hwdata->context, hwdata->handle, &buffer)) +#endif + { + int i; + + /* Extract axis data from buffer and notify GLFW of any changes + * in axis state + */ + for (i = 0; i < joystick->axisCount; i++) { + int axisdata = BUFFER_OFFSET(buffer, hwdata->axisBufferOffset[i]); + + /* Clamp axis data to 16-bits to work around possible AI driver bugs */ + if (axisdata > 32767) axisdata = 32767; + if (axisdata < -32768) axisdata = -32768; + + if (axisdata != hwdata->axisData[i]) { + _glfwInputJoystickAxis(joystick, i, (float) axisdata); + hwdata->axisData[i] = axisdata; + } + } + + /* Extract button data from buffer and notify GLFW of any changes + * in button state + */ + for (i = 0; i < joystick->buttonCount; i++) { + int buttondata = BUFFER_OFFSET(buffer, hwdata->buttonBufferOffset[i]); + + if (buttondata != hwdata->buttonData[i]) { + _glfwInputJoystickButton(joystick, i, buttondata ? GLFW_PRESS : GLFW_RELEASE); + hwdata->buttonData[i] = buttondata; + } + } + + /* Extract hat data from buffer and notify GLFW of any changes + * in hat state + */ + for (i = 0; i < joystick->hatCount; i++) { + int hatdata = BUFFER_OFFSET(buffer, hwdata->hatBufferOffset[i]); + + if (hatdata != hwdata->hatData[i]) { + _glfwInputJoystickHat(joystick, i, AMIGAINPUT_MapHatData(hatdata)); + hwdata->hatData[i] = hatdata; + } + } + return GLFW_TRUE; + } return GLFW_FALSE; } const char* _glfwGetMappingNameOS4(void) { - return ""; + return "AmigaOS4"; } void _glfwUpdateGamepadGUIDOS4(char* guid) diff --git a/src/os4_joystick.h b/src/os4_joystick.h new file mode 100644 index 00000000..29915144 --- /dev/null +++ b/src/os4_joystick.h @@ -0,0 +1,79 @@ +//======================================================================== +// GLFW 3.4 - www.glfw.org +//------------------------------------------------------------------------ +// Copyright (c) 2006-2017 Camilla Löwy +// +// 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 OLDSDK 1 + +#include +#include + +#define MAX_JOYSTICKS 32 + +#define MAX_AXES 8 +#define MAX_BUTTONS 16 +#define MAX_HATS 8 + +#define BUFFER_OFFSET(buffer, offset) (((int32 *)buffer)[offset]) + +struct joystick +{ + AIN_DeviceID id; + const char *name; +}; + +/* Per-joystick data private to driver */ +struct joystick_hwdata +{ + AIN_DeviceHandle *handle; + APTR context; + + uint32 axisBufferOffset[MAX_AXES]; + int32 axisData[MAX_AXES]; + TEXT axisName[MAX_AXES][32]; + + uint32 buttonBufferOffset[MAX_BUTTONS]; + int32 buttonData[MAX_BUTTONS]; + + uint32 hatBufferOffset[MAX_HATS]; + int32 hatData[MAX_HATS]; +}; + +/* A handy container to encapsulate the information we + * need when enumerating joysticks on the system. + */ +struct enumPacket +{ + APTR context; + uint32 *count; + struct joystick *joyList; +}; + +GLFWbool _glfwInitJoysticksOS4(void); +void _glfwTerminateJoysticksOS4(void); +int _glfwPollJoystickOS4(_GLFWjoystick* js, int mode); +const char* _glfwGetMappingNameOS4(void); +void _glfwUpdateGamepadGUIDOS4(char* guid); + +void _glfwDetectJoystickConnectionOS4(void); \ No newline at end of file diff --git a/src/os4_platform.h b/src/os4_platform.h index 6e9913a9..c7979711 100644 --- a/src/os4_platform.h +++ b/src/os4_platform.h @@ -68,15 +68,18 @@ #include #endif +#include "os4_joystick.h" + #define MIN_MINIGLVERSION 2 #define MIN_OGLES2_VERSION 0 -#define GLFW_OS4_WINDOW_STATE _GLFWwindowOS4 os4; -#define GLFW_OS4_LIBRARY_WINDOW_STATE _GLFWlibraryOS4 os4; -#define GLFW_OS4_MONITOR_STATE _GLFWmonitorOS4 os4; -#define GLFW_OS4_CONTEXT_STATE _GLFWcontextGL gl; - -#define GLFW_OS4_CURSOR_STATE _GLFWcursorOS4 os4; +#define GLFW_OS4_WINDOW_STATE _GLFWwindowOS4 os4; +#define GLFW_OS4_LIBRARY_WINDOW_STATE _GLFWlibraryOS4 os4; +#define GLFW_OS4_MONITOR_STATE _GLFWmonitorOS4 os4; +#define GLFW_OS4_CONTEXT_STATE _GLFWcontextGL gl; +#define GLFW_OS4_JOYSTICK_STATE _GLFWjoystickOS4 os4js; +#define GLFW_OS4_LIBRARY_JOYSTICK_STATE _GLFWjoystickOS4 os4js; +#define GLFW_OS4_CURSOR_STATE _GLFWcursorOS4 os4; #define GLFW_OS4_LIBRARY_CONTEXT_STATE #define GID_ICONIFY 123 @@ -145,9 +148,9 @@ typedef struct _GLFWmonitorOS4 GLFWgammaramp ramp; } _GLFWmonitorOS4; -// X11-specific per-cursor data +// OS4-specific per-cursor data // -typedef struct _GLFWcursorX11 +typedef struct _GLFWcursorOS4 { Object *handle; uint32_t *imageData; @@ -155,8 +158,7 @@ typedef struct _GLFWcursorX11 // OS4-specific global data // -typedef struct _GLFWlibraryOS4 -{ +typedef struct _GLFWlibraryOS4 { STRPTR appName; int xcursor; @@ -173,8 +175,20 @@ typedef struct _GLFWlibraryOS4 struct Screen *publicScreen; _GLFWwindow *focusedWindow; + // The window whose disabled cursor mode is active + _GLFWwindow *disabledCursorWindow; } _GLFWlibraryOS4; +// OS4-specific joystick data +// +typedef struct _GLFWjoystickOS4 { + struct joystick_hwdata *hwdata; + uint32 joystickCount; + struct joystick joystickList [MAX_JOYSTICKS]; + APTR joystickContext; + uint32 instance_id; +} _GLFWjoystickOS4; + void _glfwPollMonitorsOS4(void); GLFWbool _glfwConnectOS4(int platformID, _GLFWplatform* platform); @@ -242,23 +256,26 @@ const char* _glfwGetClipboardStringOS4(void); const char* _glfwGetScancodeNameOS4(int scancode); int _glfwGetKeyScancodeOS4(int key); +void _glfwGetRequiredInstanceExtensionsOS4(char** extensions); +int _glfwGetPhysicalDevicePresentationSupportOS4(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); +VkResult _glfwCreateWindowSurfaceOS4(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); +GLFWbool _glfwCreateContextGL(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig); + +EGLenum _glfwGetEGLPlatformOS4(EGLint** attribs); +EGLNativeDisplayType _glfwGetEGLNativeDisplayOS4(void); +EGLNativeWindowType _glfwGetEGLNativeWindowOS4(_GLFWwindow* window); + +void _glfwPollMonitorsOS4(void); + GLFWbool _glfwInitJoysticksOS4(void); void _glfwTerminateJoysticksOS4(void); int _glfwPollJoystickOS4(_GLFWjoystick* js, int mode); const char* _glfwGetMappingNameOS4(void); void _glfwUpdateGamepadGUIDOS4(char* guid); - -void _glfwGetRequiredInstanceExtensionsOS4(char** extensions); -int _glfwGetPhysicalDevicePresentationSupportOS4(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); -VkResult _glfwCreateWindowSurfaceOS4(VkInstance instance, _GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); - -void _glfwPollMonitorsOS4(void); - - /************************************************************************************/ /********************************* AmigaOS4 METHODS *********************************/ /************************************************************************************/ -#define DEBUG +//#define DEBUG #ifndef DEBUG # define dprintf(format, args...) diff --git a/src/os4_window.c b/src/os4_window.c index ac58b1fc..9a7f3f6c 100644 --- a/src/os4_window.c +++ b/src/os4_window.c @@ -68,6 +68,29 @@ static struct Hook OS4_BackFillHook = { 0 /* h_Data */ }; +static ULONG +OS4_MapCursorIdToNative(int id) +{ + switch (id) { + case GLFW_ARROW_CURSOR: return POINTERTYPE_NORMAL; + case GLFW_IBEAM_CURSOR: return POINTERTYPE_SELECT; //54.21 + //case SDL_SYSTEM_CURSOR_WAITARROW: + //case SDL_SYSTEM_CURSOR_WAIT: return POINTERTYPE_BUSY; + case GLFW_CROSSHAIR_CURSOR: return POINTERTYPE_CROSS; + case GLFW_RESIZE_NWSE_CURSOR: return POINTERTYPE_NORTHWESTSOUTHEASTRESIZE; + case GLFW_RESIZE_NESW_CURSOR: return POINTERTYPE_NORTHEASTSOUTHWESTRESIZE; + case GLFW_RESIZE_EW_CURSOR: return POINTERTYPE_EASTWESTRESIZE; + case GLFW_RESIZE_NS_CURSOR: return POINTERTYPE_NORTHSOUTHRESIZE; + case GLFW_NOT_ALLOWED_CURSOR: return POINTERTYPE_NOTALLOWED; + case GLFW_POINTING_HAND_CURSOR: return POINTERTYPE_HAND; + // + case GLFW_RESIZE_ALL_CURSOR: + default: + dprintf("Unknown mapping from type %d\n", id); + return POINTERTYPE_NORMAL; + } +} + static void applySizeLimits(_GLFWwindow* window, int* width, int* height) { if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE) @@ -113,13 +136,58 @@ static void releaseMonitor(_GLFWwindow* window) _glfwInputMonitorWindow(window->monitor, NULL); } +// Apply disabled cursor mode to a focused window +// +static void disableCursor(_GLFWwindow* window) +{ + _glfw.os4.disabledCursorWindow = window; +} + +// Exit disabled cursor mode for the specified window +// +static void enableCursor(_GLFWwindow* window) +{ + _glfw.os4.disabledCursorWindow = NULL; +} + +// Returns whether the cursor is in the content area of the specified window +// +static GLFWbool cursorInContentArea(_GLFWwindow* window) +{ + return GLFW_TRUE; +} + +// Updates the cursor image according to its cursor mode +// +static void updateCursorImage(_GLFWwindow* window) +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL) + { + if (window->cursor) { + IIntuition->SetWindowPointer( + window->os4.handle, + WA_Pointer, window->cursor->os4.handle, + TAG_DONE); + } + else { + IIntuition->SetWindowPointer( + window->os4.handle, + //WA_PointerType, type, + TAG_DONE); + } + } + else { + //SetCursor(NULL); + } +} + static int createNativeWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig, int windowType) { if (window->monitor) { - printf("fitToMonitor\n"); + dprintf("fitToMonitor\n"); fitToMonitor(window); } else @@ -155,6 +223,7 @@ static int createNativeWindow(_GLFWwindow* window, WA_MaxWidth, _glfw.os4.publicScreen->Width, WA_MaxHeight, _glfw.os4.publicScreen->Height, WA_Flags, windowFlags, + WA_Activate, TRUE, WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_MOUSEMOVE | IDCMP_MOUSEBUTTONS | @@ -174,7 +243,7 @@ static int createNativeWindow(_GLFWwindow* window, /* If we have a valid handle return GLFW_TRUE */ if (window->os4.handle) { - window->os4.title = wndconfig->title; + window->os4.title = (char *) wndconfig->title; _glfwGetWindowPosOS4(window, &window->os4.xpos, &window->os4.ypos); _glfwGetWindowSizeOS4(window, &window->os4.width, &window->os4.height); @@ -189,6 +258,7 @@ static int createNativeWindow(_GLFWwindow* window, if (wndconfig->autoIconify) { OS4_IconifyWindow(window); } + dprintf("Window Created\n"); return GLFW_TRUE; } @@ -206,13 +276,21 @@ int _glfwCreateWindowOS4(_GLFWwindow* window, const _GLFWctxconfig* ctxconfig, const _GLFWfbconfig* fbconfig) { - if (!createNativeWindow(window, wndconfig, fbconfig, ctxconfig->client)) + dprintf("_glfwCreateWindowOS4 enter\n"); + + if (!createNativeWindow(window, wndconfig, fbconfig, ctxconfig->client)) { + dprintf("Cannot create native window\n"); return GLFW_FALSE; + } if (ctxconfig->client != GLFW_NO_API) { - if (!_glfwCreateContextGL(window, ctxconfig, fbconfig)) + dprintf("Creating context\n"); + if (!_glfwCreateContextGL(window, ctxconfig, fbconfig)) { + dprintf("Error creating context\n"); return GLFW_FALSE; + } + dprintf("Context created\n"); } if (window->monitor) @@ -221,15 +299,13 @@ int _glfwCreateWindowOS4(_GLFWwindow* window, _glfwFocusWindowOS4(window); acquireMonitor(window); } + dprintf("_glfwCreateWindowOS4 exit\n"); return GLFW_TRUE; } void _glfwDestroyWindowOS4(_GLFWwindow* window) { - if (window->context.destroy) - window->context.destroy(window); - if (window->os4.appWin) { IWorkbench->RemoveAppWindow(window->os4.appWin); window->os4.appWin = NULL; @@ -240,6 +316,9 @@ void _glfwDestroyWindowOS4(_GLFWwindow* window) window->os4.appIcon = NULL; } + if (window->context.destroy) + window->context.destroy(window); + IIntuition->CloseWindow(window->os4.handle); if (window->os4.gadget) { @@ -593,6 +672,7 @@ void _glfwPollEventsOS4(void) { struct IntuiMessage *imsg; struct MyIntuiMessage msg; + memset(&msg, 0, sizeof(struct MyIntuiMessage)); while ((imsg = (struct IntuiMessage *)IExec->GetMsg(_glfw.os4.userPort))) { @@ -622,7 +702,7 @@ void _glfwPollEventsOS4(void) _glfwInputKey(window, key, rawkey, GLFW_PRESS, mods); if (text[0] && text[0] < 0x80) { - _glfwInputChar(window, text, mods, plain); + _glfwInputChar(window, text[0], mods, plain); } } else { _glfwInputKey(window, key, rawkey, GLFW_RELEASE, mods); @@ -673,8 +753,8 @@ void _glfwPollEventsOS4(void) break; case IDCMP_ACTIVEWINDOW: - //if (window->cursorMode == GLFW_CURSOR_DISABLED) - // disableCursor(window); + if (window->cursorMode == GLFW_CURSOR_DISABLED) + disableCursor(window); _glfwInputWindowFocus(window, GLFW_TRUE); //OS4_HandleActivation(_this, &msg, SDL_TRUE); @@ -682,8 +762,8 @@ void _glfwPollEventsOS4(void) case IDCMP_INACTIVEWINDOW: //OS4_HandleActivation(_this, &msg, SDL_FALSE); - //if (window->cursorMode == GLFW_CURSOR_DISABLED) - // enableCursor(window); + if (window->cursorMode == GLFW_CURSOR_DISABLED) + enableCursor(window); _glfwInputWindowFocus(window, GLFW_FALSE); break; @@ -758,40 +838,52 @@ void _glfwSetCursorPosOS4(_GLFWwindow* window, double x, double y) void _glfwSetCursorModeOS4(_GLFWwindow* window, int mode) { + if (mode == GLFW_CURSOR_DISABLED) { + if (_glfwWindowFocusedOS4(window)) + disableCursor(window); + } + else if (_glfw.os4.disabledCursorWindow == window) + enableCursor(window); + else if (cursorInContentArea(window)) + updateCursorImage(window); } -int _glfwCreateCursorOS4(_GLFWcursor* cursor, - const GLFWimage* image, - int xhot, int yhot) -{ - uint32_t *buffer = OS4_CopyImageData(image); - - /* We need to pass some compatibility parameters even though we are going to use just ARGB pointer */ - Object *object = IIntuition->NewObject( - NULL, - POINTERCLASS, - POINTERA_BitMap, &fallbackPointerBitMap, - POINTERA_XOffset, xhot, - POINTERA_YOffset, yhot, - POINTERA_WordWidth, 1, - POINTERA_XResolution, POINTERXRESN_SCREENRES, - POINTERA_YResolution, POINTERYRESN_SCREENRES, - POINTERA_ImageData, buffer, - POINTERA_Width, image->width, - POINTERA_Height, image->height, - TAG_DONE); - if (object) { - printf("cursor created\n"); - cursor->os4.handle = object; - cursor->os4.imageData = buffer; - return GLFW_TRUE; +int _glfwCreateCursorOS4(_GLFWcursor* cursor, const GLFWimage* image, int xhot, int yhot) { + if (image->width > 64 || image->height > 64) { + dprintf("Invalid pointer size w:%d h:%d\n", image->width, image->height, xhot, yhot); } - printf("error creating cursor\n"); + else { + uint32_t *buffer = OS4_CopyImageData(image); + /* We need to pass some compatibility parameters even though we are going to use just ARGB pointer */ + cursor->os4.handle = IIntuition->NewObject( + NULL, + POINTERCLASS, + POINTERA_BitMap, &fallbackPointerBitMap, + POINTERA_XOffset, xhot, + POINTERA_YOffset, yhot, + POINTERA_WordWidth, 1, + POINTERA_XResolution, POINTERXRESN_SCREENRES, + POINTERA_YResolution, POINTERYRESN_SCREENRES, + POINTERA_ImageData, buffer, + POINTERA_Width, image->width, + POINTERA_Height, image->height, + TAG_DONE); + if (cursor->os4.handle) { + dprintf("cursor created\n"); + cursor->os4.imageData = buffer; + return GLFW_TRUE; + } + } + dprintf("error creating cursor\n"); return GLFW_FALSE; } int _glfwCreateStandardCursorOS4(_GLFWcursor* cursor, int shape) { + int id = OS4_MapCursorIdToNative(shape); + printf("_glfwCreateStandardCursorOS4 %02x %d\n", shape, id); + + //updateCursorImage return GLFW_TRUE; } @@ -808,6 +900,7 @@ void _glfwDestroyCursorOS4(_GLFWcursor* cursor) void _glfwSetCursorOS4(_GLFWwindow* window, _GLFWcursor* cursor) { + printf("_glfwSetCursorOS4\n"); } void _glfwSetClipboardStringOS4(const char* string) @@ -881,6 +974,46 @@ VkResult _glfwCreateWindowSurfaceOS4(VkInstance instance, return VK_ERROR_EXTENSION_NOT_PRESENT; } +EGLenum _glfwGetEGLPlatformOS4(EGLint** attribs) +{ + if (_glfw.egl.ANGLE_platform_angle) + { + int type = 0; + + if (_glfw.egl.ANGLE_platform_angle_opengl) + { + if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGL) + type = EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE; + else if (_glfw.hints.init.angleType == GLFW_ANGLE_PLATFORM_TYPE_OPENGLES) + type = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE; + } + + if (type) + { + *attribs = _glfw_calloc(3, sizeof(EGLint)); + (*attribs)[0] = EGL_PLATFORM_ANGLE_TYPE_ANGLE; + (*attribs)[1] = type; + (*attribs)[2] = EGL_NONE; + return EGL_PLATFORM_ANGLE_ANGLE; + } + } + + return 0; +} + +EGLNativeDisplayType _glfwGetEGLNativeDisplayOS4(void) +{ + return EGL_DEFAULT_DISPLAY; +} + +EGLNativeWindowType _glfwGetEGLNativeWindowOS4(_GLFWwindow* window) +{ + if (_glfw.egl.platform) + return &window->os4.handle; + else + return (EGLNativeWindowType) window->os4.handle; +} + /**********************************************************************************************/ /******************************************** PRIVATE METHODS *********************************/ /**********************************************************************************************/ @@ -1019,7 +1152,7 @@ static int OS4_TranslateState(int state) static uint32_t OS4_GetWindowFlags(_GLFWwindow* window, BOOL fullscreen) { - uint32_t windowFlags = WFLG_REPORTMOUSE | WFLG_RMBTRAP | WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH; + uint32_t windowFlags = WFLG_ACTIVATE | WFLG_REPORTMOUSE | WFLG_RMBTRAP | WFLG_SMART_REFRESH | WFLG_NOCAREREFRESH; if (fullscreen) { windowFlags |= WFLG_BORDERLESS | WFLG_BACKDROP; @@ -1172,7 +1305,7 @@ OS4_UniconifyWindow(_GLFWwindow* window) if (window->os4.appIcon) { IWorkbench->RemoveAppIcon(window->os4.appIcon); - window->os4.appIcon == NULL; + window->os4.appIcon = NULL; } IIntuition->SetWindowAttrs(window->os4.handle, WA_Hidden, FALSE, diff --git a/src/platform.h b/src/platform.h index 04dce761..35d13dcd 100644 --- a/src/platform.h +++ b/src/platform.h @@ -76,6 +76,7 @@ #define GLFW_OS4_MONITOR_STATE #define GLFW_OS4_CURSOR_STATE #define GLFW_OS4_LIBRARY_WINDOW_STATE + #define GLFW_OS4_JOYSTICK_STATE #define GLFW_GLX_CONTEXT_STATE #define GLFW_GLX_LIBRARY_CONTEXT_STATE #endif @@ -154,7 +155,8 @@ #define GLFW_PLATFORM_JOYSTICK_STATE \ GLFW_WIN32_JOYSTICK_STATE \ GLFW_COCOA_JOYSTICK_STATE \ - GLFW_LINUX_JOYSTICK_STATE + GLFW_LINUX_JOYSTICK_STATE \ + GLFW_OS4_JOYSTICK_STATE #define GLFW_PLATFORM_TLS_STATE \ GLFW_WIN32_TLS_STATE \ @@ -175,7 +177,8 @@ #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_OS4_LIBRARY_JOYSTICK_STATE #define GLFW_PLATFORM_LIBRARY_TIMER_STATE \ GLFW_WIN32_LIBRARY_TIMER_STATE \ diff --git a/tests/joysticks.c b/tests/joysticks.c index df000210..7a7aed2b 100644 --- a/tests/joysticks.c +++ b/tests/joysticks.c @@ -41,6 +41,7 @@ #define NK_INCLUDE_VERTEX_BUFFER_OUTPUT #define NK_INCLUDE_STANDARD_VARARGS #define NK_BUTTON_TRIGGER_ON_RELEASE +#define NK_BIGENDIAN #include #define NK_GLFW_GL2_IMPLEMENTATION