From e7e6144dec26e69c07df7d09763b17f802c38416 Mon Sep 17 00:00:00 2001 From: Gerasim Troeglazov <3dEyes@gmail.com> Date: Sun, 6 Feb 2022 20:53:45 +1000 Subject: [PATCH] GLFW: rework backend, implement window resize --- media-libs/glfw/glfw-3.3.6.recipe | 2 +- media-libs/glfw/patches/glfw-3.3.6.patchset | 773 ++++++++++++++++---- 2 files changed, 640 insertions(+), 135 deletions(-) diff --git a/media-libs/glfw/glfw-3.3.6.recipe b/media-libs/glfw/glfw-3.3.6.recipe index 5fafa8b0a..ef6eb093a 100644 --- a/media-libs/glfw/glfw-3.3.6.recipe +++ b/media-libs/glfw/glfw-3.3.6.recipe @@ -7,7 +7,7 @@ COPYRIGHT="2002-2006 Marcus Geelnard 2006-2021 Camilla Löwy " LICENSE="Zlib" -REVISION="1" +REVISION="2" SOURCE_URI="https://github.com/glfw/glfw/archive/$portVersion.tar.gz" CHECKSUM_SHA256="ed07b90e334dcd39903e6288d90fa1ae0cf2d2119fec516cf743a0a404527c02" PATCHES="glfw-$portVersion.patchset" diff --git a/media-libs/glfw/patches/glfw-3.3.6.patchset b/media-libs/glfw/patches/glfw-3.3.6.patchset index 29394dd44..ca2f3fb96 100644 --- a/media-libs/glfw/patches/glfw-3.3.6.patchset +++ b/media-libs/glfw/patches/glfw-3.3.6.patchset @@ -1,6 +1,6 @@ -From 42bdcc918e31a327e48ac7fd2fe8477b1c009387 Mon Sep 17 00:00:00 2001 +From 88c7ff5c685df86ab96e0e238979bc20d1deb9c9 Mon Sep 17 00:00:00 2001 From: Gerasim Troeglazov <3dEyes@gmail.com> -Date: Sat, 15 Jan 2022 14:50:46 +1000 +Date: Sun, 6 Feb 2022 20:26:48 +1000 Subject: Add Haiku support @@ -42,7 +42,7 @@ index b4bbded..68aac62 100644 # Use X11 for window creation #-------------------------------------------------------------------- diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index b6dd86c..1696033 100644 +index b6dd86c..9ff9b28 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,12 @@ elseif (_GLFW_WAYLAND) @@ -51,10 +51,10 @@ index b6dd86c..1696033 100644 BASENAME idle-inhibit-unstable-v1) +elseif (_GLFW_HAIKU) + set(glfw_HEADERS ${common_HEADERS} haiku_platform.h haiku_joystick.h haiku_platform_window.h -+ haiku_platform_view.h posix_time.h posix_thread.h osmesa_context.h) ++ haiku_platform_view.h posix_time.h posix_thread.h haiku_context.h) + set(glfw_SOURCES ${common_SOURCES} haiku_init.cpp haiku_monitor.cpp haiku_window.cpp + haiku_platform_window.cpp haiku_platform_view.cpp haiku_joystick.cpp posix_time.c -+ posix_thread.c osmesa_context.c) ++ posix_thread.c haiku_context.cpp) elseif (_GLFW_OSMESA) set(glfw_HEADERS ${common_HEADERS} null_platform.h null_joystick.h posix_time.h posix_thread.h osmesa_context.h) @@ -71,14 +71,491 @@ index f418c99..631eb2d 100644 // Define this to 1 if building GLFW for OSMesa #cmakedefine _GLFW_OSMESA +diff --git a/src/haiku_context.cpp b/src/haiku_context.cpp +new file mode 100644 +index 0000000..f1038ed +--- /dev/null ++++ b/src/haiku_context.cpp +@@ -0,0 +1,373 @@ ++//======================================================================== ++// GLFW 3.3 OSMesa - www.glfw.org ++//------------------------------------------------------------------------ ++// Copyright (c) 2016 Google Inc. ++// Copyright (c) 2016-2017 Camilla Löwy ++// Copyright (c) 2022 Gerasim Troeglazov <3dEyes@gmail.com> ++// ++// 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. ++// ++//======================================================================== ++// Please use C89 style variable declarations in this file because VS 2010 ++//======================================================================== ++ ++#include ++#include ++#include ++ ++extern "C" { ++#include "internal.h" ++} ++ ++#include "haiku_platform_window.h" ++ ++static void makeContextCurrentOSMesa(_GLFWwindow* window) ++{ ++ if (window) ++ { ++ int width, height; ++ _glfwPlatformGetFramebufferSize(window, &width, &height); ++ ++ if (window->context.source == GLFW_NATIVE_CONTEXT_API) ++ { ++ window->context.osmesa.buffer = PLATFORM_VIEW(window)->GetBuffer(); ++ window->context.osmesa.width = PLATFORM_VIEW(window)->Width(); ++ window->context.osmesa.height = PLATFORM_VIEW(window)->Height(); ++ } else { ++ if ((window->context.osmesa.buffer == NULL) || ++ (width != window->context.osmesa.width) || ++ (height != window->context.osmesa.height)) ++ { ++ if (window->context.osmesa.buffer) ++ free(window->context.osmesa.buffer); ++ ++ window->context.osmesa.buffer = calloc(4, (size_t) width * height); ++ window->context.osmesa.width = width; ++ window->context.osmesa.height = height; ++ } ++ } ++ ++ if (!OSMesaMakeCurrent(window->context.osmesa.handle, ++ window->context.osmesa.buffer, ++ GL_UNSIGNED_BYTE, ++ width, height)) ++ { ++ _glfwInputError(GLFW_PLATFORM_ERROR, ++ "OSMesa: Failed to make context current"); ++ return; ++ } ++ ++ if (window->context.source == GLFW_NATIVE_CONTEXT_API) ++ OSMesaPixelStore(OSMESA_Y_UP, 0); ++ } ++ ++ _glfwPlatformSetTls(&_glfw.contextSlot, window); ++} ++ ++static GLFWglproc getProcAddressOSMesa(const char* procname) ++{ ++ return (GLFWglproc) OSMesaGetProcAddress(procname); ++} ++ ++static void destroyContextOSMesa(_GLFWwindow* window) ++{ ++ if (window->context.osmesa.handle) ++ { ++ OSMesaDestroyContext(window->context.osmesa.handle); ++ window->context.osmesa.handle = NULL; ++ } ++ ++ if (window->context.osmesa.buffer) ++ { ++ if (window->context.source == GLFW_OSMESA_CONTEXT_API) ++ free(window->context.osmesa.buffer); ++ ++ window->context.osmesa.width = 0; ++ window->context.osmesa.height = 0; ++ } ++} ++ ++static void swapBuffersOSMesa(_GLFWwindow* window) ++{ ++ if (window) ++ _glfwPlatformSwapBuffers(window); ++} ++ ++static void swapIntervalOSMesa(int interval) ++{ ++} ++ ++static int extensionSupportedOSMesa(const char* extension) ++{ ++ return GLFW_FALSE; ++} ++ ++ ++////////////////////////////////////////////////////////////////////////// ++////// GLFW internal API ////// ++////////////////////////////////////////////////////////////////////////// ++ ++GLFWbool _glfwInitOSMesa(void) ++{ ++ if (_glfw.osmesa.handle) ++ return GLFW_TRUE; ++ ++ _glfw.osmesa.handle = _glfw_dlopen("libOSMesa.so.8"); ++ ++ if (!_glfw.osmesa.handle) ++ { ++ _glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found"); ++ return GLFW_FALSE; ++ } ++ ++ _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt"); ++ _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs"); ++ _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext"); ++ _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent"); ++ _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer"); ++ _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer"); ++ _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress"); ++ _glfw.osmesa.PixelStore = (PFN_OSMesaPixelStore) ++ _glfw_dlsym(_glfw.osmesa.handle, "OSMesaPixelStore"); ++ ++ if (!_glfw.osmesa.CreateContextExt || ++ !_glfw.osmesa.DestroyContext || ++ !_glfw.osmesa.MakeCurrent || ++ !_glfw.osmesa.GetColorBuffer || ++ !_glfw.osmesa.GetDepthBuffer || ++ !_glfw.osmesa.GetProcAddress || ++ !_glfw.osmesa.PixelStore) ++ { ++ _glfwInputError(GLFW_PLATFORM_ERROR, ++ "OSMesa: Failed to load required entry points"); ++ ++ _glfwTerminateOSMesa(); ++ return GLFW_FALSE; ++ } ++ ++ return GLFW_TRUE; ++} ++ ++void _glfwTerminateOSMesa(void) ++{ ++ if (_glfw.osmesa.handle) ++ { ++ _glfw_dlclose(_glfw.osmesa.handle); ++ _glfw.osmesa.handle = NULL; ++ } ++} ++ ++#define setAttrib(a, v) \ ++{ \ ++ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ ++ attribs[index++] = a; \ ++ attribs[index++] = v; \ ++} ++ ++GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, ++ const _GLFWctxconfig* ctxconfig, ++ const _GLFWfbconfig* fbconfig) ++{ ++ OSMesaContext share = NULL; ++ const int accumBits = fbconfig->accumRedBits + ++ fbconfig->accumGreenBits + ++ fbconfig->accumBlueBits + ++ fbconfig->accumAlphaBits; ++ ++ if (ctxconfig->client == GLFW_OPENGL_ES_API) ++ { ++ _glfwInputError(GLFW_API_UNAVAILABLE, ++ "OSMesa: OpenGL ES is not available on OSMesa"); ++ return GLFW_FALSE; ++ } ++ ++ if (ctxconfig->share) ++ share = ctxconfig->share->context.osmesa.handle; ++ ++ if (OSMesaCreateContextAttribs) ++ { ++ int index = 0, attribs[40]; ++ ++ setAttrib(OSMESA_FORMAT, ctxconfig->source == GLFW_NATIVE_CONTEXT_API ? OSMESA_BGRA : OSMESA_RGBA); ++ setAttrib(OSMESA_DEPTH_BITS, fbconfig->depthBits); ++ setAttrib(OSMESA_STENCIL_BITS, fbconfig->stencilBits); ++ setAttrib(OSMESA_ACCUM_BITS, accumBits); ++ ++ if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE) ++ { ++ setAttrib(OSMESA_PROFILE, OSMESA_CORE_PROFILE); ++ } ++ else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE) ++ { ++ setAttrib(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE); ++ } ++ ++ if (ctxconfig->major != 1 || ctxconfig->minor != 0) ++ { ++ setAttrib(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major); ++ setAttrib(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor); ++ } ++ ++ if (ctxconfig->forward) ++ { ++ _glfwInputError(GLFW_VERSION_UNAVAILABLE, ++ "OSMesa: Forward-compatible contexts not supported"); ++ return GLFW_FALSE; ++ } ++ ++ setAttrib(0, 0); ++ ++ window->context.osmesa.handle = ++ OSMesaCreateContextAttribs(attribs, share); ++ } ++ else ++ { ++ if (ctxconfig->profile) ++ { ++ _glfwInputError(GLFW_VERSION_UNAVAILABLE, ++ "OSMesa: OpenGL profiles unavailable"); ++ return GLFW_FALSE; ++ } ++ ++ window->context.osmesa.handle = ++ OSMesaCreateContextExt(ctxconfig->source == GLFW_NATIVE_CONTEXT_API ? OSMESA_BGRA : OSMESA_RGBA, ++ fbconfig->depthBits, fbconfig->stencilBits, accumBits, share); ++ } ++ ++ if (window->context.osmesa.handle == NULL) ++ { ++ _glfwInputError(GLFW_VERSION_UNAVAILABLE, ++ "OSMesa: Failed to create context"); ++ return GLFW_FALSE; ++ } ++ ++ window->context.makeCurrent = makeContextCurrentOSMesa; ++ window->context.swapBuffers = swapBuffersOSMesa; ++ window->context.swapInterval = swapIntervalOSMesa; ++ window->context.extensionSupported = extensionSupportedOSMesa; ++ window->context.getProcAddress = getProcAddressOSMesa; ++ window->context.destroy = destroyContextOSMesa; ++ ++ return GLFW_TRUE; ++} ++ ++#undef setAttrib ++ ++ ++////////////////////////////////////////////////////////////////////////// ++////// GLFW native API ////// ++////////////////////////////////////////////////////////////////////////// ++ ++GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width, ++ int* height, int* format, void** buffer) ++{ ++ void* mesaBuffer; ++ GLint mesaWidth, mesaHeight, mesaFormat; ++ _GLFWwindow* window = (_GLFWwindow*) handle; ++ assert(window != NULL); ++ ++ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); ++ ++ if (window->context.source != GLFW_OSMESA_CONTEXT_API) ++ { ++ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); ++ return GLFW_FALSE; ++ } ++ ++ if (!OSMesaGetColorBuffer(window->context.osmesa.handle, ++ &mesaWidth, &mesaHeight, ++ &mesaFormat, &mesaBuffer)) ++ { ++ _glfwInputError(GLFW_PLATFORM_ERROR, ++ "OSMesa: Failed to retrieve color buffer"); ++ return GLFW_FALSE; ++ } ++ ++ if (width) ++ *width = mesaWidth; ++ if (height) ++ *height = mesaHeight; ++ if (format) ++ *format = mesaFormat; ++ if (buffer) ++ *buffer = mesaBuffer; ++ ++ return GLFW_TRUE; ++} ++ ++GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle, ++ int* width, int* height, ++ int* bytesPerValue, ++ void** buffer) ++{ ++ void* mesaBuffer; ++ GLint mesaWidth, mesaHeight, mesaBytes; ++ _GLFWwindow* window = (_GLFWwindow*) handle; ++ assert(window != NULL); ++ ++ _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE); ++ ++ if (window->context.source != GLFW_OSMESA_CONTEXT_API) ++ { ++ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); ++ return GLFW_FALSE; ++ } ++ ++ if (!OSMesaGetDepthBuffer(window->context.osmesa.handle, ++ &mesaWidth, &mesaHeight, ++ &mesaBytes, &mesaBuffer)) ++ { ++ _glfwInputError(GLFW_PLATFORM_ERROR, ++ "OSMesa: Failed to retrieve depth buffer"); ++ return GLFW_FALSE; ++ } ++ ++ if (width) ++ *width = mesaWidth; ++ if (height) ++ *height = mesaHeight; ++ if (bytesPerValue) ++ *bytesPerValue = mesaBytes; ++ if (buffer) ++ *buffer = mesaBuffer; ++ ++ return GLFW_TRUE; ++} ++ ++GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle) ++{ ++ _GLFWwindow* window = (_GLFWwindow*) handle; ++ _GLFW_REQUIRE_INIT_OR_RETURN(NULL); ++ ++ if (window->context.source != GLFW_OSMESA_CONTEXT_API) ++ { ++ _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL); ++ return NULL; ++ } ++ ++ return window->context.osmesa.handle; ++} +diff --git a/src/haiku_context.h b/src/haiku_context.h +new file mode 100644 +index 0000000..1d3957e +--- /dev/null ++++ b/src/haiku_context.h +@@ -0,0 +1,92 @@ ++//======================================================================== ++// GLFW 3.3 OSMesa - www.glfw.org ++//------------------------------------------------------------------------ ++// Copyright (c) 2016 Google Inc. ++// Copyright (c) 2016-2017 Camilla Löwy ++// Copyright (c) 2022 Gerasim Troeglazov <3dEyes@gmail.com> ++// ++// 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 OSMESA_RGBA 0x1908 ++#define OSMESA_BGRA 0x1 ++#define OSMESA_FORMAT 0x22 ++#define OSMESA_DEPTH_BITS 0x30 ++#define OSMESA_STENCIL_BITS 0x31 ++#define OSMESA_ACCUM_BITS 0x32 ++#define OSMESA_PROFILE 0x33 ++#define OSMESA_CORE_PROFILE 0x34 ++#define OSMESA_COMPAT_PROFILE 0x35 ++#define OSMESA_CONTEXT_MAJOR_VERSION 0x36 ++#define OSMESA_CONTEXT_MINOR_VERSION 0x37 ++#define OSMESA_Y_UP 0x11 ++ ++typedef void* OSMesaContext; ++ ++typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextExt)(GLenum,GLint,GLint,GLint,OSMesaContext); ++typedef OSMesaContext (GLAPIENTRY * PFN_OSMesaCreateContextAttribs)(const int*,OSMesaContext); ++typedef void (GLAPIENTRY * PFN_OSMesaDestroyContext)(OSMesaContext); ++typedef int (GLAPIENTRY * PFN_OSMesaMakeCurrent)(OSMesaContext,void*,int,int,int); ++typedef int (GLAPIENTRY * PFN_OSMesaGetColorBuffer)(OSMesaContext,int*,int*,int*,void**); ++typedef int (GLAPIENTRY * PFN_OSMesaGetDepthBuffer)(OSMesaContext,int*,int*,int*,void**); ++typedef GLFWglproc (GLAPIENTRY * PFN_OSMesaGetProcAddress)(const char*); ++typedef void (GLAPIENTRY * PFN_OSMesaPixelStore)(int,int); ++#define OSMesaCreateContextExt _glfw.osmesa.CreateContextExt ++#define OSMesaCreateContextAttribs _glfw.osmesa.CreateContextAttribs ++#define OSMesaDestroyContext _glfw.osmesa.DestroyContext ++#define OSMesaMakeCurrent _glfw.osmesa.MakeCurrent ++#define OSMesaGetColorBuffer _glfw.osmesa.GetColorBuffer ++#define OSMesaGetDepthBuffer _glfw.osmesa.GetDepthBuffer ++#define OSMesaGetProcAddress _glfw.osmesa.GetProcAddress ++#define OSMesaPixelStore _glfw.osmesa.PixelStore ++ ++#define _GLFW_OSMESA_CONTEXT_STATE _GLFWcontextOSMesa osmesa ++#define _GLFW_OSMESA_LIBRARY_CONTEXT_STATE _GLFWlibraryOSMesa osmesa ++ ++typedef struct _GLFWcontextOSMesa ++{ ++ OSMesaContext handle; ++ int width; ++ int height; ++ void* buffer; ++} _GLFWcontextOSMesa; ++ ++typedef struct _GLFWlibraryOSMesa ++{ ++ void* handle; ++ ++ PFN_OSMesaCreateContextExt CreateContextExt; ++ PFN_OSMesaCreateContextAttribs CreateContextAttribs; ++ PFN_OSMesaDestroyContext DestroyContext; ++ PFN_OSMesaMakeCurrent MakeCurrent; ++ PFN_OSMesaGetColorBuffer GetColorBuffer; ++ PFN_OSMesaGetDepthBuffer GetDepthBuffer; ++ PFN_OSMesaGetProcAddress GetProcAddress; ++ PFN_OSMesaPixelStore PixelStore; ++} _GLFWlibraryOSMesa; ++ ++ ++GLFWbool _glfwInitOSMesa(void); ++void _glfwTerminateOSMesa(void); ++GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window, ++ const _GLFWctxconfig* ctxconfig, ++ const _GLFWfbconfig* fbconfig); ++ diff --git a/src/haiku_init.cpp b/src/haiku_init.cpp new file mode 100644 -index 0000000..60058c2 +index 0000000..9d4303b --- /dev/null +++ b/src/haiku_init.cpp -@@ -0,0 +1,218 @@ +@@ -0,0 +1,219 @@ +//======================================================================== -+// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> ++// Copyright (c) 2021-2022 Gerasim Troeglazov <3dEyes@gmail.com> +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages @@ -248,7 +725,8 @@ index 0000000..60058c2 + +int _glfwPlatformInit(void) +{ -+ if (!be_app) { ++ if (!be_app) ++ { + image_info info; + int32 cookie = 0; + if (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) { @@ -297,10 +775,10 @@ index 0000000..60058c2 +} diff --git a/src/haiku_joystick.cpp b/src/haiku_joystick.cpp new file mode 100644 -index 0000000..4b8b33a +index 0000000..2e8fc5a --- /dev/null +++ b/src/haiku_joystick.cpp -@@ -0,0 +1,145 @@ +@@ -0,0 +1,151 @@ +//======================================================================== +// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> +// @@ -378,7 +856,8 @@ index 0000000..4b8b33a +// +void _glfwTerminateJoysticksHaiku(void) +{ -+ for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) { ++ for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++) ++ { + if (_glfw.joysticks[jid].present) + delete (BJoystick*)(_glfw.joysticks[jid].haiku.device); + } @@ -391,10 +870,12 @@ index 0000000..4b8b33a +{ + BJoystick *joystick = (BJoystick*)js->haiku.device; + joystick->Update(); -+ if (mode & _GLFW_POLL_AXES) { ++ if (mode & _GLFW_POLL_AXES) ++ { + int16 axes[joystick->CountAxes()]; + joystick->GetAxisValues(axes); -+ for (int axesIdx = 0; axesIdx < joystick->CountAxes(); axesIdx++) { ++ for (int axesIdx = 0; axesIdx < joystick->CountAxes(); axesIdx++) ++ { + double value = 0; + if (axes[axesIdx] >= 0) + value = axes[axesIdx] / 32767.0; @@ -405,9 +886,11 @@ index 0000000..4b8b33a + } + } + -+ if (mode & _GLFW_POLL_BUTTONS) { ++ if (mode & _GLFW_POLL_BUTTONS) ++ { + uint32 buttonValues = joystick->ButtonValues(); -+ for (int buttonIdx = 0; buttonIdx < joystick->CountButtons(); buttonIdx++) { ++ for (int buttonIdx = 0; buttonIdx < joystick->CountButtons(); buttonIdx++) ++ { + bool buttonValue = buttonValues & (1 << buttonIdx); + bool lastButtonValue = js->haiku.lastButtonValues & (1 << buttonIdx); + if (buttonValue != lastButtonValue) @@ -419,7 +902,8 @@ index 0000000..4b8b33a + uint8 hatsValues[hatsCount]; + joystick->GetHatValues(hatsValues, 0); + -+ for (int i = 0; i < hatsCount; i++) { ++ for (int i = 0; i < hatsCount; i++) ++ { + const int states[9] = { + GLFW_HAT_CENTERED, + GLFW_HAT_UP, @@ -494,10 +978,10 @@ index 0000000..679bc80 +void _glfwTerminateJoysticksHaiku(void); diff --git a/src/haiku_monitor.cpp b/src/haiku_monitor.cpp new file mode 100644 -index 0000000..54d9f0d +index 0000000..a33a2a7 --- /dev/null +++ b/src/haiku_monitor.cpp -@@ -0,0 +1,142 @@ +@@ -0,0 +1,143 @@ +//======================================================================== +// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> +// @@ -540,12 +1024,14 @@ index 0000000..54d9f0d + mode.blueBits = 8; + mode.refreshRate = (int)refresh; + -+ if (monitor->modeCount > 0 && monitor->modes) { -+ for (int i = 0; i < monitor->modeCount; i++) { ++ if (monitor->modeCount > 0 && monitor->modes) ++ { ++ for (int i = 0; i < monitor->modeCount; i++) ++ { + if (monitor->modes[i].width == width && + monitor->modes[i].height == height && + monitor->modes[i].refreshRate == refresh) -+ return; ++ return; + } + } + @@ -639,10 +1125,9 @@ index 0000000..54d9f0d +void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) +{ +} -+ diff --git a/src/haiku_platform.h b/src/haiku_platform.h new file mode 100644 -index 0000000..3c5dbf4 +index 0000000..bfa0553 --- /dev/null +++ b/src/haiku_platform.h @@ -0,0 +1,71 @@ @@ -682,7 +1167,7 @@ index 0000000..3c5dbf4 + +#define _GLFW_PLATFORM_LIBRARY_WINDOW_STATE _GLFWlibraryHaiku haiku + -+#include "osmesa_context.h" ++#include "haiku_context.h" +#include "posix_time.h" +#include "posix_thread.h" +#include "haiku_joystick.h" @@ -703,7 +1188,7 @@ index 0000000..3c5dbf4 +} _GLFWwindowHaiku; + + -+// Cocoa-specific global data ++// Haiku-specific global data +// +typedef struct _GLFWlibraryHaiku +{ @@ -719,12 +1204,12 @@ index 0000000..3c5dbf4 +} _GLFWlibraryHaiku; diff --git a/src/haiku_platform_view.cpp b/src/haiku_platform_view.cpp new file mode 100644 -index 0000000..d8558f9 +index 0000000..d490e75 --- /dev/null +++ b/src/haiku_platform_view.cpp -@@ -0,0 +1,142 @@ +@@ -0,0 +1,135 @@ +//======================================================================== -+// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> ++// Copyright (c) 2021-2022 Gerasim Troeglazov <3dEyes@gmail.com> +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages @@ -751,24 +1236,17 @@ index 0000000..d8558f9 +#include "haiku_platform_view.h" + +HaikuPlatformView::HaikuPlatformView(BRect rect, int width, int height, _GLFWwindow* win) : -+ BView(rect, "HaikuPlatformView", B_FOLLOW_ALL, B_WILL_DRAW) ++ BView(rect, "HaikuPlatformView", B_FOLLOW_ALL, B_WILL_DRAW), ++ window(win), ++ bufferBitmap(NULL), ++ mouseMode(MOUSE_MODE_NORMAL) +{ -+ mouseMode = MOUSE_MODE_NORMAL; -+ pixelBufferWidth = width; -+ pixelBufferHeight = height; -+ window = win; -+ -+ BRect fbRect = BRect(0, 0, pixelBufferWidth - 1, pixelBufferHeight - 1); -+ bufferBitmap = new BBitmap(fbRect, B_RGB32, true); -+ pixelBuffer = (char*)malloc(bufferBitmap->BitsLength()); +} + +HaikuPlatformView::~HaikuPlatformView() +{ + if (bufferBitmap) + delete bufferBitmap; -+ if (pixelBuffer) -+ free(pixelBuffer); +} + +void @@ -776,7 +1254,8 @@ index 0000000..d8558f9 +{ + BMessageQueue *queue = (BMessageQueue*)(_glfw.haiku.messageQueue); + -+ switch (message->what) { ++ switch (message->what) ++ { + case B_MOUSE_DOWN: + { + SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); @@ -809,7 +1288,14 @@ index 0000000..d8558f9 + BView::MessageReceived(message); +} + -+void ++void ++HaikuPlatformView::AttachedToWindow() ++{ ++ ResizeBitmap(Bounds().IntegerWidth() + 1, Bounds().IntegerHeight() + 1); ++ BView::AttachedToWindow(); ++} ++ ++void +HaikuPlatformView::Draw(BRect rect) +{ + SetDrawingMode(B_OP_COPY); @@ -830,14 +1316,6 @@ index 0000000..d8558f9 +void +HaikuPlatformView::Repaint() +{ -+ uint32 bytesPerRow = bufferBitmap->BytesPerRow(); -+ -+ char *s_ptr = pixelBuffer + ((pixelBufferHeight - 1) * pixelBufferWidth) * 4; -+ char *d_ptr = (char*)bufferBitmap->Bits(); -+ -+ for (int i=0; i < pixelBufferHeight; i++, d_ptr += bytesPerRow, s_ptr -= bytesPerRow) -+ memcpy(d_ptr, s_ptr, bytesPerRow); -+ + if (LockLooperWithTimeout(10000) == B_OK) { + SetDrawingMode(B_OP_COPY); + DrawBitmap(bufferBitmap); @@ -847,32 +1325,32 @@ index 0000000..d8558f9 + +void +HaikuPlatformView::ResizeBitmap(int width, int height) -+{ -+ if(width == pixelBufferWidth && height == pixelBufferHeight) -+ return; ++{ ++ if (LockLooperWithTimeout(10000) == B_OK) ++ { ++ if (bufferBitmap) ++ { ++ if (width == Width() && height == Height()) ++ { ++ UnlockLooper(); ++ return; ++ } ++ delete bufferBitmap; ++ } + -+ if(LockLooper()) { -+ delete bufferBitmap; -+ free(pixelBuffer); -+ -+ pixelBufferWidth = width; -+ pixelBufferHeight = height; -+ -+ BRect fbRect = BRect(0, 0, pixelBufferWidth - 1, pixelBufferHeight - 1); -+ bufferBitmap = new BBitmap(fbRect, B_RGB32, true); -+ pixelBuffer = (char*)malloc(bufferBitmap->BitsLength()); ++ bufferBitmap = new BBitmap(BRect(0, 0, width - 1, height - 1), B_RGB32, true); + + UnlockLooper(); -+ } ++ } +} diff --git a/src/haiku_platform_view.h b/src/haiku_platform_view.h new file mode 100644 -index 0000000..8b0db24 +index 0000000..fe4ff46 --- /dev/null +++ b/src/haiku_platform_view.h -@@ -0,0 +1,82 @@ +@@ -0,0 +1,74 @@ +//======================================================================== -+// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> ++// Copyright (c) 2021-2022 Gerasim Troeglazov <3dEyes@gmail.com> +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages @@ -920,47 +1398,39 @@ index 0000000..8b0db24 + HaikuPlatformView(BRect rect, int width, int height, _GLFWwindow* win); + ~HaikuPlatformView(); + -+// virtual void MouseDown(BPoint point); -+// virtual void MouseUp(BPoint point); -+// virtual void MouseMoved(BPoint where, uint32 code, const BMessage *message); + virtual void MessageReceived(BMessage *message); + virtual void Draw(BRect r); ++ virtual void AttachedToWindow(); + + void Repaint(); + + void SetMouseMode(int32 mode); + -+ char* GetBuffer() { return pixelBuffer; } ++ char* GetBuffer() { return (char*)bufferBitmap->Bits(); } + uint32 GetBufferSize() { return bufferBitmap->BitsLength(); } + + void ResizeBitmap(int width, int height); + -+ int Width() { return pixelBufferWidth; } -+ int Height() { return pixelBufferHeight; } ++ int Width() { return bufferBitmap->Bounds().IntegerWidth() + 1; } ++ int Height() { return bufferBitmap->Bounds().IntegerHeight() + 1; } + + private: + _GLFWwindow* window; + + BBitmap* bufferBitmap; + -+ int pixelBufferWidth; -+ int pixelBufferHeight; -+ char* pixelBuffer; -+ -+// BPoint lastMousePosition; -+// uint32 lastButtons; + int32 mouseMode; +}; + +#endif //_HAIKU_PLATFORM_VIEW_H diff --git a/src/haiku_platform_window.cpp b/src/haiku_platform_window.cpp new file mode 100644 -index 0000000..d3b258d +index 0000000..af75685 --- /dev/null +++ b/src/haiku_platform_window.cpp -@@ -0,0 +1,117 @@ +@@ -0,0 +1,119 @@ +//======================================================================== -+// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> ++// Copyright (c) 2021-2022 Gerasim Troeglazov <3dEyes@gmail.com> +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages @@ -990,7 +1460,8 @@ index 0000000..d3b258d + +#include + -+HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, const char* title, window_type type, uint32 flags, _GLFWwindow* glwin) ++HaikuPlatformWindow::HaikuPlatformWindow(BRect frame, const char* title, window_type type, ++ uint32 flags, _GLFWwindow* glwin) + : BWindow(frame, title, type, flags) +{ + window = glwin; @@ -1012,17 +1483,18 @@ index 0000000..d3b258d +void +HaikuPlatformWindow::MessageReceived(BMessage *message) +{ -+ switch (message->what) { -+ case 'mSHO': ++ switch (message->what) ++ { ++ case kShowCursor: + fView->SetViewCursor(cursorStd); + break; -+ case 'mHID': ++ case kHideCursor: + fView->SetViewCursor(cursorEmpty); + break; -+ case 'mNOR': ++ case kMouseModeNormal: + fView->SetMouseMode(MOUSE_MODE_NORMAL); + break; -+ case 'mREL': ++ case kMouseModeRelative: + fView->SetMouseMode(MOUSE_MODE_RELATIVE); + break; + case B_UNMAPPED_KEY_UP: @@ -1047,8 +1519,8 @@ index 0000000..d3b258d +{ + BMessage *msg = new BMessage(B_WINDOW_RESIZED); + msg->AddPointer("window", (void*)window); -+ msg->AddFloat("width", width); -+ msg->AddFloat("height", height); ++ msg->AddFloat("width", width + 1); ++ msg->AddFloat("height", height + 1); + PLATFORM_QUEUE->AddMessage(msg); +} + @@ -1078,10 +1550,10 @@ index 0000000..d3b258d +} diff --git a/src/haiku_platform_window.h b/src/haiku_platform_window.h new file mode 100644 -index 0000000..9800439 +index 0000000..b2e5461 --- /dev/null +++ b/src/haiku_platform_window.h -@@ -0,0 +1,63 @@ +@@ -0,0 +1,68 @@ +//======================================================================== +// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> +// @@ -1116,6 +1588,11 @@ index 0000000..9800439 +#include +#include + ++const uint32 kShowCursor = 'mSHO'; ++const uint32 kHideCursor = 'mHID'; ++const uint32 kMouseModeNormal = 'mNOR'; ++const uint32 kMouseModeRelative = 'mREL'; ++ +#include "haiku_platform_view.h" + +class HaikuPlatformWindow : public BWindow { @@ -1147,12 +1624,12 @@ index 0000000..9800439 + diff --git a/src/haiku_window.cpp b/src/haiku_window.cpp new file mode 100644 -index 0000000..b043b40 +index 0000000..966b1f7 --- /dev/null +++ b/src/haiku_window.cpp -@@ -0,0 +1,687 @@ +@@ -0,0 +1,715 @@ +//======================================================================== -+// Copyright (c) 2021 Gerasim Troeglazov <3dEyes@gmail.com> ++// Copyright (c) 2021-2022 Gerasim Troeglazov <3dEyes@gmail.com> +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages @@ -1204,7 +1681,8 @@ index 0000000..b043b40 + + BRect winPos = BRect(100, 100, 100 + (wndconfig->width - 1), 100 + (wndconfig->height - 1)); + -+ if (window->monitor) { ++ if (window->monitor) ++ { + BScreen scr(B_MAIN_SCREEN_ID); + window->haiku.width = scr.Frame().Width() + 1; + window->haiku.height = scr.Frame().Height() + 1; @@ -1213,19 +1691,18 @@ index 0000000..b043b40 + + uint32 flags = B_NOT_RESIZABLE | B_NOT_ZOOMABLE; + -+#if 0 -+ if (wndconfig->resizable && !window->monitor) { ++ if (wndconfig->resizable && !window->monitor) ++ { + flags &= ~B_NOT_RESIZABLE; + flags &= ~B_NOT_ZOOMABLE; + } -+#endif + + HaikuPlatformWindow *haiku_window = new HaikuPlatformWindow(winPos, + wndconfig->title, B_TITLED_WINDOW, flags, window); + + window->haiku.object = (void*)(haiku_window); + window->haiku.mouseGrab = GLFW_FALSE; -+ ++ + if (window->monitor) + haiku_window->Show(); + @@ -1290,9 +1767,9 @@ index 0000000..b043b40 +{ + if (window->cursorMode == GLFW_CURSOR_NORMAL || + !PLATFORM_WINDOW(window)->IsActive()) { -+ PLATFORM_WINDOW(window)->PostMessage('mSHO'); ++ PLATFORM_WINDOW(window)->PostMessage(kShowCursor); + } else { -+ PLATFORM_WINDOW(window)->PostMessage('mHID'); ++ PLATFORM_WINDOW(window)->PostMessage(kHideCursor); + } +} + @@ -1304,7 +1781,7 @@ index 0000000..b043b40 + _glfwPlatformGetCursorPos(window, &_glfw.haiku.restoreCursorPosX, &_glfw.haiku.restoreCursorPosY); + updateCursorImage(window); + _glfwCenterCursorInContentArea(window); -+ PLATFORM_WINDOW(window)->PostMessage('mREL'); ++ PLATFORM_WINDOW(window)->PostMessage(kMouseModeRelative); +} + +// Exit disabled cursor mode for the specified window @@ -1315,7 +1792,7 @@ index 0000000..b043b40 + _glfwPlatformSetCursorPos(window, _glfw.haiku.restoreCursorPosX, _glfw.haiku.restoreCursorPosY); + window->haiku.mouseGrab = GLFW_FALSE; + updateCursorImage(window); -+ PLATFORM_WINDOW(window)->PostMessage('mNOR'); ++ PLATFORM_WINDOW(window)->PostMessage(kMouseModeNormal); +} + + @@ -1482,16 +1959,17 @@ index 0000000..b043b40 + +void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled) +{ -+#if 0 -+ uint32 flags = ((BWindow*)(window->haiku.wnd))->Flags(); -+ if (enabled) { ++ uint32 flags = PLATFORM_WINDOW(window)->Flags(); ++ if (enabled) ++ { + flags &= ~B_NOT_RESIZABLE; + flags &= ~B_NOT_ZOOMABLE; -+ } else { ++ } ++ else ++ { + flags |= B_NOT_RESIZABLE | B_NOT_ZOOMABLE; + } -+ ((BWindow*)(window->haiku.wnd))->SetFlags(flags); -+#endif ++ PLATFORM_WINDOW(window)->SetFlags(flags); +} + +void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled) @@ -1567,17 +2045,21 @@ index 0000000..b043b40 +void _glfwPlatformPollEvents(void) +{ + PLATFORM_QUEUE->Lock(); -+ while(!PLATFORM_QUEUE->IsEmpty()) { ++ while(!PLATFORM_QUEUE->IsEmpty()) ++ { + BMessage *message = PLATFORM_QUEUE->NextMessage(); + _GLFWwindow* window = (_GLFWwindow*)(message->GetPointer("window")); -+ switch(message->what) { ++ switch(message->what) ++ { + case B_MOUSE_DOWN: + { + int32 mod = modifiers(); + uint32 buttons = message->FindInt32("buttons"); + -+ if (buttons & B_PRIMARY_MOUSE_BUTTON) { -+ if (window->cursorMode == GLFW_CURSOR_DISABLED && window->haiku.mouseGrab == GLFW_FALSE) { ++ if (buttons & B_PRIMARY_MOUSE_BUTTON) ++ { ++ if (window->cursorMode == GLFW_CURSOR_DISABLED && window->haiku.mouseGrab == GLFW_FALSE) ++ { + window->haiku.mouseGrab = GLFW_TRUE; + disableCursor(window); + } @@ -1617,13 +2099,20 @@ index 0000000..b043b40 + BPoint where; + message->FindPoint("be:view_where", &where); + -+ if (transit == B_ENTERED_VIEW) { ++ if (transit == B_ENTERED_VIEW) ++ { + _glfwInputCursorEnter(window, GLFW_TRUE); -+ } else if (transit == B_EXITED_VIEW) { ++ } ++ else if (transit == B_EXITED_VIEW) ++ { + _glfwInputCursorEnter(window, GLFW_FALSE); -+ } else if (transit == B_INSIDE_VIEW || transit == B_OUTSIDE_VIEW) { -+ if (window->cursorMode == GLFW_CURSOR_DISABLED) { -+ if (PLATFORM_WINDOW(window)->IsActive() && window->haiku.mouseGrab == GLFW_TRUE) { ++ } ++ else if (transit == B_INSIDE_VIEW || transit == B_OUTSIDE_VIEW) ++ { ++ if (window->cursorMode == GLFW_CURSOR_DISABLED) ++ { ++ if (PLATFORM_WINDOW(window)->IsActive() && window->haiku.mouseGrab == GLFW_TRUE) ++ { + int cx = PLATFORM_WINDOW(window)->Bounds().Width() / 2; + int cy = PLATFORM_WINDOW(window)->Bounds().Height() / 2; + float dx = where.x - cx; @@ -1633,8 +2122,11 @@ index 0000000..b043b40 + set_mouse_position(center.x, center.y); + _glfwInputCursorPos(window, window->virtualCursorPosX + dx, window->virtualCursorPosY + dy); + } -+ } else ++ } ++ else ++ { + _glfwInputCursorPos(window, where.x, where.y); ++ } + } + break; + } @@ -1653,11 +2145,14 @@ index 0000000..b043b40 + case B_WINDOW_ACTIVATED: + { + bool active = message->FindBool("active"); -+ if (active) { ++ if (active) ++ { + _glfwInputWindowFocus(window, GLFW_TRUE); + if (window->cursorMode == GLFW_CURSOR_DISABLED && window->haiku.mouseGrab == GLFW_TRUE) + disableCursor(window); -+ } else { ++ } ++ else ++ { + if (window->cursorMode == GLFW_CURSOR_DISABLED) + enableCursor(window); + @@ -1676,14 +2171,21 @@ index 0000000..b043b40 + } + case B_WINDOW_RESIZED: + { -+ float width = message->FindFloat("width"); -+ float height = message->FindFloat("height"); -+ if (!window->monitor) -+ _glfwInputFramebufferSize(window, width, height); ++ int width = int(message->FindFloat("width")); ++ int height = int(message->FindFloat("height")); + -+ _glfwInputWindowSize(window, width, height); -+ window->haiku.width = width; -+ window->haiku.height = height; ++ if (width != window->haiku.width || height != window->haiku.height) ++ { ++ window->haiku.width = width; ++ window->haiku.height = height; ++ ++ _glfwInputFramebufferSize(window, width, height); ++ _glfwInputWindowSize(window, width, height); ++ ++ PLATFORM_VIEW(window)->ResizeBitmap(width, height); ++ ++ window->context.makeCurrent(window); ++ } + break; + } + case B_UNMAPPED_KEY_UP: @@ -1700,9 +2202,11 @@ index 0000000..b043b40 + + _glfwInputKey(window, key, key, action, mods); + -+ if (action == GLFW_PRESS) { ++ if (action == GLFW_PRESS) ++ { + const char* bytes; -+ if(message->FindString("bytes", &bytes) == B_OK) { ++ if(message->FindString("bytes", &bytes) == B_OK) ++ { + const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT)); + _glfwInputChar(window, decodeUTF8(&bytes), mods, plain); + } @@ -1726,7 +2230,8 @@ index 0000000..b043b40 +{ + bigtime_t enterTime = system_time(); + -+ while(PLATFORM_QUEUE->IsEmpty()) { ++ while(PLATFORM_QUEUE->IsEmpty()) ++ { + bigtime_t elapsed = system_time() - enterTime; + if (elapsed > timeout * 1000000) + break; @@ -1819,8 +2324,8 @@ index 0000000..b043b40 +void _glfwPlatformSwapBuffers(_GLFWwindow* window) +{ + HaikuPlatformView *view = PLATFORM_VIEW(window); -+ glReadPixels(0, 0, view->Width(), view->Height(), GL_BGRA, GL_UNSIGNED_BYTE, view->GetBuffer()); -+ view->Repaint(); ++ glFinish(); ++ view->Repaint(); +} + +int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance,