From 8fa1a9749e1120fb8f63f86fa78868187b6d6f7a Mon Sep 17 00:00:00 2001 From: Youmu Liu <105042599+Nitload-NSI@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:12:50 +0800 Subject: [PATCH] going on big buffer, need three diff task scheduler --- .gitignore | 7 + .../Numeric/MatrixCompute.Basic.cs | 20 +- .../Numeric/MatrixComputeModel.cs | 16 +- .../Numeric/MatrixParallel.Publish.cs | 19 +- .../Numeric/MatrixParallel.cs | 9 +- .../Numeric/MatrixParallelTaskPackage.cs | 14 +- .../Numeric/MatrixParallelThread.cs | 1 - StgSharp.Native/StgSharp.Native.vcxproj | 15 +- .../StgSharp.Native.vcxproj.filters | 23 +- StgSharp.Native/glfw/glfw3.h | 6561 ------------- StgSharp.Native/glfw/glfw3.lib | Bin 733462 -> 0 bytes StgSharp.Native/glfw/glfw3native.h | 632 -- StgSharp.Native/sn-head/StgSharpNative.h | 4 +- StgSharp.Native/sn-head/glfw3.h | 6440 ------------- StgSharp.Native/sn-head/glfw3native.h | 632 -- StgSharp.Native/sn-head/glfw_function.h | 4 +- StgSharp.Native/sn-head/stb_image.h | 787 -- StgSharp.Native/{ => sn-src}/k_bufop.c | 0 StgSharp.Native/sn-src/sn_native.c | 12 +- StgSharp.Native/sn-src/stb_image.c | 8475 ----------------- 20 files changed, 88 insertions(+), 23583 deletions(-) delete mode 100644 StgSharp.Native/glfw/glfw3.h delete mode 100644 StgSharp.Native/glfw/glfw3.lib delete mode 100644 StgSharp.Native/glfw/glfw3native.h delete mode 100644 StgSharp.Native/sn-head/glfw3.h delete mode 100644 StgSharp.Native/sn-head/glfw3native.h delete mode 100644 StgSharp.Native/sn-head/stb_image.h rename StgSharp.Native/{ => sn-src}/k_bufop.c (100%) delete mode 100644 StgSharp.Native/sn-src/stb_image.c diff --git a/.gitignore b/.gitignore index b6fab14a..ea16a23d 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,10 @@ /TestResults */x64 */.vs +/StgSharp.Native/lib +/StgSharp.Native/sn-head/stb_image.h +/StgSharp.Native/glfw/glfw3native.h +/StgSharp.Native/glfw/glfw3dll.lib +/StgSharp.Native/glfw/glfw3_mt.lib +/StgSharp.Native/glfw/glfw3.h +/StgSharp.Native/glfw/glfw3.lib diff --git a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs index 8c3c1d55..05d9bf53 100644 --- a/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs +++ b/StgSharp.Mathematics/Numeric/MatrixCompute.Basic.cs @@ -68,18 +68,22 @@ namespace StgSharp.Mathematics.Numeric MatrixParallel.ReturnParallelResources(ref pool); return ans; } - MatrixParallelHandle taskGroup = /**/ default - /* - MatrixParallel.PublicTask(left.GetColumnEnumeration(), - right.GetColumnEnumeration(), - ans.GetColumnEnumeration(), - (delegate**, MatrixKernel*, MatrixKernel*, void>)NativeIntrinsic.Intrinsic.f32_add) - /**/ - ; + MatrixParallelTaskPackage* package = MatrixParallelFactory.CreateBaseTask(); + package->Left = left.Buffer; + package->Right = right.Buffer; + package->Result = ans.Buffer; + package->ElementSize = sizeof(float); + package->PrimCount = left.KernelColumnLength; + package->SecCount = left.KernelRowLength; + package->ComputeMode = new MatrixOpMode(MatrixOperationStyle.BUFFER_OP, MatrixOperationParam.LEFT_RIGHT_ANS_PARAM); + package->ComputeHandle = (IntPtr)NativeIntrinsic.Intrinsic.f32_add; + MatrixParallelHandle taskGroup = MatrixParallel.ScheduleTask(package); + MatrixParallel.LaunchParallel(taskGroup, SleepMode.DeepSleep); /* * run parallel */ + MatrixParallelFactory.Release(package); taskGroup.Dispose(); return ans; } diff --git a/StgSharp.Mathematics/Numeric/MatrixComputeModel.cs b/StgSharp.Mathematics/Numeric/MatrixComputeModel.cs index d14dc082..619f71ae 100644 --- a/StgSharp.Mathematics/Numeric/MatrixComputeModel.cs +++ b/StgSharp.Mathematics/Numeric/MatrixComputeModel.cs @@ -70,7 +70,7 @@ namespace StgSharp.Mathematics.Numeric lCount = (long)p->LeftPrimOffset * p->LeftPrimStride, rCount = (long)p->RightPrimOffset * p->RightPrimStride, aCount = (long)p->ResultPrimOffset * p->ResultPrimStride, - pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, + pCount = int.Min(p->PrimCount, p->PrimColumnCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, //edge to reset counters lLimit = pCount - p->LeftPrimOffset, rLimit = pCount - p->RightPrimOffset, @@ -93,7 +93,7 @@ namespace StgSharp.Mathematics.Numeric lc = (long)p->LeftSecOffset * p->LeftSecStride, rc = (long)p->RightSecOffset * p->RightSecStride, ac = (long)p->ResultSecOffset * p->ResultSecStride, - sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset); + sCount = int.Min(p->SecCount, p->PrimColumnCountInTile * p->SecTileOffset); long ll = sCount - p->LeftSecOffset, rl = sCount - p->RightSecOffset, @@ -121,7 +121,7 @@ namespace StgSharp.Mathematics.Numeric lCount = (long)p->LeftPrimOffset * p->LeftPrimStride, rCount = (long)p->RightPrimOffset * p->RightPrimStride, aCount = (long)p->ResultPrimOffset * p->ResultPrimStride, - pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, + pCount = int.Min(p->PrimCount, p->PrimColumnCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, //edge to reset counters lLimit = pCount - p->LeftPrimOffset, rLimit = pCount - p->RightPrimOffset, @@ -144,7 +144,7 @@ namespace StgSharp.Mathematics.Numeric lc = (long)p->LeftSecOffset * p->LeftSecStride, rc = (long)p->RightSecOffset * p->RightSecStride, ac = (long)p->ResultSecOffset * p->ResultSecStride, - sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset); + sCount = int.Min(p->SecCount, p->PrimColumnCountInTile * p->SecTileOffset); long ll = sCount - p->LeftSecOffset, rl = sCount - p->RightSecOffset, @@ -171,7 +171,7 @@ namespace StgSharp.Mathematics.Numeric // set beginning value to counters for primary offsets rCount = (long)p->RightPrimOffset * p->RightPrimStride, aCount = (long)p->ResultPrimOffset * p->ResultPrimStride, - pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, + pCount = int.Min(p->PrimCount, p->PrimColumnCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, //edge to reset counters rLimit = pCount - p->RightPrimOffset, aLimit = pCount - p->ResultPrimOffset; @@ -190,7 +190,7 @@ namespace StgSharp.Mathematics.Numeric long rc = (long)p->RightSecOffset * p->RightSecStride, ac = (long)p->ResultSecOffset * p->ResultSecStride, - sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset); + sCount = int.Min(p->SecCount, p->PrimColumnCountInTile * p->SecTileOffset); long rl = sCount - p->RightSecOffset, al = sCount - p->ResultSecOffset; @@ -215,7 +215,7 @@ namespace StgSharp.Mathematics.Numeric // set beginning value to counters for primary offsets rCount = (long)p->RightPrimOffset * p->RightPrimStride, aCount = (long)p->ResultPrimOffset * p->ResultPrimStride, - pCount = int.Min(p->PrimCount, p->PrimCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, + pCount = int.Min(p->PrimCount, p->PrimColumnCountInTile + p->PrimTileOffset) /*_count of tile may be too much*/, //edge to reset counters rLimit = pCount - p->RightPrimOffset, aLimit = pCount - p->ResultPrimOffset; @@ -234,7 +234,7 @@ namespace StgSharp.Mathematics.Numeric long rc = (long)p->RightSecOffset * p->RightSecStride, ac = (long)p->ResultSecOffset * p->ResultSecStride, - sCount = int.Min(p->SecCount, p->SecCountInTile * p->SecTileOffset); + sCount = int.Min(p->SecCount, p->PrimColumnCountInTile * p->SecTileOffset); long rl = sCount - p->RightSecOffset, al = sCount - p->ResultSecOffset; diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs index 2a883b76..5e50c3f1 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.Publish.cs @@ -32,6 +32,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Numerics; +using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; @@ -40,8 +41,16 @@ namespace StgSharp.Mathematics.Numeric public static partial class MatrixParallel { - private static unsafe MatrixParallelHandle PublicTaskPrivate(MatrixParallelTaskPackage* package) - where T : unmanaged, INumber + [MethodImpl(MethodImplOptions.AggressiveInlining)] + + internal static unsafe MatrixParallelHandle ScheduleTask(MatrixParallelTaskPackage* package) + where T : unmanaged + { + MatrixParallelTaskPackageNonGeneric* nonGeneric = (MatrixParallelTaskPackageNonGeneric*)package; + return ScheduleTask(nonGeneric); + } + + internal static unsafe MatrixParallelHandle ScheduleTask(MatrixParallelTaskPackageNonGeneric* package) { int primCount = package->PrimCount; int secCount = package->SecCount; @@ -59,7 +68,7 @@ namespace StgSharp.Mathematics.Numeric MatrixParallelHandle handle = new MatrixParallelHandle(pool); if (handle.Wraps.Count() == 1) { - handle.Wraps.First().WrapTask = (MatrixParallelTaskPackageNonGeneric*)package; + handle.Wraps.First().WrapTask = package; return handle; } int threadCount = pool.Length; @@ -70,7 +79,7 @@ namespace StgSharp.Mathematics.Numeric int total = primCount; Stack taskBunch = new Stack(threadCount); - MatrixParallelTaskPackage* current = package; + MatrixParallelTaskPackageNonGeneric* current = package; foreach (MatrixParallelWrap wrap in handle.Wraps) { bool hasSlice = columnAfterBaseTile > 0; @@ -103,7 +112,7 @@ namespace StgSharp.Mathematics.Numeric total -= columnInWrap; // set to wrap and push - wrap.WrapTask = (MatrixParallelTaskPackageNonGeneric*)current; + wrap.WrapTask = current; if (total <= 0) { diff --git a/StgSharp.Mathematics/Numeric/MatrixParallel.cs b/StgSharp.Mathematics/Numeric/MatrixParallel.cs index 81981676..fcb5ce05 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallel.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallel.cs @@ -43,7 +43,14 @@ namespace StgSharp.Mathematics.Numeric private static CapacityFixedStack _threads; private static volatile int RemainThreadCount = 0; - private static readonly object _lock = new(); + private static readonly +#if NET10_0_OR_GREATER + Lock +#else + object +#endif + _lock = new(); + private static ThreadPriority _AfterWork = ThreadPriority.Lowest; public static bool SupportParallel { get; } = Environment.ProcessorCount > 6; diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelTaskPackage.cs b/StgSharp.Mathematics/Numeric/MatrixParallelTaskPackage.cs index df38b04d..cca6d2d6 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelTaskPackage.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelTaskPackage.cs @@ -73,11 +73,11 @@ namespace StgSharp.Mathematics.Numeric } [StructLayout(LayoutKind.Sequential)] - public struct MatrixOpMode + public struct MatrixOpMode(MatrixOperationStyle style, MatrixOperationParam paramLayout) { - public MatrixOperationParam ParameterStyle; - public MatrixOperationStyle OperationStyle; + public MatrixOperationParam ParameterStyle = paramLayout; + public MatrixOperationStyle OperationStyle = style; } @@ -97,7 +97,7 @@ namespace StgSharp.Mathematics.Numeric #region source // Group 1: Left/Right matrix kernel base address - [FieldOffset(0)]public IntPtr Left; // 8 + [FieldOffset(0)] public IntPtr Left; // 8 [FieldOffset(8)] public IntPtr Right; // 8 #endregion @@ -106,7 +106,7 @@ namespace StgSharp.Mathematics.Numeric // Group 2: Result kernel base address + reserved [FieldOffset(16)] public IntPtr Result; // 8 - [FieldOffset(24)]public int ElementSize; + [FieldOffset(24)] public int ElementSize; [FieldOffset(28)] public int ReservedPtr0; // 4 (extension/reserved) #endregion @@ -158,8 +158,8 @@ namespace StgSharp.Mathematics.Numeric [FieldOffset(112)]public int PrimTileOffset; // 4 [FieldOffset(116)]public int SecTileOffset; // 4 - [FieldOffset(120)]public int PrimCountInTile; // 4 - [FieldOffset(124)]public int SecCountInTile; // 4 + [FieldOffset(120)] public int PrimColumnCountInTile; // 4 + [FieldOffset(124)] public int SecColumnCountInTile; // 4 #endregion } diff --git a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs index 834430ce..84cdf2b3 100644 --- a/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs +++ b/StgSharp.Mathematics/Numeric/MatrixParallelThread.cs @@ -173,7 +173,6 @@ namespace StgSharp.Mathematics.Numeric BindedWrap.PublishTaskToWorkers(Tasks); BindedWrap.SetAllWorker(); ExecuteTaskPackage(Tasks); - break; case 2://leader, error because leader should be at outer thread but not here break; diff --git a/StgSharp.Native/StgSharp.Native.vcxproj b/StgSharp.Native/StgSharp.Native.vcxproj index cdaa152a..b4d8f9a1 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj +++ b/StgSharp.Native/StgSharp.Native.vcxproj @@ -66,7 +66,7 @@ true true Speed - $(ProjectDir)sdl-head;$(ProjectDir)sn-head;%(AdditionalIncludeDirectories) + $(ProjectDir)lib;$(ProjectDir)sn-head;%(AdditionalIncludeDirectories) Console @@ -91,7 +91,7 @@ stdc11 CompileAsC true - $(ProjectDir)sdl-head;$(ProjectDir)sn-head;%(AdditionalIncludeDirectories) + $(ProjectDir)lib;$(ProjectDir)sn-head;%(AdditionalIncludeDirectories) Console @@ -104,9 +104,9 @@ - + @@ -114,26 +114,27 @@ CppCode - - + + + - - + + diff --git a/StgSharp.Native/StgSharp.Native.vcxproj.filters b/StgSharp.Native/StgSharp.Native.vcxproj.filters index e98500dc..13ad698b 100644 --- a/StgSharp.Native/StgSharp.Native.vcxproj.filters +++ b/StgSharp.Native/StgSharp.Native.vcxproj.filters @@ -24,9 +24,6 @@ 源文件 - - 源文件 - 源文件 @@ -51,7 +48,7 @@ 源文件 - + 源文件 @@ -65,9 +62,6 @@ 头文件 - - 头文件 - 头文件 @@ -80,15 +74,24 @@ 头文件 - + 头文件 - + + 头文件 + + + 头文件 + + 头文件 - + + 资源文件 + + 资源文件 diff --git a/StgSharp.Native/glfw/glfw3.h b/StgSharp.Native/glfw/glfw3.h deleted file mode 100644 index 79b06288..00000000 --- a/StgSharp.Native/glfw/glfw3.h +++ /dev/null @@ -1,6561 +0,0 @@ -/************************************************************************* - * GLFW 3.5 - www.glfw.org - * A library for OpenGL, window and input - *------------------------------------------------------------------------ - * Copyright (c) 2002-2006 Marcus Geelnard - * Copyright (c) 2006-2019 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. - * - *************************************************************************/ - -#ifndef _glfw3_h_ -#define _glfw3_h_ - -#ifdef __cplusplus -extern "C" { -#endif - - -/************************************************************************* - * Doxygen documentation - *************************************************************************/ - -/*! @file glfw3.h - * @brief The header of the GLFW 3 API. - * - * This is the header file of the GLFW 3 API. It defines all its types and - * declares all its functions. - * - * For more information about how to use this file, see @ref build_include. - */ -/*! @defgroup context Context reference - * @brief Functions and types related to OpenGL and OpenGL ES contexts. - * - * This is the reference documentation for OpenGL and OpenGL ES context related - * functions. For more task-oriented information, see the @ref context_guide. - */ -/*! @defgroup vulkan Vulkan support reference - * @brief Functions and types related to Vulkan. - * - * This is the reference documentation for Vulkan related functions and types. - * For more task-oriented information, see the @ref vulkan_guide. - */ -/*! @defgroup init Initialization, version and error reference - * @brief Functions and types related to initialization and error handling. - * - * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more task-oriented - * information, see the @ref intro_guide. - */ -/*! @defgroup input Input reference - * @brief Functions and types related to input handling. - * - * This is the reference documentation for input related functions and types. - * For more task-oriented information, see the @ref input_guide. - */ -/*! @defgroup monitor Monitor reference - * @brief Functions and types related to monitors. - * - * This is the reference documentation for monitor related functions and types. - * For more task-oriented information, see the @ref monitor_guide. - */ -/*! @defgroup window Window reference - * @brief Functions and types related to windows. - * - * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more task-oriented - * information, see the @ref window_guide. - */ - - -/************************************************************************* - * Compiler- and platform-specific preprocessor work - *************************************************************************/ - -/* If we are we on Windows, we want a single define for it. - */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) - #define _WIN32 -#endif /* _WIN32 */ - -/* Include because most Windows GLU headers need wchar_t and - * the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h. - * Include it unconditionally to avoid surprising side-effects. - */ -#include - -/* Include because it is needed by Vulkan and related functions. - * Include it unconditionally to avoid surprising side-effects. - */ -#include - -#if defined(GLFW_INCLUDE_VULKAN) - #include -#endif /* Vulkan header */ - -/* The Vulkan header may have indirectly included windows.h (because of - * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it. - */ - -/* It is customary to use APIENTRY for OpenGL function pointer declarations on - * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. - */ -#if !defined(APIENTRY) - #if defined(_WIN32) - #define APIENTRY __stdcall - #else - #define APIENTRY - #endif - #define GLFW_APIENTRY_DEFINED -#endif /* APIENTRY */ - -/* Some Windows OpenGL headers need this. - */ -#if !defined(WINGDIAPI) && defined(_WIN32) - #define WINGDIAPI __declspec(dllimport) - #define GLFW_WINGDIAPI_DEFINED -#endif /* WINGDIAPI */ - -/* Some Windows GLU headers need this. - */ -#if !defined(CALLBACK) && defined(_WIN32) - #define CALLBACK __stdcall - #define GLFW_CALLBACK_DEFINED -#endif /* CALLBACK */ - -/* Include the chosen OpenGL or OpenGL ES headers. - */ -#if defined(GLFW_INCLUDE_ES1) - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - -#elif defined(GLFW_INCLUDE_ES2) - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - -#elif defined(GLFW_INCLUDE_ES3) - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - -#elif defined(GLFW_INCLUDE_ES31) - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - -#elif defined(GLFW_INCLUDE_ES32) - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - -#elif defined(GLFW_INCLUDE_GLCOREARB) - - #if defined(__APPLE__) - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif /*GLFW_INCLUDE_GLEXT*/ - - #else /*__APPLE__*/ - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - - #endif /*__APPLE__*/ - -#elif defined(GLFW_INCLUDE_GLU) - - #if defined(__APPLE__) - - #if defined(GLFW_INCLUDE_GLU) - #include - #endif - - #else /*__APPLE__*/ - - #if defined(GLFW_INCLUDE_GLU) - #include - #endif - - #endif /*__APPLE__*/ - -#elif !defined(GLFW_INCLUDE_NONE) && \ - !defined(__gl_h_) && \ - !defined(__gles1_gl_h_) && \ - !defined(__gles2_gl2_h_) && \ - !defined(__gles2_gl3_h_) && \ - !defined(__gles2_gl31_h_) && \ - !defined(__gles2_gl32_h_) && \ - !defined(__gl_glcorearb_h_) && \ - !defined(__gl2_h_) /*legacy*/ && \ - !defined(__gl3_h_) /*legacy*/ && \ - !defined(__gl31_h_) /*legacy*/ && \ - !defined(__gl32_h_) /*legacy*/ && \ - !defined(__glcorearb_h_) /*legacy*/ && \ - !defined(__GL_H__) /*non-standard*/ && \ - !defined(__gltypes_h_) /*non-standard*/ && \ - !defined(__glee_h_) /*non-standard*/ - - #if defined(__APPLE__) - - #if !defined(GLFW_INCLUDE_GLEXT) - #define GL_GLEXT_LEGACY - #endif - #include - - #else /*__APPLE__*/ - - #include - #if defined(GLFW_INCLUDE_GLEXT) - #include - #endif - - #endif /*__APPLE__*/ - -#endif /* OpenGL and OpenGL ES headers */ - -#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) - /* GLFW_DLL must be defined by applications that are linking against the DLL - * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW - * configuration header when compiling the DLL version of the library. - */ - #error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined" -#endif - -/* GLFWAPI is used to declare public API functions for export - * from the DLL / shared library / dynamic library. - */ -#if defined(_WIN32) && defined(_GLFW_BUILD_DLL) - /* We are building GLFW as a Win32 DLL */ - #define GLFWAPI __declspec(dllexport) -#elif defined(_WIN32) && defined(GLFW_DLL) - /* We are calling a GLFW Win32 DLL */ - #define GLFWAPI __declspec(dllimport) -#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) - /* We are building GLFW as a Unix shared library */ - #define GLFWAPI __attribute__((visibility("default"))) -#else - #define GLFWAPI -#endif - - -/************************************************************************* - * GLFW API tokens - *************************************************************************/ - -/*! @name GLFW version macros - * @{ */ -/*! @brief The major version number of the GLFW header. - * - * The major version number of the GLFW header. This is incremented when the - * API is changed in non-compatible ways. - * @ingroup init - */ -#define GLFW_VERSION_MAJOR 3 -/*! @brief The minor version number of the GLFW header. - * - * The minor version number of the GLFW header. This is incremented when - * features are added to the API but it remains backward-compatible. - * @ingroup init - */ -#define GLFW_VERSION_MINOR 5 -/*! @brief The revision number of the GLFW header. - * - * The revision number of the GLFW header. This is incremented when a bug fix - * release is made that does not contain any API changes. - * @ingroup init - */ -#define GLFW_VERSION_REVISION 0 -/*! @} */ - -/*! @brief One. - * - * This is only semantic sugar for the number 1. You can instead use `1` or - * `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal - * to one. - * - * @ingroup init - */ -#define GLFW_TRUE 1 -/*! @brief Zero. - * - * This is only semantic sugar for the number 0. You can instead use `0` or - * `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is - * equal to zero. - * - * @ingroup init - */ -#define GLFW_FALSE 0 - -/*! @name Key and button actions - * @{ */ -/*! @brief The key or mouse button was released. - * - * The key or mouse button was released. - * - * @ingroup input - */ -#define GLFW_RELEASE 0 -/*! @brief The key or mouse button was pressed. - * - * The key or mouse button was pressed. - * - * @ingroup input - */ -#define GLFW_PRESS 1 -/*! @brief The key was held down until it repeated. - * - * The key was held down until it repeated. - * - * @ingroup input - */ -#define GLFW_REPEAT 2 -/*! @} */ - -/*! @defgroup hat_state Joystick hat states - * @brief Joystick hat states. - * - * See [joystick hat input](@ref joystick_hat) for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_HAT_CENTERED 0 -#define GLFW_HAT_UP 1 -#define GLFW_HAT_RIGHT 2 -#define GLFW_HAT_DOWN 4 -#define GLFW_HAT_LEFT 8 -#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP) -#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) -#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP) -#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN) - -/*! @ingroup input - */ -#define GLFW_KEY_UNKNOWN -1 - -/*! @} */ - -/*! @defgroup keys Keyboard key tokens - * @brief Keyboard key tokens. - * - * See [key input](@ref input_key) for how these are used. - * - * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60), - * but re-arranged to map to 7-bit ASCII for printable keys (function keys are - * put in the 256+ range). - * - * The naming of the key codes follow these rules: - * - The US keyboard layout is used - * - Names of printable alphanumeric characters are used (e.g. "A", "R", - * "3", etc.) - * - For non-alphanumeric characters, Unicode:ish names are used (e.g. - * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not - * correspond to the Unicode standard (usually for brevity) - * - Keys that lack a clear US mapping are named "WORLD_x" - * - For non-printable keys, custom names are used (e.g. "F4", - * "BACKSPACE", etc.) - * - * @ingroup input - * @{ - */ - -/* Printable keys */ -#define GLFW_KEY_SPACE 32 -#define GLFW_KEY_APOSTROPHE 39 /* ' */ -#define GLFW_KEY_COMMA 44 /* , */ -#define GLFW_KEY_MINUS 45 /* - */ -#define GLFW_KEY_PERIOD 46 /* . */ -#define GLFW_KEY_SLASH 47 /* / */ -#define GLFW_KEY_0 48 -#define GLFW_KEY_1 49 -#define GLFW_KEY_2 50 -#define GLFW_KEY_3 51 -#define GLFW_KEY_4 52 -#define GLFW_KEY_5 53 -#define GLFW_KEY_6 54 -#define GLFW_KEY_7 55 -#define GLFW_KEY_8 56 -#define GLFW_KEY_9 57 -#define GLFW_KEY_SEMICOLON 59 /* ; */ -#define GLFW_KEY_EQUAL 61 /* = */ -#define GLFW_KEY_A 65 -#define GLFW_KEY_B 66 -#define GLFW_KEY_C 67 -#define GLFW_KEY_D 68 -#define GLFW_KEY_E 69 -#define GLFW_KEY_F 70 -#define GLFW_KEY_G 71 -#define GLFW_KEY_H 72 -#define GLFW_KEY_I 73 -#define GLFW_KEY_J 74 -#define GLFW_KEY_K 75 -#define GLFW_KEY_L 76 -#define GLFW_KEY_M 77 -#define GLFW_KEY_N 78 -#define GLFW_KEY_O 79 -#define GLFW_KEY_P 80 -#define GLFW_KEY_Q 81 -#define GLFW_KEY_R 82 -#define GLFW_KEY_S 83 -#define GLFW_KEY_T 84 -#define GLFW_KEY_U 85 -#define GLFW_KEY_V 86 -#define GLFW_KEY_W 87 -#define GLFW_KEY_X 88 -#define GLFW_KEY_Y 89 -#define GLFW_KEY_Z 90 -#define GLFW_KEY_LEFT_BRACKET 91 /* [ */ -#define GLFW_KEY_BACKSLASH 92 /* \ */ -#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */ -#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */ -#define GLFW_KEY_WORLD_1 161 /* non-US #1 */ -#define GLFW_KEY_WORLD_2 162 /* non-US #2 */ - -/* Function keys */ -#define GLFW_KEY_ESCAPE 256 -#define GLFW_KEY_ENTER 257 -#define GLFW_KEY_TAB 258 -#define GLFW_KEY_BACKSPACE 259 -#define GLFW_KEY_INSERT 260 -#define GLFW_KEY_DELETE 261 -#define GLFW_KEY_RIGHT 262 -#define GLFW_KEY_LEFT 263 -#define GLFW_KEY_DOWN 264 -#define GLFW_KEY_UP 265 -#define GLFW_KEY_PAGE_UP 266 -#define GLFW_KEY_PAGE_DOWN 267 -#define GLFW_KEY_HOME 268 -#define GLFW_KEY_END 269 -#define GLFW_KEY_CAPS_LOCK 280 -#define GLFW_KEY_SCROLL_LOCK 281 -#define GLFW_KEY_NUM_LOCK 282 -#define GLFW_KEY_PRINT_SCREEN 283 -#define GLFW_KEY_PAUSE 284 -#define GLFW_KEY_F1 290 -#define GLFW_KEY_F2 291 -#define GLFW_KEY_F3 292 -#define GLFW_KEY_F4 293 -#define GLFW_KEY_F5 294 -#define GLFW_KEY_F6 295 -#define GLFW_KEY_F7 296 -#define GLFW_KEY_F8 297 -#define GLFW_KEY_F9 298 -#define GLFW_KEY_F10 299 -#define GLFW_KEY_F11 300 -#define GLFW_KEY_F12 301 -#define GLFW_KEY_F13 302 -#define GLFW_KEY_F14 303 -#define GLFW_KEY_F15 304 -#define GLFW_KEY_F16 305 -#define GLFW_KEY_F17 306 -#define GLFW_KEY_F18 307 -#define GLFW_KEY_F19 308 -#define GLFW_KEY_F20 309 -#define GLFW_KEY_F21 310 -#define GLFW_KEY_F22 311 -#define GLFW_KEY_F23 312 -#define GLFW_KEY_F24 313 -#define GLFW_KEY_F25 314 -#define GLFW_KEY_KP_0 320 -#define GLFW_KEY_KP_1 321 -#define GLFW_KEY_KP_2 322 -#define GLFW_KEY_KP_3 323 -#define GLFW_KEY_KP_4 324 -#define GLFW_KEY_KP_5 325 -#define GLFW_KEY_KP_6 326 -#define GLFW_KEY_KP_7 327 -#define GLFW_KEY_KP_8 328 -#define GLFW_KEY_KP_9 329 -#define GLFW_KEY_KP_DECIMAL 330 -#define GLFW_KEY_KP_DIVIDE 331 -#define GLFW_KEY_KP_MULTIPLY 332 -#define GLFW_KEY_KP_SUBTRACT 333 -#define GLFW_KEY_KP_ADD 334 -#define GLFW_KEY_KP_ENTER 335 -#define GLFW_KEY_KP_EQUAL 336 -#define GLFW_KEY_LEFT_SHIFT 340 -#define GLFW_KEY_LEFT_CONTROL 341 -#define GLFW_KEY_LEFT_ALT 342 -#define GLFW_KEY_LEFT_SUPER 343 -#define GLFW_KEY_RIGHT_SHIFT 344 -#define GLFW_KEY_RIGHT_CONTROL 345 -#define GLFW_KEY_RIGHT_ALT 346 -#define GLFW_KEY_RIGHT_SUPER 347 -#define GLFW_KEY_MENU 348 - -#define GLFW_KEY_LAST GLFW_KEY_MENU - -/*! @} */ - -/*! @defgroup mods Modifier key flags - * @brief Modifier key flags. - * - * See [key input](@ref input_key) for how these are used. - * - * @ingroup input - * @{ */ - -/*! @brief If this bit is set one or more Shift keys were held down. - * - * If this bit is set one or more Shift keys were held down. - */ -#define GLFW_MOD_SHIFT 0x0001 -/*! @brief If this bit is set one or more Control keys were held down. - * - * If this bit is set one or more Control keys were held down. - */ -#define GLFW_MOD_CONTROL 0x0002 -/*! @brief If this bit is set one or more Alt keys were held down. - * - * If this bit is set one or more Alt keys were held down. - */ -#define GLFW_MOD_ALT 0x0004 -/*! @brief If this bit is set one or more Super keys were held down. - * - * If this bit is set one or more Super keys were held down. - */ -#define GLFW_MOD_SUPER 0x0008 -/*! @brief If this bit is set the Caps Lock key is enabled. - * - * If this bit is set the Caps Lock key is enabled and the @ref - * GLFW_LOCK_KEY_MODS input mode is set. - */ -#define GLFW_MOD_CAPS_LOCK 0x0010 -/*! @brief If this bit is set the Num Lock key is enabled. - * - * If this bit is set the Num Lock key is enabled and the @ref - * GLFW_LOCK_KEY_MODS input mode is set. - */ -#define GLFW_MOD_NUM_LOCK 0x0020 - -/*! @} */ - -/*! @defgroup buttons Mouse buttons - * @brief Mouse button IDs. - * - * See [mouse button input](@ref input_mouse_button) for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_MOUSE_BUTTON_1 0 -#define GLFW_MOUSE_BUTTON_2 1 -#define GLFW_MOUSE_BUTTON_3 2 -#define GLFW_MOUSE_BUTTON_4 3 -#define GLFW_MOUSE_BUTTON_5 4 -#define GLFW_MOUSE_BUTTON_6 5 -#define GLFW_MOUSE_BUTTON_7 6 -#define GLFW_MOUSE_BUTTON_8 7 -#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8 -#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1 -#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2 -#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3 -/*! @} */ - -/*! @defgroup joysticks Joysticks - * @brief Joystick IDs. - * - * See [joystick input](@ref joystick) for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_JOYSTICK_1 0 -#define GLFW_JOYSTICK_2 1 -#define GLFW_JOYSTICK_3 2 -#define GLFW_JOYSTICK_4 3 -#define GLFW_JOYSTICK_5 4 -#define GLFW_JOYSTICK_6 5 -#define GLFW_JOYSTICK_7 6 -#define GLFW_JOYSTICK_8 7 -#define GLFW_JOYSTICK_9 8 -#define GLFW_JOYSTICK_10 9 -#define GLFW_JOYSTICK_11 10 -#define GLFW_JOYSTICK_12 11 -#define GLFW_JOYSTICK_13 12 -#define GLFW_JOYSTICK_14 13 -#define GLFW_JOYSTICK_15 14 -#define GLFW_JOYSTICK_16 15 -#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16 -/*! @} */ - -/*! @defgroup gamepad_buttons Gamepad buttons - * @brief Gamepad buttons. - * - * See @ref gamepad for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_GAMEPAD_BUTTON_A 0 -#define GLFW_GAMEPAD_BUTTON_B 1 -#define GLFW_GAMEPAD_BUTTON_X 2 -#define GLFW_GAMEPAD_BUTTON_Y 3 -#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4 -#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5 -#define GLFW_GAMEPAD_BUTTON_BACK 6 -#define GLFW_GAMEPAD_BUTTON_START 7 -#define GLFW_GAMEPAD_BUTTON_GUIDE 8 -#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9 -#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10 -#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11 -#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12 -#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13 -#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14 -#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT - -#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A -#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B -#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X -#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y -/*! @} */ - -/*! @defgroup gamepad_axes Gamepad axes - * @brief Gamepad axes. - * - * See @ref gamepad for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_GAMEPAD_AXIS_LEFT_X 0 -#define GLFW_GAMEPAD_AXIS_LEFT_Y 1 -#define GLFW_GAMEPAD_AXIS_RIGHT_X 2 -#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3 -#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4 -#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5 -#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER -/*! @} */ - -/*! @defgroup errors Error codes - * @brief Error codes. - * - * See [error handling](@ref error_handling) for how these are used. - * - * @ingroup init - * @{ */ -/*! @brief No error has occurred. - * - * No error has occurred. - * - * @analysis Yay. - */ -#define GLFW_NO_ERROR 0 -/*! @brief GLFW has not been initialized. - * - * This occurs if a GLFW function was called that must not be called unless the - * library is [initialized](@ref intro_init). - * - * @analysis Application programmer error. Initialize GLFW before calling any - * function that requires initialization. - */ -#define GLFW_NOT_INITIALIZED 0x00010001 -/*! @brief No context is current for this thread. - * - * This occurs if a GLFW function was called that needs and operates on the - * current OpenGL or OpenGL ES context but no context is current on the calling - * thread. One such function is @ref glfwSwapInterval. - * - * @analysis Application programmer error. Ensure a context is current before - * calling functions that require a current context. - */ -#define GLFW_NO_CURRENT_CONTEXT 0x00010002 -/*! @brief One of the arguments to the function was an invalid enum value. - * - * One of the arguments to the function was an invalid enum value, for example - * requesting @ref GLFW_RED_BITS with @ref glfwGetWindowAttrib. - * - * @analysis Application programmer error. Fix the offending call. - */ -#define GLFW_INVALID_ENUM 0x00010003 -/*! @brief One of the arguments to the function was an invalid value. - * - * One of the arguments to the function was an invalid value, for example - * requesting a non-existent OpenGL or OpenGL ES version like 2.7. - * - * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead - * result in a @ref GLFW_VERSION_UNAVAILABLE error. - * - * @analysis Application programmer error. Fix the offending call. - */ -#define GLFW_INVALID_VALUE 0x00010004 -/*! @brief A memory allocation failed. - * - * A memory allocation failed. - * - * @analysis A bug in GLFW or the underlying operating system. Report the bug - * to our [issue tracker](https://github.com/glfw/glfw/issues). - */ -#define GLFW_OUT_OF_MEMORY 0x00010005 -/*! @brief GLFW could not find support for the requested API on the system. - * - * GLFW could not find support for the requested API on the system. - * - * @analysis The installed graphics driver does not support the requested - * API, or does not support it via the chosen context creation API. - * Below are a few examples. - * - * @par - * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only support it via - * a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa - * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. Older graphics drivers do not support Vulkan. - */ -#define GLFW_API_UNAVAILABLE 0x00010006 -/*! @brief The requested OpenGL or OpenGL ES version is not available. - * - * The requested OpenGL or OpenGL ES version (including any requested context - * or framebuffer hints) is not available on this machine. - * - * @analysis The machine does not support your requirements. If your - * application is sufficiently flexible, downgrade your requirements and try - * again. Otherwise, inform the user that their machine does not match your - * requirements. - * - * @par - * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0 - * comes out before the 4.x series gets that far, also fail with this error and - * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions - * will exist. - */ -#define GLFW_VERSION_UNAVAILABLE 0x00010007 -/*! @brief A platform-specific error occurred that does not match any of the - * more specific categories. - * - * A platform-specific error occurred that does not match any of the more - * specific categories. - * - * @analysis A bug or configuration error in GLFW, the underlying operating - * system or its drivers, or a lack of required resources. Report the issue to - * our [issue tracker](https://github.com/glfw/glfw/issues). - */ -#define GLFW_PLATFORM_ERROR 0x00010008 -/*! @brief The requested format is not supported or available. - * - * If emitted during window creation, the requested pixel format is not - * supported. - * - * If emitted when querying the clipboard, the contents of the clipboard could - * not be converted to the requested format. - * - * @analysis If emitted during window creation, one or more - * [hard constraints](@ref window_hints_hard) did not match any of the - * available pixel formats. If your application is sufficiently flexible, - * downgrade your requirements and try again. Otherwise, inform the user that - * their machine does not match your requirements. - * - * @par - * If emitted when querying the clipboard, ignore the error or report it to - * the user, as appropriate. - */ -#define GLFW_FORMAT_UNAVAILABLE 0x00010009 -/*! @brief The specified window does not have an OpenGL or OpenGL ES context. - * - * A window that does not have an OpenGL or OpenGL ES context was passed to - * a function that requires it to have one. - * - * @analysis Application programmer error. Fix the offending call. - */ -#define GLFW_NO_WINDOW_CONTEXT 0x0001000A -/*! @brief The specified cursor shape is not available. - * - * The specified standard cursor shape is not available, either because the - * current platform cursor theme does not provide it or because it is not - * available on the platform. - * - * @analysis Platform or system settings limitation. Pick another - * [standard cursor shape](@ref shapes) or create a - * [custom cursor](@ref cursor_custom). - */ -#define GLFW_CURSOR_UNAVAILABLE 0x0001000B -/*! @brief The requested feature is not provided by the platform. - * - * The requested feature is not provided by the platform, so GLFW is unable to - * implement it. The documentation for each function notes if it could emit - * this error. - * - * @analysis Platform or platform version limitation. The error can be ignored - * unless the feature is critical to the application. - * - * @par - * A function call that emits this error has no effect other than the error and - * updating any existing out parameters. - */ -#define GLFW_FEATURE_UNAVAILABLE 0x0001000C -/*! @brief The requested feature is not implemented for the platform. - * - * The requested feature has not yet been implemented in GLFW for this platform. - * - * @analysis An incomplete implementation of GLFW for this platform, hopefully - * fixed in a future release. The error can be ignored unless the feature is - * critical to the application. - * - * @par - * A function call that emits this error has no effect other than the error and - * updating any existing out parameters. - */ -#define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D -/*! @brief Platform unavailable or no matching platform was found. - * - * If emitted during initialization, no matching platform was found. If the @ref - * GLFW_PLATFORM init hint was set to `GLFW_ANY_PLATFORM`, GLFW could not detect any of - * the platforms supported by this library binary, except for the Null platform. If the - * init hint was set to a specific platform, it is either not supported by this library - * binary or GLFW was not able to detect it. - * - * If emitted by a native access function, GLFW was initialized for a different platform - * than the function is for. - * - * @analysis Failure to detect any platform usually only happens on non-macOS Unix - * systems, either when no window system is running or the program was run from - * a terminal that does not have the necessary environment variables. Fall back to - * a different platform if possible or notify the user that no usable platform was - * detected. - * - * Failure to detect a specific platform may have the same cause as above or be because - * support for that platform was not compiled in. Call @ref glfwPlatformSupported to - * check whether a specific platform is supported by a library binary. - */ -#define GLFW_PLATFORM_UNAVAILABLE 0x0001000E -/*! @} */ - -/*! @addtogroup window - * @{ */ -/*! @brief Input focus window hint and attribute - * - * Input focus [window hint](@ref GLFW_FOCUSED_hint) or - * [window attribute](@ref GLFW_FOCUSED_attrib). - */ -#define GLFW_FOCUSED 0x00020001 -/*! @brief Window iconification window attribute - * - * Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib). - */ -#define GLFW_ICONIFIED 0x00020002 -/*! @brief Window resize-ability window hint and attribute - * - * Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and - * [window attribute](@ref GLFW_RESIZABLE_attrib). - */ -#define GLFW_RESIZABLE 0x00020003 -/*! @brief Window visibility window hint and attribute - * - * Window visibility [window hint](@ref GLFW_VISIBLE_hint) and - * [window attribute](@ref GLFW_VISIBLE_attrib). - */ -#define GLFW_VISIBLE 0x00020004 -/*! @brief Window decoration window hint and attribute - * - * Window decoration [window hint](@ref GLFW_DECORATED_hint) and - * [window attribute](@ref GLFW_DECORATED_attrib). - */ -#define GLFW_DECORATED 0x00020005 -/*! @brief Window auto-iconification window hint and attribute - * - * Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and - * [window attribute](@ref GLFW_AUTO_ICONIFY_attrib). - */ -#define GLFW_AUTO_ICONIFY 0x00020006 -/*! @brief Window decoration window hint and attribute - * - * Window decoration [window hint](@ref GLFW_FLOATING_hint) and - * [window attribute](@ref GLFW_FLOATING_attrib). - */ -#define GLFW_FLOATING 0x00020007 -/*! @brief Window maximization window hint and attribute - * - * Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and - * [window attribute](@ref GLFW_MAXIMIZED_attrib). - */ -#define GLFW_MAXIMIZED 0x00020008 -/*! @brief Cursor centering window hint - * - * Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint). - */ -#define GLFW_CENTER_CURSOR 0x00020009 -/*! @brief Window framebuffer transparency hint and attribute - * - * Window framebuffer transparency - * [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and - * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). - */ -#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A -/*! @brief Mouse cursor hover window attribute. - * - * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). - */ -#define GLFW_HOVERED 0x0002000B -/*! @brief Input focus on calling show window hint and attribute - * - * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or - * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). - */ -#define GLFW_FOCUS_ON_SHOW 0x0002000C - -/*! @brief Mouse input transparency window hint and attribute - * - * Mouse input transparency [window hint](@ref GLFW_MOUSE_PASSTHROUGH_hint) or - * [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). - */ -#define GLFW_MOUSE_PASSTHROUGH 0x0002000D - -/*! @brief Initial position x-coordinate window hint. - * - * Initial position x-coordinate [window hint](@ref GLFW_POSITION_X). - */ -#define GLFW_POSITION_X 0x0002000E - -/*! @brief Initial position y-coordinate window hint. - * - * Initial position y-coordinate [window hint](@ref GLFW_POSITION_Y). - */ -#define GLFW_POSITION_Y 0x0002000F - -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). - */ -#define GLFW_RED_BITS 0x00021001 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS). - */ -#define GLFW_GREEN_BITS 0x00021002 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS). - */ -#define GLFW_BLUE_BITS 0x00021003 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS). - */ -#define GLFW_ALPHA_BITS 0x00021004 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS). - */ -#define GLFW_DEPTH_BITS 0x00021005 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS). - */ -#define GLFW_STENCIL_BITS 0x00021006 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS). - */ -#define GLFW_ACCUM_RED_BITS 0x00021007 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS). - */ -#define GLFW_ACCUM_GREEN_BITS 0x00021008 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS). - */ -#define GLFW_ACCUM_BLUE_BITS 0x00021009 -/*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS). - */ -#define GLFW_ACCUM_ALPHA_BITS 0x0002100A -/*! @brief Framebuffer auxiliary buffer hint. - * - * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS). - */ -#define GLFW_AUX_BUFFERS 0x0002100B -/*! @brief OpenGL stereoscopic rendering hint. - * - * OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO). - */ -#define GLFW_STEREO 0x0002100C -/*! @brief Framebuffer MSAA samples hint. - * - * Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES). - */ -#define GLFW_SAMPLES 0x0002100D -/*! @brief Framebuffer sRGB hint. - * - * Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE). - */ -#define GLFW_SRGB_CAPABLE 0x0002100E -/*! @brief Monitor refresh rate hint. - * - * Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE). - */ -#define GLFW_REFRESH_RATE 0x0002100F -/*! @brief Framebuffer double buffering hint and attribute. - * - * Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER_hint) and - * [attribute](@ref GLFW_DOUBLEBUFFER_attrib). - */ -#define GLFW_DOUBLEBUFFER 0x00021010 - -/*! @brief Context client API hint and attribute. - * - * Context client API [hint](@ref GLFW_CLIENT_API_hint) and - * [attribute](@ref GLFW_CLIENT_API_attrib). - */ -#define GLFW_CLIENT_API 0x00022001 -/*! @brief Context client API major version hint and attribute. - * - * Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint) - * and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib). - */ -#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 -/*! @brief Context client API minor version hint and attribute. - * - * Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint) - * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). - */ -#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 -/*! @brief Context client API revision number attribute. - * - * Context client API revision number - * [attribute](@ref GLFW_CONTEXT_REVISION_attrib). - */ -#define GLFW_CONTEXT_REVISION 0x00022004 -/*! @brief Context robustness hint and attribute. - * - * Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint) - * and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib). - */ -#define GLFW_CONTEXT_ROBUSTNESS 0x00022005 -/*! @brief OpenGL forward-compatibility hint and attribute. - * - * OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) - * and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib). - */ -#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006 -/*! @brief Debug mode context hint and attribute. - * - * Debug mode context [hint](@ref GLFW_CONTEXT_DEBUG_hint) and - * [attribute](@ref GLFW_CONTEXT_DEBUG_attrib). - */ -#define GLFW_CONTEXT_DEBUG 0x00022007 -/*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_OPENGL_DEBUG_CONTEXT GLFW_CONTEXT_DEBUG -/*! @brief OpenGL profile hint and attribute. - * - * OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and - * [attribute](@ref GLFW_OPENGL_PROFILE_attrib). - */ -#define GLFW_OPENGL_PROFILE 0x00022008 -/*! @brief Context flush-on-release hint and attribute. - * - * Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and - * [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib). - */ -#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 -/*! @brief Context error suppression hint and attribute. - * - * Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and - * [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib). - */ -#define GLFW_CONTEXT_NO_ERROR 0x0002200A -/*! @brief Context creation API hint and attribute. - * - * Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and - * [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib). - */ -#define GLFW_CONTEXT_CREATION_API 0x0002200B -/*! @brief Window content area scaling window - * [window hint](@ref GLFW_SCALE_TO_MONITOR). - */ -#define GLFW_SCALE_TO_MONITOR 0x0002200C -/*! @brief Window framebuffer scaling - * [window hint](@ref GLFW_SCALE_FRAMEBUFFER_hint). - */ -#define GLFW_SCALE_FRAMEBUFFER 0x0002200D -/*! @brief Legacy name for compatibility. - * - * This is an alias for the - * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) window hint for - * compatibility with earlier versions. - */ -#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 -/*! @brief macOS specific - * [window hint](@ref GLFW_COCOA_FRAME_NAME_hint). - */ -#define GLFW_COCOA_FRAME_NAME 0x00023002 -/*! @brief macOS specific - * [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint). - */ -#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003 -/*! @brief X11 specific - * [window hint](@ref GLFW_X11_CLASS_NAME_hint). - */ -#define GLFW_X11_CLASS_NAME 0x00024001 -/*! @brief X11 specific - * [window hint](@ref GLFW_X11_CLASS_NAME_hint). - */ -#define GLFW_X11_INSTANCE_NAME 0x00024002 -#define GLFW_WIN32_KEYBOARD_MENU 0x00025001 -/*! @brief Win32 specific [window hint](@ref GLFW_WIN32_SHOWDEFAULT_hint). - */ -#define GLFW_WIN32_SHOWDEFAULT 0x00025002 -/*! @brief Wayland specific - * [window hint](@ref GLFW_WAYLAND_APP_ID_hint). - * - * Allows specification of the Wayland app_id. - */ -#define GLFW_WAYLAND_APP_ID 0x00026001 -/*! @} */ - -#define GLFW_NO_API 0 -#define GLFW_OPENGL_API 0x00030001 -#define GLFW_OPENGL_ES_API 0x00030002 - -#define GLFW_NO_ROBUSTNESS 0 -#define GLFW_NO_RESET_NOTIFICATION 0x00031001 -#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002 - -#define GLFW_OPENGL_ANY_PROFILE 0 -#define GLFW_OPENGL_CORE_PROFILE 0x00032001 -#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002 - -#define GLFW_CURSOR 0x00033001 -#define GLFW_STICKY_KEYS 0x00033002 -#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 -#define GLFW_LOCK_KEY_MODS 0x00033004 -#define GLFW_RAW_MOUSE_MOTION 0x00033005 -#define GLFW_UNLIMITED_MOUSE_BUTTONS 0x00033006 - -#define GLFW_CURSOR_NORMAL 0x00034001 -#define GLFW_CURSOR_HIDDEN 0x00034002 -#define GLFW_CURSOR_DISABLED 0x00034003 -#define GLFW_CURSOR_CAPTURED 0x00034004 - -#define GLFW_ANY_RELEASE_BEHAVIOR 0 -#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 -#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 - -#define GLFW_NATIVE_CONTEXT_API 0x00036001 -#define GLFW_EGL_CONTEXT_API 0x00036002 -#define GLFW_OSMESA_CONTEXT_API 0x00036003 - -#define GLFW_ANGLE_PLATFORM_TYPE_NONE 0x00037001 -#define GLFW_ANGLE_PLATFORM_TYPE_OPENGL 0x00037002 -#define GLFW_ANGLE_PLATFORM_TYPE_OPENGLES 0x00037003 -#define GLFW_ANGLE_PLATFORM_TYPE_D3D9 0x00037004 -#define GLFW_ANGLE_PLATFORM_TYPE_D3D11 0x00037005 -#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007 -#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008 - -#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001 -#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002 - -#define GLFW_ANY_POSITION 0x80000000 - -/*! @defgroup shapes Standard cursor shapes - * @brief Standard system cursor shapes. - * - * These are the [standard cursor shapes](@ref cursor_standard) that can be - * requested from the platform (window system). - * - * @ingroup input - * @{ */ - -/*! @brief The regular arrow cursor shape. - * - * The regular arrow cursor shape. - */ -#define GLFW_ARROW_CURSOR 0x00036001 -/*! @brief The text input I-beam cursor shape. - * - * The text input I-beam cursor shape. - */ -#define GLFW_IBEAM_CURSOR 0x00036002 -/*! @brief The crosshair cursor shape. - * - * The crosshair cursor shape. - */ -#define GLFW_CROSSHAIR_CURSOR 0x00036003 -/*! @brief The pointing hand cursor shape. - * - * The pointing hand cursor shape. - */ -#define GLFW_POINTING_HAND_CURSOR 0x00036004 -/*! @brief The horizontal resize/move arrow shape. - * - * The horizontal resize/move arrow shape. This is usually a horizontal - * double-headed arrow. - */ -#define GLFW_RESIZE_EW_CURSOR 0x00036005 -/*! @brief The vertical resize/move arrow shape. - * - * The vertical resize/move shape. This is usually a vertical double-headed - * arrow. - */ -#define GLFW_RESIZE_NS_CURSOR 0x00036006 -/*! @brief The top-left to bottom-right diagonal resize/move arrow shape. - * - * The top-left to bottom-right diagonal resize/move shape. This is usually - * a diagonal double-headed arrow. - * - * @note @macos This shape is provided by a private system API and may fail - * with @ref GLFW_CURSOR_UNAVAILABLE in the future. - * - * @note @wayland This shape is provided by a newer standard not supported by - * all cursor themes. - * - * @note @x11 This shape is provided by a newer standard not supported by all - * cursor themes. - */ -#define GLFW_RESIZE_NWSE_CURSOR 0x00036007 -/*! @brief The top-right to bottom-left diagonal resize/move arrow shape. - * - * The top-right to bottom-left diagonal resize/move shape. This is usually - * a diagonal double-headed arrow. - * - * @note @macos This shape is provided by a private system API and may fail - * with @ref GLFW_CURSOR_UNAVAILABLE in the future. - * - * @note @wayland This shape is provided by a newer standard not supported by - * all cursor themes. - * - * @note @x11 This shape is provided by a newer standard not supported by all - * cursor themes. - */ -#define GLFW_RESIZE_NESW_CURSOR 0x00036008 -/*! @brief The omni-directional resize/move cursor shape. - * - * The omni-directional resize cursor/move shape. This is usually either - * a combined horizontal and vertical double-headed arrow or a grabbing hand. - */ -#define GLFW_RESIZE_ALL_CURSOR 0x00036009 -/*! @brief The operation-not-allowed shape. - * - * The operation-not-allowed shape. This is usually a circle with a diagonal - * line through it. - * - * @note @wayland This shape is provided by a newer standard not supported by - * all cursor themes. - * - * @note @x11 This shape is provided by a newer standard not supported by all - * cursor themes. - */ -#define GLFW_NOT_ALLOWED_CURSOR 0x0003600A -/*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_HRESIZE_CURSOR GLFW_RESIZE_EW_CURSOR -/*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_VRESIZE_CURSOR GLFW_RESIZE_NS_CURSOR -/*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_HAND_CURSOR GLFW_POINTING_HAND_CURSOR -/*! @} */ - -#define GLFW_CONNECTED 0x00040001 -#define GLFW_DISCONNECTED 0x00040002 - -/*! @addtogroup init - * @{ */ -/*! @brief Joystick hat buttons init hint. - * - * Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS). - */ -#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001 -/*! @brief ANGLE rendering backend init hint. - * - * ANGLE rendering backend [init hint](@ref GLFW_ANGLE_PLATFORM_TYPE_hint). - */ -#define GLFW_ANGLE_PLATFORM_TYPE 0x00050002 -/*! @brief Platform selection init hint. - * - * Platform selection [init hint](@ref GLFW_PLATFORM). - */ -#define GLFW_PLATFORM 0x00050003 -/*! @brief macOS specific init hint. - * - * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). - */ -#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001 -/*! @brief macOS specific init hint. - * - * macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint). - */ -#define GLFW_COCOA_MENUBAR 0x00051002 -/*! @brief X11 specific init hint. - * - * X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint). - */ -#define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001 -/*! @brief Wayland specific init hint. - * - * Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint). - */ -#define GLFW_WAYLAND_LIBDECOR 0x00053001 -/*! @} */ - -/*! @addtogroup init - * @{ */ -/*! @brief Hint value that enables automatic platform selection. - * - * Hint value for @ref GLFW_PLATFORM that enables automatic platform selection. - */ -#define GLFW_ANY_PLATFORM 0x00060000 -#define GLFW_PLATFORM_WIN32 0x00060001 -#define GLFW_PLATFORM_COCOA 0x00060002 -#define GLFW_PLATFORM_WAYLAND 0x00060003 -#define GLFW_PLATFORM_X11 0x00060004 -#define GLFW_PLATFORM_NULL 0x00060005 -/*! @} */ - -#define GLFW_DONT_CARE -1 - - -/************************************************************************* - * GLFW API types - *************************************************************************/ - -/*! @brief Client API function pointer type. - * - * Generic function pointer used for returning client API function pointers - * without forcing a cast from a regular pointer. - * - * @sa @ref context_glext - * @sa @ref glfwGetProcAddress - * - * @since Added in version 3.0. - * - * @ingroup context - */ -typedef void (*GLFWglproc)(void); - -/*! @brief Vulkan API function pointer type. - * - * Generic function pointer used for returning Vulkan API function pointers - * without forcing a cast from a regular pointer. - * - * @sa @ref vulkan_proc - * @sa @ref glfwGetInstanceProcAddress - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ -typedef void (*GLFWvkproc)(void); - -/*! @brief Opaque monitor object. - * - * Opaque monitor object. - * - * @see @ref monitor_object - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -typedef struct GLFWmonitor GLFWmonitor; - -/*! @brief Opaque window object. - * - * Opaque window object. - * - * @see @ref window_object - * - * @since Added in version 3.0. - * - * @ingroup window - */ -typedef struct GLFWwindow GLFWwindow; - -/*! @brief Opaque cursor object. - * - * Opaque cursor object. - * - * @see @ref cursor_object - * - * @since Added in version 3.1. - * - * @ingroup input - */ -typedef struct GLFWcursor GLFWcursor; - -/*! @brief The function pointer type for memory allocation callbacks. - * - * This is the function pointer type for memory allocation callbacks. A memory - * allocation callback function has the following signature: - * @code - * void* function_name(size_t size, void* user) - * @endcode - * - * This function must return either a memory block at least `size` bytes long, - * or `NULL` if allocation failed. Note that not all parts of GLFW handle allocation - * failures gracefully yet. - * - * This function must support being called during @ref glfwInit but before the library is - * flagged as initialized, as well as during @ref glfwTerminate after the library is no - * longer flagged as initialized. - * - * Any memory allocated via this function will be deallocated via the same allocator - * during library termination or earlier. - * - * Any memory allocated via this function must be suitably aligned for any object type. - * If you are using C99 or earlier, this alignment is platform-dependent but will be the - * same as what `malloc` provides. If you are using C11 or later, this is the value of - * `alignof(max_align_t)`. - * - * The size will always be greater than zero. Allocations of size zero are filtered out - * before reaching the custom allocator. - * - * If this function returns `NULL`, GLFW will emit @ref GLFW_OUT_OF_MEMORY. - * - * This function must not call any GLFW function. - * - * @param[in] size The minimum size, in bytes, of the memory block. - * @param[in] user The user-defined pointer from the allocator. - * @return The address of the newly allocated memory block, or `NULL` if an - * error occurred. - * - * @pointer_lifetime The returned memory block must be valid at least until it - * is deallocated. - * - * @reentrancy This function should not call any GLFW function. - * - * @thread_safety This function must support being called from any thread that calls GLFW - * functions. - * - * @sa @ref init_allocator - * @sa @ref GLFWallocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ -typedef void* (* GLFWallocatefun)(size_t size, void* user); - -/*! @brief The function pointer type for memory reallocation callbacks. - * - * This is the function pointer type for memory reallocation callbacks. - * A memory reallocation callback function has the following signature: - * @code - * void* function_name(void* block, size_t size, void* user) - * @endcode - * - * This function must return a memory block at least `size` bytes long, or - * `NULL` if allocation failed. Note that not all parts of GLFW handle allocation - * failures gracefully yet. - * - * This function must support being called during @ref glfwInit but before the library is - * flagged as initialized, as well as during @ref glfwTerminate after the library is no - * longer flagged as initialized. - * - * Any memory allocated via this function will be deallocated via the same allocator - * during library termination or earlier. - * - * Any memory allocated via this function must be suitably aligned for any object type. - * If you are using C99 or earlier, this alignment is platform-dependent but will be the - * same as what `realloc` provides. If you are using C11 or later, this is the value of - * `alignof(max_align_t)`. - * - * The block address will never be `NULL` and the size will always be greater than zero. - * Reallocations of a block to size zero are converted into deallocations before reaching - * the custom allocator. Reallocations of `NULL` to a non-zero size are converted into - * regular allocations before reaching the custom allocator. - * - * If this function returns `NULL`, GLFW will emit @ref GLFW_OUT_OF_MEMORY. - * - * This function must not call any GLFW function. - * - * @param[in] block The address of the memory block to reallocate. - * @param[in] size The new minimum size, in bytes, of the memory block. - * @param[in] user The user-defined pointer from the allocator. - * @return The address of the newly allocated or resized memory block, or - * `NULL` if an error occurred. - * - * @pointer_lifetime The returned memory block must be valid at least until it - * is deallocated. - * - * @reentrancy This function should not call any GLFW function. - * - * @thread_safety This function must support being called from any thread that calls GLFW - * functions. - * - * @sa @ref init_allocator - * @sa @ref GLFWallocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ -typedef void* (* GLFWreallocatefun)(void* block, size_t size, void* user); - -/*! @brief The function pointer type for memory deallocation callbacks. - * - * This is the function pointer type for memory deallocation callbacks. - * A memory deallocation callback function has the following signature: - * @code - * void function_name(void* block, void* user) - * @endcode - * - * This function may deallocate the specified memory block. This memory block - * will have been allocated with the same allocator. - * - * This function must support being called during @ref glfwInit but before the library is - * flagged as initialized, as well as during @ref glfwTerminate after the library is no - * longer flagged as initialized. - * - * The block address will never be `NULL`. Deallocations of `NULL` are filtered out - * before reaching the custom allocator. - * - * If this function returns `NULL`, GLFW will emit @ref GLFW_OUT_OF_MEMORY. - * - * This function must not call any GLFW function. - * - * @param[in] block The address of the memory block to deallocate. - * @param[in] user The user-defined pointer from the allocator. - * - * @pointer_lifetime The specified memory block will not be accessed by GLFW - * after this function is called. - * - * @reentrancy This function should not call any GLFW function. - * - * @thread_safety This function must support being called from any thread that calls GLFW - * functions. - * - * @sa @ref init_allocator - * @sa @ref GLFWallocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ -typedef void (* GLFWdeallocatefun)(void* block, void* user); - -/*! @brief The function pointer type for error callbacks. - * - * This is the function pointer type for error callbacks. An error callback - * function has the following signature: - * @code - * void callback_name(int error_code, const char* description) - * @endcode - * - * @param[in] error_code An [error code](@ref errors). Future releases may add - * more error codes. - * @param[in] description A UTF-8 encoded string describing the error. - * - * @pointer_lifetime The error description string is valid until the callback - * function returns. - * - * @sa @ref error_handling - * @sa @ref glfwSetErrorCallback - * - * @since Added in version 3.0. - * - * @ingroup init - */ -typedef void (* GLFWerrorfun)(int error_code, const char* description); - -/*! @brief The function pointer type for window position callbacks. - * - * This is the function pointer type for window position callbacks. A window - * position callback function has the following signature: - * @code - * void callback_name(GLFWwindow* window, int xpos, int ypos) - * @endcode - * - * @param[in] window The window that was moved. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the - * upper-left corner of the content area of the window. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the - * upper-left corner of the content area of the window. - * - * @sa @ref window_pos - * @sa @ref glfwSetWindowPosCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ -typedef void (* GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos); - -/*! @brief The function pointer type for window size callbacks. - * - * This is the function pointer type for window size callbacks. A window size - * callback function has the following signature: - * @code - * void callback_name(GLFWwindow* window, int width, int height) - * @endcode - * - * @param[in] window The window that was resized. - * @param[in] width The new width, in screen coordinates, of the window. - * @param[in] height The new height, in screen coordinates, of the window. - * - * @sa @ref window_size - * @sa @ref glfwSetWindowSizeCallback - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -typedef void (* GLFWwindowsizefun)(GLFWwindow* window, int width, int height); - -/*! @brief The function pointer type for window close callbacks. - * - * This is the function pointer type for window close callbacks. A window - * close callback function has the following signature: - * @code - * void function_name(GLFWwindow* window) - * @endcode - * - * @param[in] window The window that the user attempted to close. - * - * @sa @ref window_close - * @sa @ref glfwSetWindowCloseCallback - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -typedef void (* GLFWwindowclosefun)(GLFWwindow* window); - -/*! @brief The function pointer type for window content refresh callbacks. - * - * This is the function pointer type for window content refresh callbacks. - * A window content refresh callback function has the following signature: - * @code - * void function_name(GLFWwindow* window); - * @endcode - * - * @param[in] window The window whose content needs to be refreshed. - * - * @sa @ref window_refresh - * @sa @ref glfwSetWindowRefreshCallback - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -typedef void (* GLFWwindowrefreshfun)(GLFWwindow* window); - -/*! @brief The function pointer type for window focus callbacks. - * - * This is the function pointer type for window focus callbacks. A window - * focus callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int focused) - * @endcode - * - * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GLFW_TRUE` if the window was given input focus, or - * `GLFW_FALSE` if it lost it. - * - * @sa @ref window_focus - * @sa @ref glfwSetWindowFocusCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ -typedef void (* GLFWwindowfocusfun)(GLFWwindow* window, int focused); - -/*! @brief The function pointer type for window iconify callbacks. - * - * This is the function pointer type for window iconify callbacks. A window - * iconify callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int iconified) - * @endcode - * - * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GLFW_TRUE` if the window was iconified, or - * `GLFW_FALSE` if it was restored. - * - * @sa @ref window_iconify - * @sa @ref glfwSetWindowIconifyCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ -typedef void (* GLFWwindowiconifyfun)(GLFWwindow* window, int iconified); - -/*! @brief The function pointer type for window maximize callbacks. - * - * This is the function pointer type for window maximize callbacks. A window - * maximize callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int maximized) - * @endcode - * - * @param[in] window The window that was maximized or restored. - * @param[in] maximized `GLFW_TRUE` if the window was maximized, or - * `GLFW_FALSE` if it was restored. - * - * @sa @ref window_maximize - * @sa glfwSetWindowMaximizeCallback - * - * @since Added in version 3.3. - * - * @ingroup window - */ -typedef void (* GLFWwindowmaximizefun)(GLFWwindow* window, int maximized); - -/*! @brief The function pointer type for framebuffer size callbacks. - * - * This is the function pointer type for framebuffer size callbacks. - * A framebuffer size callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int width, int height) - * @endcode - * - * @param[in] window The window whose framebuffer was resized. - * @param[in] width The new width, in pixels, of the framebuffer. - * @param[in] height The new height, in pixels, of the framebuffer. - * - * @sa @ref window_fbsize - * @sa @ref glfwSetFramebufferSizeCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ -typedef void (* GLFWframebuffersizefun)(GLFWwindow* window, int width, int height); - -/*! @brief The function pointer type for window content scale callbacks. - * - * This is the function pointer type for window content scale callbacks. - * A window content scale callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, float xscale, float yscale) - * @endcode - * - * @param[in] window The window whose content scale changed. - * @param[in] xscale The new x-axis content scale of the window. - * @param[in] yscale The new y-axis content scale of the window. - * - * @sa @ref window_scale - * @sa @ref glfwSetWindowContentScaleCallback - * - * @since Added in version 3.3. - * - * @ingroup window - */ -typedef void (* GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, float yscale); - -/*! @brief The function pointer type for mouse button callbacks. - * - * This is the function pointer type for mouse button callback functions. - * A mouse button callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int button, int action, int mods) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] button The [mouse button](@ref buttons) that was pressed or - * released. - * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. Future releases - * may add more actions. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were - * held down. - * - * @sa @ref input_mouse_button - * @sa @ref glfwSetMouseButtonCallback - * - * @since Added in version 1.0. - * @glfw3 Added window handle and modifier mask parameters. - * - * @ingroup input - */ -typedef void (* GLFWmousebuttonfun)(GLFWwindow* window, int button, int action, int mods); - -/*! @brief The function pointer type for cursor position callbacks. - * - * This is the function pointer type for cursor position callbacks. A cursor - * position callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, double xpos, double ypos); - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] xpos The new cursor x-coordinate, relative to the left edge of - * the content area. - * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the - * content area. - * - * @sa @ref cursor_pos - * @sa @ref glfwSetCursorPosCallback - * - * @since Added in version 3.0. Replaces `GLFWmouseposfun`. - * - * @ingroup input - */ -typedef void (* GLFWcursorposfun)(GLFWwindow* window, double xpos, double ypos); - -/*! @brief The function pointer type for cursor enter/leave callbacks. - * - * This is the function pointer type for cursor enter/leave callbacks. - * A cursor enter/leave callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int entered) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] entered `GLFW_TRUE` if the cursor entered the window's content - * area, or `GLFW_FALSE` if it left it. - * - * @sa @ref cursor_enter - * @sa @ref glfwSetCursorEnterCallback - * - * @since Added in version 3.0. - * - * @ingroup input - */ -typedef void (* GLFWcursorenterfun)(GLFWwindow* window, int entered); - -/*! @brief The function pointer type for scroll callbacks. - * - * This is the function pointer type for scroll callbacks. A scroll callback - * function has the following signature: - * @code - * void function_name(GLFWwindow* window, double xoffset, double yoffset) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] xoffset The scroll offset along the x-axis. - * @param[in] yoffset The scroll offset along the y-axis. - * - * @sa @ref scrolling - * @sa @ref glfwSetScrollCallback - * - * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. - * - * @ingroup input - */ -typedef void (* GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffset); - -/*! @brief The function pointer type for keyboard key callbacks. - * - * This is the function pointer type for keyboard key callbacks. A keyboard - * key callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] key The [keyboard key](@ref keys) that was pressed or released. - * @param[in] scancode The platform-specific scancode of the key. - * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. Future - * releases may add more actions. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were - * held down. - * - * @sa @ref input_key - * @sa @ref glfwSetKeyCallback - * - * @since Added in version 1.0. - * @glfw3 Added window handle, scancode and modifier mask parameters. - * - * @ingroup input - */ -typedef void (* GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int action, int mods); - -/*! @brief The function pointer type for Unicode character callbacks. - * - * This is the function pointer type for Unicode character callbacks. - * A Unicode character callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] codepoint The Unicode code point of the character. - * - * @sa @ref input_char - * @sa @ref glfwSetCharCallback - * - * @since Added in version 2.4. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ -typedef void (* GLFWcharfun)(GLFWwindow* window, unsigned int codepoint); - -/*! @brief The function pointer type for Unicode character with modifiers - * callbacks. - * - * This is the function pointer type for Unicode character with modifiers - * callbacks. It is called for each input character, regardless of what - * modifier keys are held down. A Unicode character with modifiers callback - * function has the following signature: - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint, int mods) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] codepoint The Unicode code point of the character. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were - * held down. - * - * @sa @ref input_char - * @sa @ref glfwSetCharModsCallback - * - * @deprecated Scheduled for removal in version 4.0. - * - * @since Added in version 3.1. - * - * @ingroup input - */ -typedef void (* GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int mods); - -/*! @brief The function pointer type for path drop callbacks. - * - * This is the function pointer type for path drop callbacks. A path drop - * callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int path_count, const char* paths[]) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] path_count The number of dropped paths. - * @param[in] paths The UTF-8 encoded file and/or directory path names. - * - * @pointer_lifetime The path array and its strings are valid until the - * callback function returns. - * - * @sa @ref path_drop - * @sa @ref glfwSetDropCallback - * - * @since Added in version 3.1. - * - * @ingroup input - */ -typedef void (* GLFWdropfun)(GLFWwindow* window, int path_count, const char* paths[]); - -/*! @brief The function pointer type for monitor configuration callbacks. - * - * This is the function pointer type for monitor configuration callbacks. - * A monitor callback function has the following signature: - * @code - * void function_name(GLFWmonitor* monitor, int event) - * @endcode - * - * @param[in] monitor The monitor that was connected or disconnected. - * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future - * releases may add more events. - * - * @sa @ref monitor_event - * @sa @ref glfwSetMonitorCallback - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -typedef void (* GLFWmonitorfun)(GLFWmonitor* monitor, int event); - -/*! @brief The function pointer type for joystick configuration callbacks. - * - * This is the function pointer type for joystick configuration callbacks. - * A joystick configuration callback function has the following signature: - * @code - * void function_name(int jid, int event) - * @endcode - * - * @param[in] jid The joystick that was connected or disconnected. - * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future - * releases may add more events. - * - * @sa @ref joystick_event - * @sa @ref glfwSetJoystickCallback - * - * @since Added in version 3.2. - * - * @ingroup input - */ -typedef void (* GLFWjoystickfun)(int jid, int event); - -/*! @brief Video mode type. - * - * This describes a single video mode. - * - * @sa @ref monitor_modes - * @sa @ref glfwGetVideoMode - * @sa @ref glfwGetVideoModes - * - * @since Added in version 1.0. - * @glfw3 Added refresh rate member. - * - * @ingroup monitor - */ -typedef struct GLFWvidmode -{ - /*! The width, in screen coordinates, of the video mode. - */ - int width; - /*! The height, in screen coordinates, of the video mode. - */ - int height; - /*! The bit depth of the red channel of the video mode. - */ - int redBits; - /*! The bit depth of the green channel of the video mode. - */ - int greenBits; - /*! The bit depth of the blue channel of the video mode. - */ - int blueBits; - /*! The refresh rate, in Hz, of the video mode. - */ - int refreshRate; -} GLFWvidmode; - -/*! @brief Gamma ramp. - * - * This describes the gamma ramp for a monitor. - * - * @sa @ref monitor_gamma - * @sa @ref glfwGetGammaRamp - * @sa @ref glfwSetGammaRamp - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -typedef struct GLFWgammaramp -{ - /*! An array of value describing the response of the red channel. - */ - unsigned short* red; - /*! An array of value describing the response of the green channel. - */ - unsigned short* green; - /*! An array of value describing the response of the blue channel. - */ - unsigned short* blue; - /*! The number of elements in each array. - */ - unsigned int size; -} GLFWgammaramp; - -/*! @brief Image data. - * - * This describes a single 2D image. See the documentation for each related - * function what the expected pixel format is. - * - * @sa @ref cursor_custom - * @sa @ref window_icon - * - * @since Added in version 2.1. - * @glfw3 Removed format and bytes-per-pixel members. - * - * @ingroup window - */ -typedef struct GLFWimage -{ - /*! The width, in pixels, of this image. - */ - int width; - /*! The height, in pixels, of this image. - */ - int height; - /*! The pixel data of this image, arranged left-to-right, top-to-bottom. - */ - unsigned char* pixels; -} GLFWimage; - -/*! @brief Gamepad input state - * - * This describes the input state of a gamepad. - * - * @sa @ref gamepad - * @sa @ref glfwGetGamepadState - * - * @since Added in version 3.3. - * - * @ingroup input - */ -typedef struct GLFWgamepadstate -{ - /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS` - * or `GLFW_RELEASE`. - */ - unsigned char buttons[15]; - /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0 - * to 1.0 inclusive. - */ - float axes[6]; -} GLFWgamepadstate; - -/*! @brief Custom heap memory allocator. - * - * This describes a custom heap memory allocator for GLFW. To set an allocator, pass it - * to @ref glfwInitAllocator before initializing the library. - * - * @sa @ref init_allocator - * @sa @ref glfwInitAllocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ -typedef struct GLFWallocator -{ - /*! The memory allocation function. See @ref GLFWallocatefun for details about - * allocation function. - */ - GLFWallocatefun allocate; - /*! The memory reallocation function. See @ref GLFWreallocatefun for details about - * reallocation function. - */ - GLFWreallocatefun reallocate; - /*! The memory deallocation function. See @ref GLFWdeallocatefun for details about - * deallocation function. - */ - GLFWdeallocatefun deallocate; - /*! The user pointer for this custom allocator. This value will be passed to the - * allocator functions. - */ - void* user; -} GLFWallocator; - - -/************************************************************************* - * GLFW API functions - *************************************************************************/ - -/*! @brief Initializes the GLFW library. - * - * This function initializes the GLFW library. Before most GLFW functions can - * be used, GLFW must be initialized, and before an application terminates GLFW - * should be terminated in order to free any resources allocated during or - * after initialization. - * - * If this function fails, it calls @ref glfwTerminate before returning. If it - * succeeds, you should call @ref glfwTerminate before the application exits. - * - * Additional calls to this function after successful initialization but before - * termination will return `GLFW_TRUE` immediately. - * - * The @ref GLFW_PLATFORM init hint controls which platforms are considered during - * initialization. This also depends on which platforms the library was compiled to - * support. - * - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @macos This function will change the current directory of the - * application to the `Contents/Resources` subdirectory of the application's - * bundle, if present. This can be disabled with the @ref - * GLFW_COCOA_CHDIR_RESOURCES init hint. - * - * @remark @macos This function will create the main menu and dock icon for the - * application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to - * contain a menu bar. Otherwise a minimal menu bar is created manually with - * common commands like Hide, Quit and About. The About entry opens a minimal - * about dialog with information from the application's bundle. The menu bar - * and dock icon can be disabled entirely with the @ref GLFW_COCOA_MENUBAR init - * hint. - * - * @remark __Wayland, X11:__ If the library was compiled with support for both - * Wayland and X11, and the @ref GLFW_PLATFORM init hint is set to - * `GLFW_ANY_PLATFORM`, the `XDG_SESSION_TYPE` environment variable affects - * which platform is picked. If the environment variable is not set, or is set - * to something other than `wayland` or `x11`, the regular detection mechanism - * will be used instead. - * - * @remark @x11 This function will set the `LC_CTYPE` category of the - * application locale according to the current environment if that category is - * still "C". This is because the "C" locale breaks Unicode text input. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref intro_init - * @sa @ref glfwInitHint - * @sa @ref glfwInitAllocator - * @sa @ref glfwTerminate - * - * @since Added in version 1.0. - * - * @ingroup init - */ -GLFWAPI int glfwInit(void); - -/*! @brief Terminates the GLFW library. - * - * This function destroys all remaining windows and cursors, restores any - * modified gamma ramps and frees any other allocated resources. Once this - * function is called, you must again call @ref glfwInit successfully before - * you will be able to use most GLFW functions. - * - * If GLFW has been successfully initialized, this function should be called - * before the application exits. If initialization fails, there is no need to - * call this function, as it is called by @ref glfwInit before it returns - * failure. - * - * This function has no effect if GLFW is not initialized. - * - * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. - * - * @remark This function may be called before @ref glfwInit. - * - * @warning The contexts of any remaining windows must not be current on any - * other thread when this function is called. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref intro_init - * @sa @ref glfwInit - * - * @since Added in version 1.0. - * - * @ingroup init - */ -GLFWAPI void glfwTerminate(void); - -/*! @brief Sets the specified init hint to the desired value. - * - * This function sets hints for the next initialization of GLFW. - * - * The values you set hints to are never reset by GLFW, but they only take - * effect during initialization. Once GLFW has been initialized, any values - * you set will be ignored until the library is terminated and initialized - * again. - * - * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will ignore them. - * Setting these hints requires no platform specific headers or functions. - * - * @param[in] hint The [init hint](@ref init_hints) to set. - * @param[in] value The new value of the init hint. - * - * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref - * GLFW_INVALID_VALUE. - * - * @remarks This function may be called before @ref glfwInit. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa init_hints - * @sa glfwInit - * - * @since Added in version 3.3. - * - * @ingroup init - */ -GLFWAPI void glfwInitHint(int hint, int value); - -/*! @brief Sets the init allocator to the desired value. - * - * To use the default allocator, call this function with a `NULL` argument. - * - * If you specify an allocator struct, every member must be a valid function - * pointer. If any member is `NULL`, this function will emit @ref - * GLFW_INVALID_VALUE and the init allocator will be unchanged. - * - * The functions in the allocator must fulfil a number of requirements. See the - * documentation for @ref GLFWallocatefun, @ref GLFWreallocatefun and @ref - * GLFWdeallocatefun for details. - * - * @param[in] allocator The allocator to use at the next initialization, or - * `NULL` to use the default one. - * - * @errors Possible errors include @ref GLFW_INVALID_VALUE. - * - * @pointer_lifetime The specified allocator is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref init_allocator - * @sa @ref glfwInit - * - * @since Added in version 3.4. - * - * @ingroup init - */ -GLFWAPI void glfwInitAllocator(const GLFWallocator* allocator); - -#if defined(VK_VERSION_1_0) - -/*! @brief Sets the desired Vulkan `vkGetInstanceProcAddr` function. - * - * This function sets the `vkGetInstanceProcAddr` function that GLFW will use for all - * Vulkan related entry point queries. - * - * This feature is mostly useful on macOS, if your copy of the Vulkan loader is in - * a location where GLFW cannot find it through dynamic loading, or if you are still - * using the static library version of the loader. - * - * If set to `NULL`, GLFW will try to load the Vulkan loader dynamically by its standard - * name and get this function from there. This is the default behavior. - * - * The standard name of the loader is `vulkan-1.dll` on Windows, `libvulkan.so.1` on - * Linux and other Unix-like systems and `libvulkan.1.dylib` on macOS. If your code is - * also loading it via these names then you probably don't need to use this function. - * - * The function address you set is never reset by GLFW, but it only takes effect during - * initialization. Once GLFW has been initialized, any updates will be ignored until the - * library is terminated and initialized again. - * - * @param[in] loader The address of the function to use, or `NULL`. - * - * @par Loader function signature - * @code - * PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* name) - * @endcode - * For more information about this function, see the - * [Vulkan Registry](https://www.khronos.org/registry/vulkan/). - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref vulkan_loader - * @sa @ref glfwInit - * - * @since Added in version 3.4. - * - * @ingroup init - */ -GLFWAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader); - -#endif /*VK_VERSION_1_0*/ - -/*! @brief Retrieves the version of the GLFW library. - * - * This function retrieves the major, minor and revision numbers of the GLFW - * library. It is intended for when you are using GLFW as a shared library and - * want to ensure that you are using the minimum required version. - * - * Any or all of the version arguments may be `NULL`. - * - * @param[out] major Where to store the major version number, or `NULL`. - * @param[out] minor Where to store the minor version number, or `NULL`. - * @param[out] rev Where to store the revision number, or `NULL`. - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref intro_version - * @sa @ref glfwGetVersionString - * - * @since Added in version 1.0. - * - * @ingroup init - */ -GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev); - -/*! @brief Returns a string describing the compile-time configuration. - * - * This function returns the compile-time generated - * [version string](@ref intro_version_string) of the GLFW library binary. It describes - * the version, platforms, compiler and any platform or operating system specific - * compile-time options. It should not be confused with the OpenGL or OpenGL ES version - * string, queried with `glGetString`. - * - * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function provides the version of the running library - * binary in numerical format. - * - * __Do not use the version string__ to parse what platforms are supported. The @ref - * glfwPlatformSupported function lets you query platform support. - * - * @return The ASCII encoded GLFW version string. - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @pointer_lifetime The returned string is static and compile-time generated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref intro_version - * @sa @ref glfwGetVersion - * - * @since Added in version 3.0. - * - * @ingroup init - */ -GLFWAPI const char* glfwGetVersionString(void); - -/*! @brief Returns and clears the last error for the calling thread. - * - * This function returns and clears the [error code](@ref errors) of the last - * error that occurred on the calling thread, and optionally a UTF-8 encoded - * human-readable description of it. If no error has occurred since the last - * call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is - * set to `NULL`. - * - * @param[in] description Where to store the error description pointer, or `NULL`. - * @return The last error code for the calling thread, or @ref GLFW_NO_ERROR - * (zero). - * - * @errors None. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is guaranteed to be valid only until the - * next error occurs or the library is terminated. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref error_handling - * @sa @ref glfwSetErrorCallback - * - * @since Added in version 3.3. - * - * @ingroup init - */ -GLFWAPI int glfwGetError(const char** description); - -/*! @brief Sets the error callback. - * - * This function sets the error callback, which is called with an error code - * and a human-readable description each time a GLFW error occurs. - * - * The error code is set before the callback is called. Calling @ref - * glfwGetError from the error callback will return the same value as the error - * code argument. - * - * The error callback is called on the thread where the error occurred. If you - * are using GLFW from multiple threads, your error callback needs to be - * written accordingly. - * - * Because the description string may have been generated specifically for that - * error, it is not guaranteed to be valid after the callback has returned. If - * you wish to use it after the callback returns, you need to make a copy. - * - * Once set, the error callback remains set even after the library has been - * terminated. - * - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set. - * - * @callback_signature - * @code - * void callback_name(int error_code, const char* description) - * @endcode - * For more information about the callback parameters, see the - * [callback pointer type](@ref GLFWerrorfun). - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref error_handling - * @sa @ref glfwGetError - * - * @since Added in version 3.0. - * - * @ingroup init - */ -GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback); - -/*! @brief Returns the currently selected platform. - * - * This function returns the platform that was selected during initialization. The - * returned value will be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, - * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`. - * - * @return The currently selected platform, or zero if an error occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref platform - * @sa @ref glfwPlatformSupported - * - * @since Added in version 3.4. - * - * @ingroup init - */ -GLFWAPI int glfwGetPlatform(void); - -/*! @brief Returns whether the library includes support for the specified platform. - * - * This function returns whether the library was compiled with support for the specified - * platform. The platform must be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, - * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`. - * - * @param[in] platform The platform to query. - * @return `GLFW_TRUE` if the platform is supported, or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_INVALID_ENUM. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref platform - * @sa @ref glfwGetPlatform - * - * @since Added in version 3.4. - * - * @ingroup init - */ -GLFWAPI int glfwPlatformSupported(int platform); - -/*! @brief Returns the currently connected monitors. - * - * This function returns an array of handles for all currently connected - * monitors. The primary monitor is always first in the returned array. If no - * monitors were found, this function returns `NULL`. - * - * @param[out] count Where to store the number of monitors in the returned - * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if no monitors were found or - * if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is guaranteed to be valid only until the - * monitor configuration changes or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_monitors - * @sa @ref monitor_event - * @sa @ref glfwGetPrimaryMonitor - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI GLFWmonitor** glfwGetMonitors(int* count); - -/*! @brief Returns the primary monitor. - * - * This function returns the primary monitor. This is usually the monitor - * where elements like the task bar or global menu bar are located. - * - * @return The primary monitor, or `NULL` if no monitors were found or if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @remark The primary monitor is always first in the array returned by @ref - * glfwGetMonitors. - * - * @sa @ref monitor_monitors - * @sa @ref glfwGetMonitors - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI GLFWmonitor* glfwGetPrimaryMonitor(void); - -/*! @brief Returns the position of the monitor's viewport on the virtual screen. - * - * This function returns the position, in screen coordinates, of the upper-left - * corner of the specified monitor. - * - * Any or all of the position arguments may be `NULL`. If an error occurs, all - * non-`NULL` position arguments will be set to zero. - * - * @param[in] monitor The monitor to query. - * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. - * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_properties - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); - -/*! @brief Retrieves the work area of the monitor. - * - * This function returns the position, in screen coordinates, of the upper-left - * corner of the work area of the specified monitor along with the work area - * size in screen coordinates. The work area is defined as the area of the - * monitor not occluded by the window system task bar where present. If no - * task bar exists then the work area is the monitor resolution in screen - * coordinates. - * - * Any or all of the position and size arguments may be `NULL`. If an error - * occurs, all non-`NULL` position and size arguments will be set to zero. - * - * @param[in] monitor The monitor to query. - * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. - * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. - * @param[out] width Where to store the monitor width, or `NULL`. - * @param[out] height Where to store the monitor height, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_workarea - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ -GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); - -/*! @brief Returns the physical size of the monitor. - * - * This function returns the size, in millimetres, of the display area of the - * specified monitor. - * - * Some platforms do not provide accurate monitor size information, either - * because the monitor [EDID][] data is incorrect or because the driver does - * not report it accurately. - * - * [EDID]: https://en.wikipedia.org/wiki/Extended_display_identification_data - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] monitor The monitor to query. - * @param[out] widthMM Where to store the width, in millimetres, of the - * monitor's display area, or `NULL`. - * @param[out] heightMM Where to store the height, in millimetres, of the - * monitor's display area, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark @win32 On Windows 8 and earlier the physical size is calculated from - * the current resolution and system DPI instead of querying the monitor EDID data. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_properties - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM); - -/*! @brief Retrieves the content scale for the specified monitor. - * - * This function retrieves the content scale for the specified monitor. The - * content scale is the ratio between the current DPI and the platform's - * default DPI. This is especially important for text and any UI elements. If - * the pixel dimensions of your UI scaled by this look appropriate on your - * machine then it should appear at a reasonable size on other machines - * regardless of their DPI and scaling settings. This relies on the system DPI - * and scaling settings being somewhat correct. - * - * The content scale may depend on both the monitor resolution and pixel - * density and on user settings. It may be very different from the raw DPI - * calculated from the physical size and current resolution. - * - * @param[in] monitor The monitor to query. - * @param[out] xscale Where to store the x-axis content scale, or `NULL`. - * @param[out] yscale Where to store the y-axis content scale, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland Fractional scaling information is not yet available for - * monitors, so this function only returns integer content scales. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_scale - * @sa @ref glfwGetWindowContentScale - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ -GLFWAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale); - -/*! @brief Returns the name of the specified monitor. - * - * This function returns a human-readable name, encoded as UTF-8, of the - * specified monitor. The name typically reflects the make and model of the - * monitor and is not guaranteed to be unique among the connected monitors. - * - * @param[in] monitor The monitor to query. - * @return The UTF-8 encoded name of the monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified monitor is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_properties - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI const char* glfwGetMonitorName(GLFWmonitor* monitor); - -/*! @brief Sets the user pointer of the specified monitor. - * - * This function sets the user-defined pointer of the specified monitor. The - * current value is retained until the monitor is disconnected. The initial - * value is `NULL`. - * - * This function may be called from the monitor callback, even for a monitor - * that is being disconnected. - * - * @param[in] monitor The monitor whose pointer to set. - * @param[in] pointer The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref monitor_userptr - * @sa @ref glfwGetMonitorUserPointer - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ -GLFWAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer); - -/*! @brief Returns the user pointer of the specified monitor. - * - * This function returns the current value of the user-defined pointer of the - * specified monitor. The initial value is `NULL`. - * - * This function may be called from the monitor callback, even for a monitor - * that is being disconnected. - * - * @param[in] monitor The monitor whose pointer to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref monitor_userptr - * @sa @ref glfwSetMonitorUserPointer - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ -GLFWAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor); - -/*! @brief Sets the monitor configuration callback. - * - * This function sets the monitor configuration callback, or removes the - * currently set callback. This is called when a monitor is connected to or - * disconnected from the system. - * - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWmonitor* monitor, int event) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWmonitorfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_event - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun callback); - -/*! @brief Returns the available video modes for the specified monitor. - * - * This function returns an array of all video modes supported by the specified - * monitor. The returned array is sorted in ascending order, first by color - * bit depth (the sum of all channel depths), then by resolution area (the - * product of width and height), then resolution width and finally by refresh - * rate. - * - * @param[in] monitor The monitor to query. - * @param[out] count Where to store the number of video modes in the returned - * array. This is set to zero if an error occurred. - * @return An array of video modes, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified monitor is - * disconnected, this function is called again for that monitor or the library - * is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_modes - * @sa @ref glfwGetVideoMode - * - * @since Added in version 1.0. - * @glfw3 Changed to return an array of modes for a specific monitor. - * - * @ingroup monitor - */ -GLFWAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); - -/*! @brief Returns the current mode of the specified monitor. - * - * This function returns the current video mode of the specified monitor. If - * you have created a full screen window for that monitor, the return value - * will depend on whether that window is iconified. - * - * @param[in] monitor The monitor to query. - * @return The current mode of the monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified monitor is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_modes - * @sa @ref glfwGetVideoModes - * - * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. - * - * @ingroup monitor - */ -GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); - -/*! @brief Generates a gamma ramp and sets it for the specified monitor. - * - * This function generates an appropriately sized gamma ramp from the specified - * exponent and then calls @ref glfwSetGammaRamp with it. The value must be - * a finite number greater than zero. - * - * The software controlled gamma ramp is applied _in addition_ to the hardware - * gamma correction, which today is usually 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. - * - * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref - * GLFW_SRGB_CAPABLE hint. - * - * @param[in] monitor The monitor whose gamma ramp to set. - * @param[in] gamma The desired exponent. - * - * @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. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_gamma - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); - -/*! @brief Returns the current gamma ramp for the specified monitor. - * - * This function returns the current gamma ramp of the specified monitor. - * - * @param[in] monitor The monitor to query. - * @return The current gamma ramp, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @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 - * returning `NULL`. - * - * @pointer_lifetime The returned structure and its arrays are allocated and - * freed by GLFW. You should not free them yourself. They are valid until the - * specified monitor is disconnected, this function is called again for that - * monitor or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_gamma - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); - -/*! @brief Sets the current gamma ramp for the specified monitor. - * - * This function sets the current gamma ramp for the specified monitor. The - * original gamma ramp for that monitor is saved by GLFW the first time this - * function is called and is restored by @ref glfwTerminate. - * - * The software controlled gamma ramp is applied _in addition_ to the hardware - * gamma correction, which today is usually 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. - * - * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref - * GLFW_SRGB_CAPABLE hint. - * - * @param[in] monitor The monitor whose gamma ramp to set. - * @param[in] ramp The gamma ramp to use. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR - * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @remark The size of the specified gamma ramp should match the size of the - * current ramp for that 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. - * - * @pointer_lifetime The specified gamma ramp is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_gamma - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ -GLFWAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); - -/*! @brief Resets all window hints to their default values. - * - * This function resets all window hints to their - * [default values](@ref window_hints_values). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hints - * @sa @ref glfwWindowHint - * @sa @ref glfwWindowHintString - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwDefaultWindowHints(void); - -/*! @brief Sets the specified window hint to the desired value. - * - * This function sets hints for the next call to @ref glfwCreateWindow. The - * hints, once set, retain their values until changed by a call to this - * function or @ref glfwDefaultWindowHints, or until the library is terminated. - * - * Only integer value hints can be set with this function. String value hints - * are set with @ref glfwWindowHintString. - * - * This function does not check whether the specified hint values are valid. - * If you set hints to invalid values this will instead be reported by the next - * call to @ref glfwCreateWindow. - * - * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will ignore them. - * Setting these hints requires no platform specific headers or functions. - * - * @param[in] hint The [window hint](@ref window_hints) to set. - * @param[in] value The new value of the window hint. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hints - * @sa @ref glfwWindowHintString - * @sa @ref glfwDefaultWindowHints - * - * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. - * - * @ingroup window - */ -GLFWAPI void glfwWindowHint(int hint, int value); - -/*! @brief Sets the specified window hint to the desired value. - * - * This function sets hints for the next call to @ref glfwCreateWindow. The - * hints, once set, retain their values until changed by a call to this - * function or @ref glfwDefaultWindowHints, or until the library is terminated. - * - * Only string type hints can be set with this function. Integer value hints - * are set with @ref glfwWindowHint. - * - * This function does not check whether the specified hint values are valid. - * If you set hints to invalid values this will instead be reported by the next - * call to @ref glfwCreateWindow. - * - * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will ignore them. - * Setting these hints requires no platform specific headers or functions. - * - * @param[in] hint The [window hint](@ref window_hints) to set. - * @param[in] value The new value of the window hint. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @pointer_lifetime The specified string is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hints - * @sa @ref glfwWindowHint - * @sa @ref glfwDefaultWindowHints - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI void glfwWindowHintString(int hint, const char* value); - -/*! @brief Creates a window and its associated context. - * - * This function creates a window and its associated OpenGL or OpenGL ES - * context. Most of the options controlling how the window and its context - * should be created are specified with [window hints](@ref window_hints). - * - * Successful creation does not change which context is current. Before you - * can use the newly created context, you need to - * [make it current](@ref context_current). For information about the `share` - * parameter, see @ref context_sharing. - * - * The created window, framebuffer and context may differ from what you - * requested, as not all parameters and hints are - * [hard constraints](@ref window_hints_hard). This includes the size of the - * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, see @ref - * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. - * - * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, the window will be windowed mode. - * Unless you have a way for the user to choose a specific monitor, it is - * recommended that you pick the primary monitor. For more information on how - * to query connected monitors, see @ref monitor_monitors. - * - * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window is not - * iconified, the supported video mode most closely matching the desired video - * mode is set for the specified monitor. For more information about full - * screen windows, including the creation of so called _windowed full screen_ - * or _borderless full screen_ windows, see @ref window_windowed_full_screen. - * - * Once you have created the window, you can switch it between windowed and - * full screen mode with @ref glfwSetWindowMonitor. This will not affect its - * OpenGL or OpenGL ES context. - * - * By default, newly created windows use the placement recommended by the - * window system. To create the window at a specific position, set the @ref - * GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints before creation. To - * restore the default behavior, set either or both hints back to - * `GLFW_ANY_POSITION`. - * - * As long as at least one full screen window is not iconified, the screensaver - * is prohibited from starting. - * - * Window systems put limits on window sizes. Very large or very small window - * dimensions may be overridden by the window system on creation. Check the - * actual [size](@ref window_size) after creation. - * - * The [swap interval](@ref buffer_swap) is not set during window creation and - * the initial value may vary depending on driver settings and defaults. - * - * @param[in] width The desired width, in screen coordinates, of the window. - * This must be greater than zero. - * @param[in] height The desired height, in screen coordinates, of the window. - * This must be greater than zero. - * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` for - * windowed mode. - * @param[in] share The window whose context to share resources with, or `NULL` - * to not share resources. - * @return The handle of the created window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref - * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE, @ref - * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark @win32 Window creation will fail if the Microsoft GDI software - * OpenGL implementation is the only one available. - * - * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it - * will be set as the initial icon for the window. If no such icon is present, - * the `IDI_APPLICATION` icon will be used instead. To set a different icon, - * see @ref glfwSetWindowIcon. - * - * @remark @win32 The context to share resources with must not be current on - * any other thread. - * - * @remark @macos The OS only supports core profile contexts for OpenGL - * versions 3.2 and later. Before creating an OpenGL context of version 3.2 or - * later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) - * hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all - * on macOS. - * - * @remark @macos The GLFW window has no icon, as it is not a document - * window, but the dock icon will be the same as the application bundle's icon. - * For more information on bundles, see the - * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library. - * - * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ - * - * @remark @macos The window frame will not be rendered at full resolution on - * Retina displays unless the - * [GLFW_SCALE_FRAMEBUFFER](@ref GLFW_SCALE_FRAMEBUFFER_hint) - * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the - * application bundle's `Info.plist`. For more information, see - * [High Resolution Guidelines for OS X][hidpi-guide] in the Mac Developer - * Library. The GLFW test and example programs use a custom `Info.plist` - * template for this, which can be found as `CMake/Info.plist.in` in the source - * tree. - * - * [hidpi-guide]: https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html - * - * @remark @macos When activating frame autosaving with - * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified - * window size and position may be overridden by previously saved values. - * - * @remark @wayland GLFW uses [libdecor][] where available to create its window - * decorations. This in turn uses server-side XDG decorations where available - * and provides high quality client-side decorations on compositors like GNOME. - * If both XDG decorations and libdecor are unavailable, GLFW falls back to - * a very simple set of window decorations that only support moving, resizing - * and the window manager's right-click menu. - * - * [libdecor]: https://gitlab.freedesktop.org/libdecor/libdecor - * - * @remark @x11 Some window managers will not respect the placement of - * initially hidden windows. - * - * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for - * a window to reach its requested state. This means you may not be able to - * query the final size, position or other attributes directly after window - * creation. - * - * @remark @x11 The class part of the `WM_CLASS` window property will by - * default be set to the window title passed to this function. The instance - * part will use the contents of the `RESOURCE_NAME` environment variable, if - * present and not empty, or fall back to the window title. Set the - * [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and - * [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to - * override this. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_creation - * @sa @ref glfwDestroyWindow - * - * @since Added in version 3.0. Replaces `glfwOpenWindow`. - * - * @ingroup window - */ -GLFWAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share); - -/*! @brief Destroys the specified window and its context. - * - * This function destroys the specified window and its context. On calling - * this function, no further callbacks will be called for that window. - * - * If the context of the specified window is current on the main thread, it is - * detached before being destroyed. - * - * @param[in] window The window to destroy. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @note The context of the specified window must not be current on any other - * thread when this function is called. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_creation - * @sa @ref glfwCreateWindow - * - * @since Added in version 3.0. Replaces `glfwCloseWindow`. - * - * @ingroup window - */ -GLFWAPI void glfwDestroyWindow(GLFWwindow* window); - -/*! @brief Checks the close flag of the specified window. - * - * This function returns the value of the close flag of the specified window. - * - * @param[in] window The window to query. - * @return The value of the close flag. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_close - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI int glfwWindowShouldClose(GLFWwindow* window); - -/*! @brief Sets the close flag of the specified window. - * - * This function sets the value of the close flag of the specified window. - * This can be used to override the user's attempt to close the window, or - * to signal that it should be closed. - * - * @param[in] window The window whose flag to change. - * @param[in] value The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_close - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value); - -/*! @brief Returns the title of the specified window. - * - * This function returns the window title, encoded as UTF-8, of the specified - * window. This is the title set previously by @ref glfwCreateWindow - * or @ref glfwSetWindowTitle. - * - * @param[in] window The window to query. - * @return The UTF-8 encoded window title, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark The returned title is currently a copy of the title last set by @ref - * glfwCreateWindow or @ref glfwSetWindowTitle. It does not include any - * additional text which may be appended by the platform or another program. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the next call to @ref - * glfwGetWindowTitle or @ref glfwSetWindowTitle, or until the library is - * terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_title - * @sa @ref glfwSetWindowTitle - * - * @since Added in version 3.4. - * - * @ingroup window - */ -GLFWAPI const char* glfwGetWindowTitle(GLFWwindow* window); - -/*! @brief Sets the title of the specified window. - * - * This function sets the window title, encoded as UTF-8, of the specified - * window. - * - * @param[in] window The window whose title to change. - * @param[in] title The UTF-8 encoded window title. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @macos The window title will not be updated until the next time you - * process events. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_title - * @sa @ref glfwGetWindowTitle - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); - -/*! @brief Sets the icon for the specified window. - * - * This function sets the icon of the specified window. If passed an array of - * candidate images, those of or closest to the sizes desired by the system are - * selected. If no images are specified, the window reverts to its default - * icon. - * - * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight - * bits per channel with the red channel first. They are arranged canonically - * as packed sequential rows, starting from the top-left corner. - * - * The desired image sizes varies depending on platform and system settings. - * The selected images will be rescaled as needed. Good sizes include 16x16, - * 32x32 and 48x48. - * - * @param[in] window The window whose icon to set. - * @param[in] count The number of images in the specified array, or zero to - * revert to the default window icon. - * @param[in] images The images to create the icon from. This is ignored if - * count is zero. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref - * GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @pointer_lifetime The specified image data is copied before this function - * returns. - * - * @remark @macos Regular windows do not have icons on macOS. This function - * will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as - * the application bundle's icon. For more information on bundles, see the - * [Bundle Programming Guide][bundle-guide] in the Mac Developer Library. - * - * [bundle-guide]: https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/ - * - * @remark @wayland There is no existing protocol to change an icon, the - * window will thus inherit the one defined in the application's desktop file. - * This function will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_icon - * - * @since Added in version 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); - -/*! @brief Retrieves the position of the content area of the specified window. - * - * This function retrieves the position, in screen coordinates, of the - * upper-left corner of the content area of the specified window. - * - * Any or all of the position arguments may be `NULL`. If an error occurs, all - * non-`NULL` position arguments will be set to zero. - * - * @param[in] window The window to query. - * @param[out] xpos Where to store the x-coordinate of the upper-left corner of - * the content area, or `NULL`. - * @param[out] ypos Where to store the y-coordinate of the upper-left corner of - * the content area, or `NULL`. - * - * @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 - * GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_pos - * @sa @ref glfwSetWindowPos - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); - -/*! @brief Sets the position of the content area of the specified window. - * - * This function sets the position, in screen coordinates, of the upper-left - * corner of the content area of the specified windowed mode window. If the - * window is a full screen window, this function does nothing. - * - * __Do not use this function__ to move an already visible window unless you - * have very good reasons for doing so, as it will confuse and annoy the user. - * - * The window manager may put limits on what positions are allowed. GLFW - * cannot and should not override these limits. - * - * @param[in] window The window to query. - * @param[in] xpos The x-coordinate of the upper-left corner of the content area. - * @param[in] ypos The y-coordinate of the upper-left corner of the content area. - * - * @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 - * GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_pos - * @sa @ref glfwGetWindowPos - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); - -/*! @brief Retrieves the size of the content area of the specified window. - * - * This function retrieves the size, in screen coordinates, of the content area - * of the specified window. If you wish to retrieve the size of the - * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] window The window whose size to retrieve. - * @param[out] width Where to store the width, in screen coordinates, of the - * content area, or `NULL`. - * @param[out] height Where to store the height, in screen coordinates, of the - * content area, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * @sa @ref glfwSetWindowSize - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); - -/*! @brief Sets the size limits of the specified window. - * - * This function sets the size limits of the content area of the specified - * window. If the window is full screen, the size limits only take effect - * once it is made windowed. If the window is not resizable, this function - * does nothing. - * - * The size limits are applied immediately to a windowed mode window and may - * cause it to be resized. - * - * The maximum dimensions must be greater than or equal to the minimum - * dimensions and all must be greater than or equal to zero. - * - * @param[in] window The window to set limits for. - * @param[in] minwidth The minimum width, in screen coordinates, of the content - * area, or `GLFW_DONT_CARE`. - * @param[in] minheight The minimum height, in screen coordinates, of the - * content area, or `GLFW_DONT_CARE`. - * @param[in] maxwidth The maximum width, in screen coordinates, of the content - * area, or `GLFW_DONT_CARE`. - * @param[in] maxheight The maximum height, in screen coordinates, of the - * content area, or `GLFW_DONT_CARE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @remark If you set size limits and an aspect ratio that conflict, the - * results are undefined. - * - * @remark @wayland The size limits will not be applied until the window is - * actually resized, either by the user or by the compositor. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_sizelimits - * @sa @ref glfwSetWindowAspectRatio - * - * @since Added in version 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); - -/*! @brief Sets the aspect ratio of the specified window. - * - * This function sets the required aspect ratio of the content area of the - * specified window. If the window is full screen, the aspect ratio only takes - * effect once it is made windowed. If the window is not resizable, this - * function does nothing. - * - * The aspect ratio is specified as a numerator and a denominator and both - * values must be greater than zero. For example, the common 16:9 aspect ratio - * is specified as 16 and 9, respectively. - * - * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect - * ratio limit is disabled. - * - * The aspect ratio is applied immediately to a windowed mode window and may - * cause it to be resized. - * - * @param[in] window The window to set limits for. - * @param[in] numer The numerator of the desired aspect ratio, or - * `GLFW_DONT_CARE`. - * @param[in] denom The denominator of the desired aspect ratio, or - * `GLFW_DONT_CARE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @remark If you set size limits and an aspect ratio that conflict, the - * results are undefined. - * - * @remark @wayland The aspect ratio will not be applied until the window is - * actually resized, either by the user or by the compositor. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_sizelimits - * @sa @ref glfwSetWindowSizeLimits - * - * @since Added in version 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); - -/*! @brief Sets the size of the content area of the specified window. - * - * This function sets the size, in screen coordinates, of the content area of - * the specified window. - * - * For full screen windows, this function updates the resolution of its desired - * video mode and switches to the video mode closest to it, without affecting - * the window's context. As the context is unaffected, the bit depths of the - * framebuffer remain unchanged. - * - * If you wish to update the refresh rate of the desired video mode in addition - * to its resolution, see @ref glfwSetWindowMonitor. - * - * The window manager may put limits on what sizes are allowed. GLFW cannot - * and should not override these limits. - * - * @param[in] window The window to resize. - * @param[in] width The desired width, in screen coordinates, of the window - * content area. - * @param[in] height The desired height, in screen coordinates, of the window - * content area. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * @sa @ref glfwGetWindowSize - * @sa @ref glfwSetWindowMonitor - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); - -/*! @brief Retrieves the size of the framebuffer of the specified window. - * - * This function retrieves the size, in pixels, of the framebuffer of the - * specified window. If you wish to retrieve the size of the window in screen - * coordinates, see @ref glfwGetWindowSize. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] window The window whose framebuffer to query. - * @param[out] width Where to store the width, in pixels, of the framebuffer, - * or `NULL`. - * @param[out] height Where to store the height, in pixels, of the framebuffer, - * or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_fbsize - * @sa @ref glfwSetFramebufferSizeCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height); - -/*! @brief Retrieves the size of the frame of the window. - * - * This function retrieves the size, in screen coordinates, of each edge of the - * frame of the specified window. This size includes the title bar, if the - * window has one. The size of the frame may vary depending on the - * [window-related hints](@ref window_hints_wnd) used to create it. - * - * Because this function retrieves the size of each window frame edge and not - * the offset along a particular coordinate axis, the retrieved values will - * always be zero or positive. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] window The window whose frame size to query. - * @param[out] left Where to store the size, in screen coordinates, of the left - * edge of the window frame, or `NULL`. - * @param[out] top Where to store the size, in screen coordinates, of the top - * edge of the window frame, or `NULL`. - * @param[out] right Where to store the size, in screen coordinates, of the - * right edge of the window frame, or `NULL`. - * @param[out] bottom Where to store the size, in screen coordinates, of the - * bottom edge of the window frame, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * - * @since Added in version 3.1. - * - * @ingroup window - */ -GLFWAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom); - -/*! @brief Retrieves the content scale for the specified window. - * - * This function retrieves the content scale for the specified window. The - * content scale is the ratio between the current DPI and the platform's - * default DPI. This is especially important for text and any UI elements. If - * the pixel dimensions of your UI scaled by this look appropriate on your - * machine then it should appear at a reasonable size on other machines - * regardless of their DPI and scaling settings. This relies on the system DPI - * and scaling settings being somewhat correct. - * - * On platforms where each monitors can have its own content scale, the window - * content scale will depend on which monitor the system considers the window - * to be on. - * - * @param[in] window The window to query. - * @param[out] xscale Where to store the x-axis content scale, or `NULL`. - * @param[out] yscale Where to store the y-axis content scale, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_scale - * @sa @ref glfwSetWindowContentScaleCallback - * @sa @ref glfwGetMonitorContentScale - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale); - -/*! @brief Returns the opacity of the whole window. - * - * This function returns the opacity of the window, including any decorations. - * - * The opacity (or alpha) value is a positive finite number between zero and - * one, where zero is fully transparent and one is fully opaque. If the system - * does not support whole window transparency, this function always returns one. - * - * The initial opacity value for newly created windows is one. - * - * @param[in] window The window to query. - * @return The opacity value of the specified window. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_transparency - * @sa @ref glfwSetWindowOpacity - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI float glfwGetWindowOpacity(GLFWwindow* window); - -/*! @brief Sets the opacity of the whole window. - * - * This function sets the opacity of the window, including any decorations. - * - * The opacity (or alpha) value is a positive finite number between zero and - * one, where zero is fully transparent and one is fully opaque. - * - * The initial opacity value for newly created windows is one. - * - * A window created with framebuffer transparency may not use whole window - * transparency. The results of doing this are undefined. - * - * @param[in] window The window to set the opacity for. - * @param[in] opacity The desired opacity of the specified window. - * - * @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 to set an opacity factor for a window. - * This function will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_transparency - * @sa @ref glfwGetWindowOpacity - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); - -/*! @brief Iconifies the specified window. - * - * This function iconifies (minimizes) the specified window if it was - * previously restored. If the window is already iconified, this function does - * nothing. - * - * If the specified window is a full screen window, GLFW restores the original - * video mode of the monitor. The window's desired video mode is set again - * when the window is restored. - * - * @param[in] window The window to iconify. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland Once a window is iconified, @ref glfwRestoreWindow won’t - * 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 - * @sa @ref glfwRestoreWindow - * @sa @ref glfwMaximizeWindow - * - * @since Added in version 2.1. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwIconifyWindow(GLFWwindow* window); - -/*! @brief Restores the specified window. - * - * This function restores the specified window if it was previously iconified - * (minimized) or maximized. If the window is already restored, this function - * does nothing. - * - * If the specified window is an iconified full screen window, its desired - * video mode is set again for its monitor when the window is restored. - * - * @param[in] window The window to restore. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_iconify - * @sa @ref glfwIconifyWindow - * @sa @ref glfwMaximizeWindow - * - * @since Added in version 2.1. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwRestoreWindow(GLFWwindow* window); - -/*! @brief Maximizes the specified window. - * - * This function maximizes the specified window if it was previously not - * maximized. If the window is already maximized, this function does nothing. - * - * If the specified window is a full screen window, this function does nothing. - * - * @param[in] window The window to maximize. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @par Thread Safety - * This function may only be called from the main thread. - * - * @sa @ref window_iconify - * @sa @ref glfwIconifyWindow - * @sa @ref glfwRestoreWindow - * - * @since Added in GLFW 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); - -/*! @brief Makes the specified window visible. - * - * This function makes the specified window visible if it was previously - * hidden. If the window is already visible or is in full screen mode, this - * function does nothing. - * - * By default, windowed mode windows are focused when shown - * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint - * to change this behavior for all newly created windows, or change the - * behavior for an existing window with @ref glfwSetWindowAttrib. - * - * @param[in] window The window to make visible. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland Because Wayland wants every frame of the desktop to be - * complete, this function does not immediately make the window visible. - * Instead it will become visible the next time the window framebuffer is - * updated after this call. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hide - * @sa @ref glfwHideWindow - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwShowWindow(GLFWwindow* window); - -/*! @brief Hides the specified window. - * - * This function hides the specified window if it was previously visible. If - * the window is already hidden or is in full screen mode, this function does - * nothing. - * - * @param[in] window The window to hide. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hide - * @sa @ref glfwShowWindow - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwHideWindow(GLFWwindow* window); - -/*! @brief Brings the specified window to front and sets input focus. - * - * This function brings the specified window to front and sets input focus. - * The window should already be visible and not iconified. - * - * By default, both windowed and full screen mode windows are focused when - * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to - * disable this behavior. - * - * Also by default, windowed mode windows are focused when shown - * with @ref glfwShowWindow. Set the - * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior. - * - * __Do not use this function__ to steal focus from other applications unless - * you are certain that is what the user wants. Focus stealing can be - * extremely disruptive. - * - * For a less disruptive way of getting the user's attention, see - * [attention requests](@ref window_attention). - * - * @param[in] window The window to give input focus. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland The compositor will likely ignore focus requests unless - * another window created by the same application already has input focus. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_focus - * @sa @ref window_attention - * - * @since Added in version 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwFocusWindow(GLFWwindow* window); - -/*! @brief Requests user attention to the specified window. - * - * This function requests user attention to the specified window. On - * platforms where this is not supported, attention is requested to the - * application as a whole. - * - * Once the user has given attention, usually by focusing the window or - * application, the system will end the request automatically. - * - * @param[in] window The window to request attention to. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @macos Attention is requested to the application as a whole, not the - * specific window. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_attention - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); - -/*! @brief Returns the monitor that the window uses for full screen mode. - * - * This function returns the handle of the monitor that the specified window is - * in full screen on. - * - * @param[in] window The window to query. - * @return The monitor, or `NULL` if the window is in windowed mode or an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_monitor - * @sa @ref glfwSetWindowMonitor - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); - -/*! @brief Sets the mode, monitor, video mode and placement of a window. - * - * This function sets the monitor that the window uses for full screen mode or, - * if the monitor is `NULL`, makes it windowed mode. - * - * When setting a monitor, this function updates the width, height and refresh - * rate of the desired video mode and switches to the video mode closest to it. - * The window position is ignored when setting a monitor. - * - * When the monitor is `NULL`, the position, width and height are used to - * place the window content area. The refresh rate is ignored when no monitor - * is specified. - * - * If you only wish to update the resolution of a full screen window or the - * size of a windowed mode window, see @ref glfwSetWindowSize. - * - * When a window transitions from full screen to windowed mode, this function - * restores any previous window settings such as whether it is decorated, - * floating, resizable, has size or aspect ratio limits, etc. - * - * @param[in] window The window whose monitor, size or video mode to set. - * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. - * @param[in] xpos The desired x-coordinate of the upper-left corner of the - * content area. - * @param[in] ypos The desired y-coordinate of the upper-left corner of the - * content area. - * @param[in] width The desired with, in screen coordinates, of the content - * area or video mode. - * @param[in] height The desired height, in screen coordinates, of the content - * area or video mode. - * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode, - * or `GLFW_DONT_CARE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise - * 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. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_monitor - * @sa @ref window_full_screen - * @sa @ref glfwGetWindowMonitor - * @sa @ref glfwSetWindowSize - * - * @since Added in version 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); - -/*! @brief Returns an attribute of the specified window. - * - * This function returns the value of an attribute of the specified window or - * its OpenGL or OpenGL ES context. - * - * @param[in] window The window to query. - * @param[in] attrib The [window attribute](@ref window_attribs) whose value to - * return. - * @return The value of the attribute, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @remark Framebuffer related hints are not window attributes. See @ref - * window_attribs_fb for more information. - * - * @remark Zero is a valid value for many window and context related - * attributes so you cannot use a return value of zero as an indication of - * 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`. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_attribs - * @sa @ref glfwSetWindowAttrib - * - * @since Added in version 3.0. Replaces `glfwGetWindowParam` and - * `glfwGetGLVersion`. - * - * @ingroup window - */ -GLFWAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); - -/*! @brief Sets an attribute of the specified window. - * - * This function sets the value of an attribute of the specified window. - * - * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), - * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), - * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), - * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and - * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). - * [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib) - * - * Some of these attributes are ignored for full screen windows. The new - * value will take effect if the window is later made windowed. - * - * Some of these attributes are ignored for windowed mode windows. The new - * value will take effect if the window is later made full screen. - * - * @param[in] window The window to set the attribute for. - * @param[in] attrib A supported window attribute. - * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref - * GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @remark Calling @ref glfwGetWindowAttrib will always return the latest - * value, even if that value is ignored by the current mode of the window. - * - * @remark @wayland The [GLFW_FLOATING](@ref GLFW_FLOATING_attrib) window attribute is - * not supported. Setting this will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_attribs - * @sa @ref glfwGetWindowAttrib - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value); - -/*! @brief Sets the user pointer of the specified window. - * - * This function sets the user-defined pointer of the specified window. The - * current value is retained until the window is destroyed. The initial value - * is `NULL`. - * - * @param[in] window The window whose pointer to set. - * @param[in] pointer The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_userptr - * @sa @ref glfwGetWindowUserPointer - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer); - -/*! @brief Returns the user pointer of the specified window. - * - * This function returns the current value of the user-defined pointer of the - * specified window. The initial value is `NULL`. - * - * @param[in] window The window whose pointer to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_userptr - * @sa @ref glfwSetWindowUserPointer - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI void* glfwGetWindowUserPointer(GLFWwindow* window); - -/*! @brief Sets the position callback for the specified window. - * - * This function sets the position callback of the specified window, which is - * called when the window is moved. The callback is provided with the - * position, in screen coordinates, of the upper-left corner of the content - * area of the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int xpos, int ypos) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowposfun). - * - * @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. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_pos - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun callback); - -/*! @brief Sets the size callback for the specified window. - * - * This function sets the size callback of the specified window, which is - * called when the window is resized. The callback is provided with the size, - * in screen coordinates, of the content area of the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int width, int height) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowsizefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup window - */ -GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun callback); - -/*! @brief Sets the close callback for the specified window. - * - * This function sets the close callback of the specified window, which is - * called when the user attempts to close the window, for example by clicking - * the close widget in the title bar. - * - * The close flag is set before this callback is called, but you can modify it - * at any time with @ref glfwSetWindowShouldClose. - * - * The close callback is not triggered by @ref glfwDestroyWindow. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowclosefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark @macos Selecting Quit from the application menu will trigger the - * close callback for all windows. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_close - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup window - */ -GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback); - -/*! @brief Sets the refresh callback for the specified window. - * - * This function sets the refresh callback of the specified window, which is - * called when the content area of the window needs to be redrawn, for example - * if the window has been exposed after having been covered by another window. - * - * On compositing window systems such as Aero, Compiz, Aqua or Wayland, where - * the window contents are saved off-screen, this callback may be called only - * very infrequently or never at all. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window); - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowrefreshfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_refresh - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup window - */ -GLFWAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun callback); - -/*! @brief Sets the focus callback for the specified window. - * - * This function sets the focus callback of the specified window, which is - * called when the window gains or loses input focus. - * - * After the focus callback is called for a window that lost input focus, - * synthetic key and mouse button release events will be generated for all such - * that had been pressed. For more information, see @ref glfwSetKeyCallback - * and @ref glfwSetMouseButtonCallback. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int focused) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowfocusfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_focus - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun callback); - -/*! @brief Sets the iconify callback for the specified window. - * - * This function sets the iconification callback of the specified window, which - * is called when the window is iconified or restored. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int iconified) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowiconifyfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_iconify - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun callback); - -/*! @brief Sets the maximize callback for the specified window. - * - * This function sets the maximization callback of the specified window, which - * is called when the window is maximized or restored. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int maximized) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowmaximizefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_maximize - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback); - -/*! @brief Sets the framebuffer resize callback for the specified window. - * - * This function sets the framebuffer resize callback of the specified window, - * which is called when the framebuffer of the specified window is resized. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int width, int height) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWframebuffersizefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_fbsize - * - * @since Added in version 3.0. - * - * @ingroup window - */ -GLFWAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun callback); - -/*! @brief Sets the window content scale callback for the specified window. - * - * This function sets the window content scale callback of the specified window, - * which is called when the content scale of the specified window changes. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, float xscale, float yscale) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowcontentscalefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_scale - * @sa @ref glfwGetWindowContentScale - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun callback); - -/*! @brief Processes all pending events. - * - * This function processes only those events that are already in the event - * queue and then returns immediately. Processing events will cause the window - * and input callbacks associated with those events to be called. - * - * On some platforms, a window move, resize or menu operation will cause event - * processing to block. This is due to how event processing is designed on - * those platforms. You can use the - * [window refresh callback](@ref window_refresh) to redraw the contents of - * your window when necessary during such operations. - * - * Do not assume that callbacks you set will _only_ be called in response to - * event processing functions like this one. While it is necessary to poll for - * events, window systems that require GLFW to register callbacks of its own - * can pass events to GLFW in response to many window system function calls. - * GLFW will pass those events on to the application callbacks before - * returning. - * - * Event processing is not required for joystick input to work. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref events - * @sa @ref glfwWaitEvents - * @sa @ref glfwWaitEventsTimeout - * - * @since Added in version 1.0. - * - * @ingroup window - */ -GLFWAPI void glfwPollEvents(void); - -/*! @brief Waits until events are queued and processes them. - * - * This function puts the calling thread to sleep until at least one event is - * available in the event queue. Once one or more events are available, - * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue - * are processed and the function then returns immediately. Processing events - * will cause the window and input callbacks associated with those events to be - * called. - * - * Since not all events are associated with callbacks, this function may return - * without a callback having been called even if you are monitoring all - * callbacks. - * - * On some platforms, a window move, resize or menu operation will cause event - * processing to block. This is due to how event processing is designed on - * those platforms. You can use the - * [window refresh callback](@ref window_refresh) to redraw the contents of - * your window when necessary during such operations. - * - * Do not assume that callbacks you set will _only_ be called in response to - * event processing functions like this one. While it is necessary to poll for - * events, window systems that require GLFW to register callbacks of its own - * can pass events to GLFW in response to many window system function calls. - * GLFW will pass those events on to the application callbacks before - * returning. - * - * Event processing is not required for joystick input to work. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref events - * @sa @ref glfwPollEvents - * @sa @ref glfwWaitEventsTimeout - * - * @since Added in version 2.5. - * - * @ingroup window - */ -GLFWAPI void glfwWaitEvents(void); - -/*! @brief Waits with timeout until events are queued and processes them. - * - * This function puts the calling thread to sleep until at least one event is - * available in the event queue, or until the specified timeout is reached. If - * one or more events are available, it behaves exactly like @ref - * glfwPollEvents, i.e. the events in the queue are processed and the function - * then returns immediately. Processing events will cause the window and input - * callbacks associated with those events to be called. - * - * The timeout value must be a positive finite number. - * - * Since not all events are associated with callbacks, this function may return - * without a callback having been called even if you are monitoring all - * callbacks. - * - * On some platforms, a window move, resize or menu operation will cause event - * processing to block. This is due to how event processing is designed on - * those platforms. You can use the - * [window refresh callback](@ref window_refresh) to redraw the contents of - * your window when necessary during such operations. - * - * Do not assume that callbacks you set will _only_ be called in response to - * event processing functions like this one. While it is necessary to poll for - * events, window systems that require GLFW to register callbacks of its own - * can pass events to GLFW in response to many window system function calls. - * GLFW will pass those events on to the application callbacks before - * returning. - * - * Event processing is not required for joystick input to work. - * - * @param[in] timeout The maximum amount of time, in seconds, to wait. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref events - * @sa @ref glfwPollEvents - * @sa @ref glfwWaitEvents - * - * @since Added in version 3.2. - * - * @ingroup window - */ -GLFWAPI void glfwWaitEventsTimeout(double timeout); - -/*! @brief Posts an empty event to the event queue. - * - * This function posts an empty event from the current thread to the event - * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref events - * @sa @ref glfwWaitEvents - * @sa @ref glfwWaitEventsTimeout - * - * @since Added in version 3.1. - * - * @ingroup window - */ -GLFWAPI void glfwPostEmptyEvent(void); - -/*! @brief Returns the value of an input option for the specified window. - * - * This function returns the value of an input option for the specified window. - * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_MOUSE_MOTION. - * - * @param[in] window The window to query. - * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or - * `GLFW_RAW_MOUSE_MOTION`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref glfwSetInputMode - * - * @since Added in version 3.0. - * - * @ingroup input - */ -GLFWAPI int glfwGetInputMode(GLFWwindow* window, int mode); - -/*! @brief Sets an input option for the specified window. - * - * This function sets an input mode option for the specified window. The mode - * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS - * @ref GLFW_RAW_MOUSE_MOTION, or @ref GLFW_UNLIMITED_MOUSE_BUTTONS. - * - * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor - * modes: - * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally. - * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the - * content area of the window but does not restrict the cursor from leaving. - * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual - * and unlimited cursor movement. This is useful for implementing for - * example 3D camera controls. - * - `GLFW_CURSOR_CAPTURED` makes the cursor visible and confines it to the - * content area of the window. - * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to - * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are - * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` - * the next time it is called even if the key had been released before the - * call. This is useful when you are only interested in whether keys have been - * pressed but not when or in which order. - * - * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. - * If sticky mouse buttons are enabled, a mouse button press will ensure that - * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even - * if the mouse button had been released before the call. This is useful when - * you are only interested in whether mouse buttons have been pressed but not - * when or in which order. - * - * If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to - * enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled, - * callbacks that receive modifier bits will also have the @ref - * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on, - * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on. - * - * If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE` - * to enable raw (unscaled and unaccelerated) mouse motion when the cursor is - * disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported, - * attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref - * glfwRawMouseMotionSupported to check for support. - * - * If the mode is `GLFW_UNLIMITED_MOUSE_BUTTONS`, the value must be either - * `GLFW_TRUE` to disable the mouse button limit when calling the mouse button - * callback, or `GLFW_FALSE` to limit the mouse buttons sent to the callback - * to the mouse button token values up to `GLFW_MOUSE_BUTTON_LAST`. - * - * @param[in] window The window whose input mode to set. - * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or - * `GLFW_RAW_MOUSE_MOTION`. - * @param[in] value The new value of the specified input mode. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_PLATFORM_ERROR and @ref - * GLFW_FEATURE_UNAVAILABLE (see above). - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref glfwGetInputMode - * - * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. - * - * @ingroup input - */ -GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); - -/*! @brief Returns whether raw mouse motion is supported. - * - * This function returns whether raw mouse motion is supported on the current - * system. This status does not change after GLFW has been initialized so you - * only need to check this once. If you attempt to enable raw motion on - * a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted. - * - * Raw mouse motion is closer to the actual motion of the mouse across - * a surface. It is not affected by the scaling and acceleration applied to - * the motion of the desktop cursor. That processing is suitable for a cursor - * while raw motion is better for controlling for example a 3D camera. Because - * of this, raw mouse motion is only provided when the cursor is disabled. - * - * @return `GLFW_TRUE` if raw mouse motion is supported on the current machine, - * or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref raw_mouse_motion - * @sa @ref glfwSetInputMode - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI int glfwRawMouseMotionSupported(void); - -/*! @brief Returns the layout-specific name of the specified printable key. - * - * This function returns the name of the specified printable key, encoded as - * UTF-8. This is typically the character that key would produce without any - * modifier keys, intended for displaying key bindings to the user. For dead - * keys, it is typically the diacritic it would add to a character. - * - * __Do not use this function__ for [text input](@ref input_char). You will - * break text input for many languages even if it happens to work for yours. - * - * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key, - * otherwise the scancode is ignored. If you specify a non-printable key, or - * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this - * function returns `NULL` but does not emit an error. - * - * This behavior allows you to always pass in the arguments in the - * [key callback](@ref input_key) without modification. - * - * The printable keys are: - * - `GLFW_KEY_APOSTROPHE` - * - `GLFW_KEY_COMMA` - * - `GLFW_KEY_MINUS` - * - `GLFW_KEY_PERIOD` - * - `GLFW_KEY_SLASH` - * - `GLFW_KEY_SEMICOLON` - * - `GLFW_KEY_EQUAL` - * - `GLFW_KEY_LEFT_BRACKET` - * - `GLFW_KEY_RIGHT_BRACKET` - * - `GLFW_KEY_BACKSLASH` - * - `GLFW_KEY_WORLD_1` - * - `GLFW_KEY_WORLD_2` - * - `GLFW_KEY_0` to `GLFW_KEY_9` - * - `GLFW_KEY_A` to `GLFW_KEY_Z` - * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` - * - `GLFW_KEY_KP_DECIMAL` - * - `GLFW_KEY_KP_DIVIDE` - * - `GLFW_KEY_KP_MULTIPLY` - * - `GLFW_KEY_KP_SUBTRACT` - * - `GLFW_KEY_KP_ADD` - * - `GLFW_KEY_KP_EQUAL` - * - * Names for printable keys depend on keyboard layout, while names for - * non-printable keys are the same across layouts but depend on the application - * language and should be localized along with other user interface text. - * - * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. - * @param[in] scancode The scancode of the key to query. - * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE, @ref GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @remark The contents of the returned string may change when a keyboard - * layout change event is received. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_key_name - * - * @since Added in version 3.2. - * - * @ingroup input - */ -GLFWAPI const char* glfwGetKeyName(int key, int scancode); - -/*! @brief Returns the platform-specific scancode of the specified key. - * - * This function returns the platform-specific scancode of the specified key. - * - * If the specified [key token](@ref keys) corresponds to a physical key not - * supported on the current platform then this method will return `-1`. - * Calling this function with anything other than a key token will return `-1` - * and generate a @ref GLFW_INVALID_ENUM error. - * - * @param[in] key Any [key token](@ref keys). - * @return The platform-specific scancode for the key, or `-1` if the key is - * not supported on the current platform or an [error](@ref error_handling) - * occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref input_key - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI int glfwGetKeyScancode(int key); - -/*! @brief Returns the last reported state of a keyboard key for the specified - * window. - * - * This function returns the last state reported for the specified key to the - * specified window. The returned state is one of `GLFW_PRESS` or - * `GLFW_RELEASE`. The action `GLFW_REPEAT` is only reported to the key callback. - * - * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns - * `GLFW_PRESS` the first time you call it for a key that was pressed, even if - * that key has already been released. - * - * The key functions deal with physical keys, with [key tokens](@ref keys) - * named after their use on the standard US keyboard layout. If you want to - * input text, use the Unicode character callback instead. - * - * The [modifier key bit masks](@ref mods) are not key tokens and cannot be - * used with this function. - * - * __Do not use this function__ to implement [text input](@ref input_char). - * - * @param[in] window The desired window. - * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is - * not a valid key for this function. - * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_key - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ -GLFWAPI int glfwGetKey(GLFWwindow* window, int key); - -/*! @brief Returns the last reported state of a mouse button for the specified - * window. - * - * This function returns the last state reported for the specified mouse button - * to the specified window. The returned state is one of `GLFW_PRESS` or - * `GLFW_RELEASE`. - * - * If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function - * returns `GLFW_PRESS` the first time you call it for a mouse button that was - * pressed, even if that mouse button has already been released. - * - * The @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode does not effect the - * limit on buttons which can be polled with this function. - * - * @param[in] window The desired window. - * @param[in] button The desired [mouse button token](@ref buttons). - * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_mouse_button - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ -GLFWAPI int glfwGetMouseButton(GLFWwindow* window, int button); - -/*! @brief Retrieves the position of the cursor relative to the content area of - * the window. - * - * This function returns the position of the cursor, in screen coordinates, - * relative to the upper-left corner of the content area of the specified - * window. - * - * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor - * position is unbounded and limited only by the minimum and maximum values of - * a `double`. - * - * The coordinate can be converted to their integer equivalents with the - * `floor` function. Casting directly to an integer type works for positive - * coordinates, but fails for negative ones. - * - * Any or all of the position arguments may be `NULL`. If an error occurs, all - * non-`NULL` position arguments will be set to zero. - * - * @param[in] window The desired window. - * @param[out] xpos Where to store the cursor x-coordinate, relative to the - * left edge of the content area, or `NULL`. - * @param[out] ypos Where to store the cursor y-coordinate, relative to the to - * top edge of the content area, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_pos - * @sa @ref glfwSetCursorPos - * - * @since Added in version 3.0. Replaces `glfwGetMousePos`. - * - * @ingroup input - */ -GLFWAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); - -/*! @brief Sets the position of the cursor, relative to the content area of the - * window. - * - * This function sets the position, in screen coordinates, of the cursor - * relative to the upper-left corner of the content area of the specified - * window. The window must have input focus. If the window does not have - * input focus when this function is called, it fails silently. - * - * __Do not use this function__ to implement things like camera controls. GLFW - * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the - * cursor, transparently re-centers it and provides unconstrained cursor - * motion. See @ref glfwSetInputMode for more information. - * - * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is - * unconstrained and limited only by the minimum and maximum values of - * a `double`. - * - * @param[in] window The desired window. - * @param[in] xpos The desired x-coordinate, relative to the left edge of the - * content area. - * @param[in] ypos The desired y-coordinate, relative to the top edge of the - * content area. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @remark @wayland This function will only work when the cursor mode is - * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_pos - * @sa @ref glfwGetCursorPos - * - * @since Added in version 3.0. Replaces `glfwSetMousePos`. - * - * @ingroup input - */ -GLFWAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); - -/*! @brief Creates a custom cursor. - * - * Creates a new custom cursor image that can be set for a window with @ref - * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. - * Any remaining cursors are destroyed by @ref glfwTerminate. - * - * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight - * bits per channel with the red channel first. They are arranged canonically - * as packed sequential rows, starting from the top-left corner. - * - * The cursor hotspot is specified in pixels, relative to the upper-left corner - * of the cursor image. Like all other coordinate systems in GLFW, the X-axis - * points to the right and the Y-axis points down. - * - * @param[in] image The desired cursor image. - * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. - * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * @return The handle of the created cursor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The specified image data is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_object - * @sa @ref glfwDestroyCursor - * @sa @ref glfwCreateStandardCursor - * - * @since Added in version 3.1. - * - * @ingroup input - */ -GLFWAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot); - -/*! @brief Creates a cursor with a standard shape. - * - * Returns a cursor with a standard shape, that can be set for a window with - * @ref glfwSetCursor. The images for these cursors come from the system - * cursor theme and their exact appearance will vary between platforms. - * - * Most of these shapes are guaranteed to exist on every supported platform but - * a few may not be present. See the table below for details. - * - * Cursor shape | Windows | macOS | X11 | Wayland - * ------------------------------ | ------- | ----- | ------ | ------- - * @ref GLFW_ARROW_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_IBEAM_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_CROSSHAIR_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_POINTING_HAND_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_RESIZE_EW_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_RESIZE_NS_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_RESIZE_NWSE_CURSOR | Yes | Yes1 | Maybe2 | Maybe2 - * @ref GLFW_RESIZE_NESW_CURSOR | Yes | Yes1 | Maybe2 | Maybe2 - * @ref GLFW_RESIZE_ALL_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_NOT_ALLOWED_CURSOR | Yes | Yes | Maybe2 | Maybe2 - * - * 1) This uses a private system API and may fail in the future. - * - * 2) This uses a newer standard that not all cursor themes support. - * - * If the requested shape is not available, this function emits a @ref - * GLFW_CURSOR_UNAVAILABLE error and returns `NULL`. - * - * @param[in] shape One of the [standard shapes](@ref shapes). - * @return A new cursor ready to use or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_CURSOR_UNAVAILABLE and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_standard - * @sa @ref glfwCreateCursor - * - * @since Added in version 3.1. - * - * @ingroup input - */ -GLFWAPI GLFWcursor* glfwCreateStandardCursor(int shape); - -/*! @brief Destroys a cursor. - * - * This function destroys a cursor previously created with @ref - * glfwCreateCursor. Any remaining cursors will be destroyed by @ref - * glfwTerminate. - * - * If the specified cursor is current for any window, that window will be - * reverted to the default cursor. This does not affect the cursor mode. - * - * @param[in] cursor The cursor object to destroy. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_object - * @sa @ref glfwCreateCursor - * - * @since Added in version 3.1. - * - * @ingroup input - */ -GLFWAPI void glfwDestroyCursor(GLFWcursor* cursor); - -/*! @brief Sets the cursor for the window. - * - * This function sets the cursor image to be used when the cursor is over the - * content area of the specified window. The set cursor will only be visible - * when the [cursor mode](@ref cursor_mode) of the window is - * `GLFW_CURSOR_NORMAL`. - * - * On some platforms, the set cursor may not be visible unless the window also - * has input focus. - * - * @param[in] window The window to set the cursor for. - * @param[in] cursor The cursor to set, or `NULL` to switch back to the default - * arrow cursor. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_object - * - * @since Added in version 3.1. - * - * @ingroup input - */ -GLFWAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); - -/*! @brief Sets the key callback. - * - * This function sets the key callback of the specified window, which is called - * when a key is pressed, repeated or released. - * - * The key functions deal with physical keys, with layout independent - * [key tokens](@ref keys) named after their values in the standard US keyboard - * layout. If you want to input text, use the - * [character callback](@ref glfwSetCharCallback) instead. - * - * When a window loses input focus, it will generate synthetic key release - * events for all pressed keys with associated key tokens. You can tell these - * events from user-generated events by the fact that the synthetic ones are - * generated after the focus loss event has been processed, i.e. after the - * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. - * - * The scancode of a key is specific to that platform or sometimes even to that - * machine. Scancodes are intended to allow users to bind keys that don't have - * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their - * state is not saved and so it cannot be queried with @ref glfwGetKey. - * - * Sometimes GLFW needs to generate synthetic key events, in which case the - * scancode may be zero. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new key callback, or `NULL` to remove the currently - * set callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWkeyfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_key - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup input - */ -GLFWAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback); - -/*! @brief Sets the Unicode character callback. - * - * This function sets the character callback of the specified window, which is - * called when a Unicode character is input. - * - * The character callback is intended for Unicode text input. As it deals with - * characters, it is keyboard layout dependent, whereas the - * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1 - * to physical keys, as a key may produce zero, one or more characters. If you - * want to know whether a specific physical key was pressed or released, see - * the key callback instead. - * - * The character callback behaves as system text input normally does and will - * not be called if modifier keys are held down that would prevent normal text - * input on that platform, for example a Super (Command) key on macOS or Alt key - * on Windows. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcharfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_char - * - * @since Added in version 2.4. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup input - */ -GLFWAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun callback); - -/*! @brief Sets the Unicode character with modifiers callback. - * - * This function sets the character with modifiers callback of the specified - * window, which is called when a Unicode character is input regardless of what - * modifier keys are used. - * - * The character with modifiers callback is intended for implementing custom - * Unicode character input. For regular Unicode text input, see the - * [character callback](@ref glfwSetCharCallback). Like the character - * callback, the character with modifiers callback deals with characters and is - * keyboard layout dependent. Characters do not map 1:1 to physical keys, as - * a key may produce zero, one or more characters. If you want to know whether - * a specific physical key was pressed or released, see the - * [key callback](@ref glfwSetKeyCallback) instead. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * [error](@ref error_handling) occurred. - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint, int mods) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcharmodsfun). - * - * @deprecated Scheduled for removal in version 4.0. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_char - * - * @since Added in version 3.1. - * - * @ingroup input - */ -GLFWAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun callback); - -/*! @brief Sets the mouse button callback. - * - * This function sets the mouse button callback of the specified window, which - * is called when a mouse button is pressed or released. - * - * When a window loses input focus, it will generate synthetic mouse button - * release events for all pressed mouse buttons with associated button tokens. - * You can tell these events from user-generated events by the fact that the - * synthetic ones are generated after the focus loss event has been processed, - * i.e. after the [window focus callback](@ref glfwSetWindowFocusCallback) has - * been called. - * - * The reported `button` value can be higher than `GLFW_MOUSE_BUTTON_LAST` if - * the button does not have an associated [button token](@ref buttons) and the - * @ref GLFW_UNLIMITED_MOUSE_BUTTONS input mode is set. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int button, int action, int mods) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWmousebuttonfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_mouse_button - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup input - */ -GLFWAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun callback); - -/*! @brief Sets the cursor position callback. - * - * This function sets the cursor position callback of the specified window, - * which is called when the cursor is moved. The callback is provided with the - * position, in screen coordinates, relative to the upper-left corner of the - * content area of the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, double xpos, double ypos); - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcursorposfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_pos - * - * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. - * - * @ingroup input - */ -GLFWAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun callback); - -/*! @brief Sets the cursor enter/leave callback. - * - * This function sets the cursor boundary crossing callback of the specified - * window, which is called when the cursor enters or leaves the content area of - * the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int entered) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcursorenterfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_enter - * - * @since Added in version 3.0. - * - * @ingroup input - */ -GLFWAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun callback); - -/*! @brief Sets the scroll callback. - * - * This function sets the scroll callback of the specified window, which is - * called when a scrolling device is used, such as a mouse wheel or scrolling - * area of a touchpad. - * - * The scroll callback receives all scrolling input, like that from a mouse - * wheel or a touchpad scrolling area. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new scroll callback, or `NULL` to remove the - * currently set callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, double xoffset, double yoffset) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWscrollfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref scrolling - * - * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. - * - * @ingroup input - */ -GLFWAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback); - -/*! @brief Sets the path drop callback. - * - * This function sets the path drop callback of the specified window, which is - * called when one or more dragged paths are dropped on the window. - * - * Because the path array and its strings may have been generated specifically - * for that event, they are not guaranteed to be valid after the callback has - * returned. If you wish to use them after the callback returns, you need to - * make a deep copy. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new file drop callback, or `NULL` to remove the - * currently set callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int path_count, const char* paths[]) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWdropfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref path_drop - * - * @since Added in version 3.1. - * - * @ingroup input - */ -GLFWAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback); - -/*! @brief Returns whether the specified joystick is present. - * - * This function returns whether the specified joystick is present. - * - * There is no need to call this function before other functions that accept - * a joystick ID, as they all check for presence before performing any other - * work. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick - * - * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. - * - * @ingroup input - */ -GLFWAPI int glfwJoystickPresent(int jid); - -/*! @brief Returns the values of all axes of the specified joystick. - * - * This function returns the values of all axes of the specified joystick. - * Each element in the array is a value between -1.0 and 1.0. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] count Where to store the number of axis values in the returned - * array. This is set to zero if the joystick is not present or an error - * occurred. - * @return An array of axis values, or `NULL` if the joystick is not present or - * an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_axis - * - * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. - * - * @ingroup input - */ -GLFWAPI const float* glfwGetJoystickAxes(int jid, int* count); - -/*! @brief Returns the state of all buttons of the specified joystick. - * - * This function returns the state of all buttons of the specified joystick. - * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. - * - * For backward compatibility with earlier versions that did not have @ref - * glfwGetJoystickHats, the button array also includes all hats, each - * represented as four buttons. The hats are in the same order as returned by - * __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and - * _left_. To disable these extra buttons, set the @ref - * GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] count Where to store the number of button states in the returned - * array. This is set to zero if the joystick is not present or an error - * occurred. - * @return An array of button states, or `NULL` if the joystick is not present - * or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_button - * - * @since Added in version 2.2. - * @glfw3 Changed to return a dynamic array. - * - * @ingroup input - */ -GLFWAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count); - -/*! @brief Returns the state of all hats of the specified joystick. - * - * This function returns the state of all hats of the specified joystick. - * Each element in the array is one of the following values: - * - * Name | Value - * ---- | ----- - * `GLFW_HAT_CENTERED` | 0 - * `GLFW_HAT_UP` | 1 - * `GLFW_HAT_RIGHT` | 2 - * `GLFW_HAT_DOWN` | 4 - * `GLFW_HAT_LEFT` | 8 - * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP` - * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN` - * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP` - * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN` - * - * The diagonal directions are bitwise combinations of the primary (up, right, - * down and left) directions and you can test for these individually by ANDing - * it with the corresponding direction. - * - * @code - * if (hats[2] & GLFW_HAT_RIGHT) - * { - * // State of hat 2 could be right-up, right or right-down - * } - * @endcode - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] count Where to store the number of hat states in the returned - * array. This is set to zero if the joystick is not present or an error - * occurred. - * @return An array of hat states, or `NULL` if the joystick is not present - * or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected, this function is called again for that joystick or the library - * is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_hat - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count); - -/*! @brief Returns the name of the specified joystick. - * - * This function returns the name, encoded as UTF-8, of the specified joystick. - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick - * is not present or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_name - * - * @since Added in version 3.0. - * - * @ingroup input - */ -GLFWAPI const char* glfwGetJoystickName(int jid); - -/*! @brief Returns the SDL compatible GUID of the specified joystick. - * - * This function returns the SDL compatible GUID, as a UTF-8 encoded - * hexadecimal string, of the specified joystick. The returned string is - * allocated and freed by GLFW. You should not free it yourself. - * - * The GUID is what connects a joystick to a gamepad mapping. A connected - * joystick will always have a GUID even if there is no gamepad mapping - * assigned to it. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * The GUID uses the format introduced in SDL 2.0.5. This GUID tries to - * uniquely identify the make and model of a joystick but does not identify - * a specific unit, e.g. all wired Xbox 360 controllers will have the same - * GUID on that platform. The GUID for a unit may vary between platforms - * depending on what hardware information the platform specific APIs provide. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return The UTF-8 encoded GUID of the joystick, or `NULL` if the joystick - * is not present or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI const char* glfwGetJoystickGUID(int jid); - -/*! @brief Sets the user pointer of the specified joystick. - * - * This function sets the user-defined pointer of the specified joystick. The - * current value is retained until the joystick is disconnected. The initial - * value is `NULL`. - * - * This function may be called from the joystick callback, even for a joystick - * that is being disconnected. - * - * @param[in] jid The joystick whose pointer to set. - * @param[in] pointer The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref joystick_userptr - * @sa @ref glfwGetJoystickUserPointer - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI void glfwSetJoystickUserPointer(int jid, void* pointer); - -/*! @brief Returns the user pointer of the specified joystick. - * - * This function returns the current value of the user-defined pointer of the - * specified joystick. The initial value is `NULL`. - * - * This function may be called from the joystick callback, even for a joystick - * that is being disconnected. - * - * @param[in] jid The joystick whose pointer to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref joystick_userptr - * @sa @ref glfwSetJoystickUserPointer - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI void* glfwGetJoystickUserPointer(int jid); - -/*! @brief Returns whether the specified joystick has a gamepad mapping. - * - * This function returns whether the specified joystick is both present and has - * a gamepad mapping. - * - * If the specified joystick is present but does not have a gamepad mapping - * this function will return `GLFW_FALSE` but will not generate an error. Call - * @ref glfwJoystickPresent to check if a joystick is present regardless of - * whether it has a mapping. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping, - * or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwGetGamepadState - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI int glfwJoystickIsGamepad(int jid); - -/*! @brief Sets the joystick configuration callback. - * - * This function sets the joystick configuration callback, or removes the - * currently set callback. This is called when a joystick is connected to or - * disconnected from the system. - * - * For joystick connection and disconnection events to be delivered on all - * platforms, you need to call one of the [event processing](@ref events) - * functions. Joystick disconnection may also be detected and the callback - * called by joystick functions. The function will then return whatever it - * returns if the joystick is not present. - * - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(int jid, int event) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWjoystickfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_event - * - * @since Added in version 3.2. - * - * @ingroup input - */ -GLFWAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback); - -/*! @brief Adds the specified SDL_GameControllerDB gamepad mappings. - * - * This function parses the specified ASCII encoded string and updates the - * internal list with any gamepad mappings it finds. This string may - * contain either a single gamepad mapping or many mappings separated by - * newlines. The parser supports the full format of the `gamecontrollerdb.txt` - * source file including empty lines and comments. - * - * See @ref gamepad_mapping for a description of the format. - * - * If there is already a gamepad mapping for a given GUID in the internal list, - * it will be replaced by the one passed to this function. If the library is - * terminated and re-initialized the internal list will revert to the built-in - * default. - * - * @param[in] string The string containing the gamepad mappings. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_VALUE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwJoystickIsGamepad - * @sa @ref glfwGetGamepadName - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI int glfwUpdateGamepadMappings(const char* string); - -/*! @brief Returns the human-readable gamepad name for the specified joystick. - * - * This function returns the human-readable name of the gamepad from the - * gamepad mapping assigned to the specified joystick. - * - * If the specified joystick is not present or does not have a gamepad mapping - * this function will return `NULL` but will not generate an error. Call - * @ref glfwJoystickPresent to check whether it is present regardless of - * whether it has a mapping. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return The UTF-8 encoded name of the gamepad, or `NULL` if the - * joystick is not present, does not have a mapping or an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected, the gamepad mappings are updated or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwJoystickIsGamepad - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI const char* glfwGetGamepadName(int jid); - -/*! @brief Retrieves the state of the specified joystick remapped as a gamepad. - * - * This function retrieves the state of the specified joystick remapped to - * an Xbox-like gamepad. - * - * If the specified joystick is not present or does not have a gamepad mapping - * this function will return `GLFW_FALSE` but will not generate an error. Call - * @ref glfwJoystickPresent to check whether it is present regardless of - * whether it has a mapping. - * - * The Guide button may not be available for input as it is often hooked by the - * system or the Steam client. - * - * Not all devices have all the buttons or axes provided by @ref - * GLFWgamepadstate. Unavailable buttons and axes will always report - * `GLFW_RELEASE` and 0.0 respectively. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] state The gamepad input state of the joystick. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is - * connected, it has no gamepad mapping or an [error](@ref error_handling) - * occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwUpdateGamepadMappings - * @sa @ref glfwJoystickIsGamepad - * - * @since Added in version 3.3. - * - * @ingroup input - */ -GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state); - -/*! @brief Sets the clipboard to the specified string. - * - * This function sets the system clipboard to the specified, UTF-8 encoded - * string. - * - * @param[in] window Deprecated. Any valid window or `NULL`. - * @param[in] string A UTF-8 encoded string. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @win32 The clipboard on Windows has a single global lock for reading and - * writing. GLFW tries to acquire it a few times, which is almost always enough. If it - * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. - * It is safe to try this multiple times. - * - * @pointer_lifetime The specified string is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa @ref glfwGetClipboardString - * - * @since Added in version 3.0. - * - * @ingroup input - */ -GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); - -/*! @brief Returns the contents of the clipboard as a string. - * - * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. If the clipboard is empty or - * if its contents cannot be converted, `NULL` is returned and a @ref - * GLFW_FORMAT_UNAVAILABLE error is generated. - * - * @param[in] window Deprecated. Any valid window or `NULL`. - * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` - * if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. - * - * @remark @win32 The clipboard on Windows has a single global lock for reading and - * writing. GLFW tries to acquire it a few times, which is almost always enough. If it - * cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. - * It is safe to try this multiple times. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the next call to @ref - * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library - * is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa @ref glfwSetClipboardString - * - * @since Added in version 3.0. - * - * @ingroup input - */ -GLFWAPI const char* glfwGetClipboardString(GLFWwindow* window); - -/*! @brief Returns the GLFW time. - * - * This function returns the current GLFW time, in seconds. Unless the time - * has been set using @ref glfwSetTime it measures time elapsed since GLFW was - * initialized. - * - * This function and @ref glfwSetTime are helper functions on top of @ref - * glfwGetTimerFrequency and @ref glfwGetTimerValue. - * - * The resolution of the timer is system dependent, but is usually on the order - * of a few micro- or nanoseconds. It uses the highest-resolution monotonic - * time source on each operating system. - * - * @return The current time, in seconds, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Reading and - * writing of the internal base time is not atomic, so it needs to be - * externally synchronized with calls to @ref glfwSetTime. - * - * @sa @ref time - * - * @since Added in version 1.0. - * - * @ingroup input - */ -GLFWAPI double glfwGetTime(void); - -/*! @brief Sets the GLFW time. - * - * This function sets the current GLFW time, in seconds. The value must be - * a positive finite number less than or equal to 18446744073.0, which is - * approximately 584.5 years. - * - * This function and @ref glfwGetTime are helper functions on top of @ref - * glfwGetTimerFrequency and @ref glfwGetTimerValue. - * - * @param[in] time The new value, in seconds. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_VALUE. - * - * @remark The upper limit of GLFW time is calculated as - * floor((264 - 1) / 109) and is due to implementations - * storing nanoseconds in 64 bits. The limit may be increased in the future. - * - * @thread_safety This function may be called from any thread. Reading and - * writing of the internal base time is not atomic, so it needs to be - * externally synchronized with calls to @ref glfwGetTime. - * - * @sa @ref time - * - * @since Added in version 2.2. - * - * @ingroup input - */ -GLFWAPI void glfwSetTime(double time); - -/*! @brief Returns the current value of the raw timer. - * - * This function returns the current value of the raw timer, measured in - * 1 / frequency seconds. To get the frequency, call @ref - * glfwGetTimerFrequency. - * - * @return The value of the timer, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref time - * @sa @ref glfwGetTimerFrequency - * - * @since Added in version 3.2. - * - * @ingroup input - */ -GLFWAPI uint64_t glfwGetTimerValue(void); - -/*! @brief Returns the frequency, in Hz, of the raw timer. - * - * This function returns the frequency, in Hz, of the raw timer. - * - * @return The frequency of the timer, in Hz, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref time - * @sa @ref glfwGetTimerValue - * - * @since Added in version 3.2. - * - * @ingroup input - */ -GLFWAPI uint64_t glfwGetTimerFrequency(void); - -/*! @brief Makes the context of the specified window current for the calling - * thread. - * - * This function makes the OpenGL or OpenGL ES context of the specified window - * current on the calling thread. It can also detach the current context from - * the calling thread without making a new one current by passing in `NULL`. - * - * A context must only be made current on a single thread at a time and each - * thread can have only a single current context at a time. Making a context - * current detaches any previously current context on the calling thread. - * - * When moving a context between threads, you must detach it (make it - * non-current) on the old thread before making it current on the new one. - * - * By default, making a context non-current implicitly forces a pipeline flush. - * On machines that support `GL_KHR_context_flush_control`, you can control - * whether a context performs this flush by setting the - * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) - * hint. - * - * The specified window must have an OpenGL or OpenGL ES context. Specifying - * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT - * error. - * - * @param[in] window The window whose context to make current, or `NULL` to - * detach the current context. - * - * @remarks If the previously current context was created via a different - * context creation API than the one passed to this function, GLFW will still - * detach the previous one from its API before making the new one current. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_current - * @sa @ref glfwGetCurrentContext - * - * @since Added in version 3.0. - * - * @ingroup context - */ -GLFWAPI void glfwMakeContextCurrent(GLFWwindow* window); - -/*! @brief Returns the window whose context is current on the calling thread. - * - * This function returns the window whose OpenGL or OpenGL ES context is - * current on the calling thread. - * - * @return The window whose context is current, or `NULL` if no window's - * context is current. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_current - * @sa @ref glfwMakeContextCurrent - * - * @since Added in version 3.0. - * - * @ingroup context - */ -GLFWAPI GLFWwindow* glfwGetCurrentContext(void); - -/*! @brief Swaps the front and back buffers of the specified window. - * - * This function swaps the front and back buffers of the specified window when - * rendering with OpenGL or OpenGL ES. If the swap interval is greater than - * zero, the GPU driver waits the specified number of screen updates before - * swapping the buffers. - * - * The specified window must have an OpenGL or OpenGL ES context. Specifying - * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT - * error. - * - * This function does not apply to Vulkan. If you are rendering with Vulkan, - * see `vkQueuePresentKHR` instead. - * - * @param[in] window The window whose buffers to swap. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark __EGL:__ The context of the specified window must be current on the - * calling thread. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref buffer_swap - * @sa @ref glfwSwapInterval - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ -GLFWAPI void glfwSwapBuffers(GLFWwindow* window); - -/*! @brief Sets the swap interval for the current context. - * - * This function sets the swap interval for the current OpenGL or OpenGL ES - * context, i.e. the number of screen updates to wait from the time @ref - * glfwSwapBuffers was called before swapping the buffers and returning. This - * is sometimes called _vertical synchronization_, _vertical retrace - * synchronization_ or just _vsync_. - * - * A context that supports either of the `WGL_EXT_swap_control_tear` and - * `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap - * intervals, which allows the driver to swap immediately even if a frame - * arrives a little bit late. You can check for these extensions with @ref - * glfwExtensionSupported. - * - * A context must be current on the calling thread. Calling this function - * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. - * - * This function does not apply to Vulkan. If you are rendering with Vulkan, - * see the present mode of your swapchain instead. - * - * @param[in] interval The minimum number of screen updates to wait for - * until the buffers are swapped by @ref glfwSwapBuffers. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark This function is not called during context creation, leaving the - * swap interval set to whatever is the default for that API. This is done - * because some swap interval extensions used by GLFW do not allow the swap - * interval to be reset to zero once it has been set to a non-zero value. - * - * @remark Some GPU drivers do not honor the requested swap interval, either - * because of a user setting that overrides the application's request or due to - * bugs in the driver. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref buffer_swap - * @sa @ref glfwSwapBuffers - * - * @since Added in version 1.0. - * - * @ingroup context - */ -GLFWAPI void glfwSwapInterval(int interval); - -/*! @brief Returns whether the specified extension is available. - * - * This function returns whether the specified - * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for client API extension and context - * creation API extensions. - * - * A context must be current on the calling thread. Calling this function - * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. - * - * As this functions retrieves and searches one or more extension strings each - * call, it is recommended that you cache its results if it is going to be used - * frequently. The extension strings will not change during the lifetime of - * a context, so there is no danger in doing this. - * - * This function does not apply to Vulkan. If you are using Vulkan, see @ref - * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` - * and `vkEnumerateDeviceExtensionProperties` instead. - * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` - * otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_glext - * @sa @ref glfwGetProcAddress - * - * @since Added in version 1.0. - * - * @ingroup context - */ -GLFWAPI int glfwExtensionSupported(const char* extension); - -/*! @brief Returns the address of the specified function for the current - * context. - * - * This function returns the address of the specified OpenGL or OpenGL ES - * [core or extension function](@ref context_glext), if it is supported - * by the current context. - * - * A context must be current on the calling thread. Calling this function - * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. - * - * This function does not apply to Vulkan. If you are rendering with Vulkan, - * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and - * `vkGetDeviceProcAddr` instead. - * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark The address of a given function is not guaranteed to be the same - * between contexts. - * - * @remark This function may return a non-`NULL` address despite the - * associated version or extension not being available. Always check the - * context version or extension string first. - * - * @pointer_lifetime The returned function pointer is valid until the context - * is destroyed or the library is terminated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_glext - * @sa @ref glfwExtensionSupported - * - * @since Added in version 1.0. - * - * @ingroup context - */ -GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); - -/*! @brief Returns whether the Vulkan loader and an ICD have been found. - * - * This function returns whether the Vulkan loader and any minimally functional - * ICD have been found. - * - * The availability of a Vulkan loader and even an ICD does not by itself guarantee that - * surface creation or even instance creation is possible. Call @ref - * glfwGetRequiredInstanceExtensions to check whether the extensions necessary for Vulkan - * surface creation are available and @ref glfwGetPhysicalDevicePresentationSupport to - * check whether a queue family of a physical device supports image presentation. - * - * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE` - * otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref vulkan_support - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ -GLFWAPI int glfwVulkanSupported(void); - -/*! @brief Returns the Vulkan instance extensions required by GLFW. - * - * This function returns an array of names of Vulkan instance extensions required - * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the - * list will always contain `VK_KHR_surface`, so if you don't require any - * additional extensions you can pass this list directly to the - * `VkInstanceCreateInfo` struct. - * - * If Vulkan is not available on the machine, this function returns `NULL` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported - * to check whether Vulkan is at least minimally available. - * - * If Vulkan is available but no set of extensions allowing window surface - * creation was found, this function returns `NULL`. You may still use Vulkan - * for off-screen rendering and compute work. - * - * @param[out] count Where to store the number of extensions in the returned - * array. This is set to zero if an error occurred. - * @return An array of ASCII encoded extension names, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_API_UNAVAILABLE. - * - * @remark Additional extensions may be required by future versions of GLFW. - * You should check if any extensions you wish to enable are already in the - * returned array, as it is an error to specify an extension more than once in - * the `VkInstanceCreateInfo` struct. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is guaranteed to be valid only until the - * library is terminated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref vulkan_ext - * @sa @ref glfwCreateWindowSurface - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ -GLFWAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); - -#if defined(VK_VERSION_1_0) - -/*! @brief Returns the address of the specified Vulkan instance function. - * - * This function returns the address of the specified Vulkan core or extension - * function for the specified instance. If instance is set to `NULL` it can - * return any function exported from the Vulkan loader, including at least the - * following functions: - * - * - `vkEnumerateInstanceExtensionProperties` - * - `vkEnumerateInstanceLayerProperties` - * - `vkCreateInstance` - * - `vkGetInstanceProcAddr` - * - * If Vulkan is not available on the machine, this function returns `NULL` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported - * to check whether Vulkan is at least minimally available. - * - * This function is equivalent to calling `vkGetInstanceProcAddr` with - * a platform-specific query of the Vulkan loader as a fallback. - * - * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve - * functions related to instance creation. - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_API_UNAVAILABLE. - * - * @pointer_lifetime The returned function pointer is valid until the library - * is terminated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref vulkan_proc - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ -GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); - -/*! @brief Returns whether the specified queue family can present images. - * - * This function returns whether the specified queue family of the specified - * physical device supports presentation to the platform GLFW was built for. - * - * If Vulkan or the required window surface creation instance extensions are - * not available on the machine, or if the specified instance was not created - * with the required extensions, this function returns `GLFW_FALSE` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported - * to check whether Vulkan is at least minimally available and @ref - * glfwGetRequiredInstanceExtensions to check what instance extensions are - * required. - * - * @param[in] instance The instance that the physical device belongs to. - * @param[in] device The physical device that the queue family belongs to. - * @param[in] queuefamily The index of the queue family to query. - * @return `GLFW_TRUE` if the queue family supports presentation, or - * `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. - * - * @remark @macos This function currently always returns `GLFW_TRUE`, as the - * `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide - * a `vkGetPhysicalDevice*PresentationSupport` type function. - * - * @thread_safety This function may be called from any thread. For - * synchronization details of Vulkan objects, see the Vulkan specification. - * - * @sa @ref vulkan_present - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ -GLFWAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); - -/*! @brief Creates a Vulkan surface for the specified window. - * - * This function creates a Vulkan surface for the specified window. - * - * If the Vulkan loader or at least one minimally functional ICD were not found, - * this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref - * GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported to check whether - * Vulkan is at least minimally available. - * - * If the required window surface creation instance extensions are not - * available or if the specified instance was not created with these extensions - * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref - * glfwGetRequiredInstanceExtensions to check what instance extensions are - * required. - * - * The window surface cannot be shared with another API so the window must - * have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib) - * set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error - * and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`. - * - * The window surface must be destroyed before the specified Vulkan instance. - * It is the responsibility of the caller to destroy the window surface. GLFW - * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the - * surface. - * - * @param[in] instance The Vulkan instance to create the surface in. - * @param[in] window The window to create the surface for. - * @param[in] allocator The allocator to use, or `NULL` to use the default - * allocator. - * @param[out] surface Where to store the handle of the surface. This is set - * to `VK_NULL_HANDLE` if an error occurred. - * @return `VK_SUCCESS` if successful, or a Vulkan error code if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE - * - * @remark If an error occurs before the creation call is made, GLFW returns - * the Vulkan error code most appropriate for the error. Appropriate use of - * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should - * eliminate almost all occurrences of these errors. - * - * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the - * `VK_MVK_macos_surface` extension as a fallback. The name of the selected - * extension, if any, is included in the array returned by @ref - * glfwGetRequiredInstanceExtensions. - * - * @remark @macos This function creates and sets a `CAMetalLayer` instance for - * the window content view, which is required for MoltenVK to function. - * - * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, - * with the `VK_KHR_xlib_surface` extension as a fallback. You can make - * `VK_KHR_xlib_surface` the preferred extension by setting the - * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init - * hint. The name of the selected extension, if any, is included in the array - * returned by @ref glfwGetRequiredInstanceExtensions. - * - * @thread_safety This function may be called from any thread. For - * synchronization details of Vulkan objects, see the Vulkan specification. - * - * @sa @ref vulkan_surface - * @sa @ref glfwGetRequiredInstanceExtensions - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ -GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); - -#endif /*VK_VERSION_1_0*/ - - -/************************************************************************* - * Global definition cleanup - *************************************************************************/ - -/* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -#ifdef GLFW_WINGDIAPI_DEFINED - #undef WINGDIAPI - #undef GLFW_WINGDIAPI_DEFINED -#endif - -#ifdef GLFW_CALLBACK_DEFINED - #undef CALLBACK - #undef GLFW_CALLBACK_DEFINED -#endif - -/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally - * defined by some gl.h variants (OpenBSD) so define it after if needed. - */ -#ifndef GLAPIENTRY - #define GLAPIENTRY APIENTRY - #define GLFW_GLAPIENTRY_DEFINED -#endif - -/* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _glfw3_h_ */ - diff --git a/StgSharp.Native/glfw/glfw3.lib b/StgSharp.Native/glfw/glfw3.lib deleted file mode 100644 index 24e3068b4910be476f51c2385c917b1fe59d0d30..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 733462 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

s=~exMaa{e)ZE=*=+HppVpc;8n{Jl6>imH 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%0Ahe*W3+VbWR}?<_QbWh#Y&ef#%Oh87qiSd|6s>o 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 +hIjn3NSD22Me$zc@1Iq7t235 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 diff --git a/StgSharp.Native/glfw/glfw3native.h b/StgSharp.Native/glfw/glfw3native.h deleted file mode 100644 index a97c9840..00000000 --- a/StgSharp.Native/glfw/glfw3native.h +++ /dev/null @@ -1,632 +0,0 @@ -/************************************************************************* - * GLFW 3.4 - www.glfw->org - * A library for OpenGL, window and input - *------------------------------------------------------------------------ - * Copyright (c) 2002-2006 Marcus Geelnard - * Copyright (c) 2006-2018 Camilla Löwy org> - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would - * be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - *************************************************************************/ - -#ifndef _glfw3_native_h_ -#define _glfw3_native_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -/************************************************************************* - * Doxygen documentation - *************************************************************************/ - -/*! @file glfw3native.h - * @brief The header of the native access functions. - * - * This is the header file of the native access functions. See @ref native for - * more information. - */ -/*! @defgroup native Native access - * @brief Functions related to accessing native handles. - * - * **By using the native access functions you assert that you know what you're - * doing and how to fix problems caused by using them. If you don't, you - * shouldn't be using them.** - * - * Before the inclusion of @ref glfw3native.h, you may define zero or more - * window system API macro and zero or more context creation API macros. - * - * The chosen backends must match those the library was compiled for. Failure - * to do this will cause a link-time error. - * - * The available window API macros are: - * * `GLFW_EXPOSE_NATIVE_WIN32` - * * `GLFW_EXPOSE_NATIVE_COCOA` - * * `GLFW_EXPOSE_NATIVE_X11` - * * `GLFW_EXPOSE_NATIVE_WAYLAND` - * - * The available context API macros are: - * * `GLFW_EXPOSE_NATIVE_WGL` - * * `GLFW_EXPOSE_NATIVE_NSGL` - * * `GLFW_EXPOSE_NATIVE_GLX` - * * `GLFW_EXPOSE_NATIVE_EGL` - * * `GLFW_EXPOSE_NATIVE_OSMESA` - * - * These macros select which of the native access functions that are declared - * and which platform-specific headers to include. It is then up your (by - * definition platform-specific) code to handle which of these should be - * defined. - * - * If you do not want the platform-specific headers to be included, define - * `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header. - * - * @code - * #define GLFW_EXPOSE_NATIVE_WIN32 - * #define GLFW_EXPOSE_NATIVE_WGL - * #define GLFW_NATIVE_INCLUDE_NONE - * #include - * @endcode - */ - -/************************************************************************* - * System headers and types - *************************************************************************/ - -#if !defined(GLFW_NATIVE_INCLUDE_NONE) - -#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) -/* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for - * example to allow applications to correctly declare a GL_KHR_debug callback) - * but windows.h assumes no one will define APIENTRY before it does - */ -#if defined(GLFW_APIENTRY_DEFINED) -#undef APIENTRY -#undef GLFW_APIENTRY_DEFINED -#endif -#include -#endif - -#if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL) -#if defined(__OBJC__) -#import -#else -#include -#include -#endif -#endif - -#if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) -#include -#include -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) -#include -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WGL) -/* WGL is declared by windows.h */ -#endif -#if defined(GLFW_EXPOSE_NATIVE_NSGL) -/* NSGL is declared by Cocoa.h */ -#endif -#if defined(GLFW_EXPOSE_NATIVE_GLX) -/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by - * default it also acts as an OpenGL header - * However, glx.h will include gl.h, which will define it unconditionally - */ -#if defined(GLFW_GLAPIENTRY_DEFINED) -#undef GLAPIENTRY -#undef GLFW_GLAPIENTRY_DEFINED -#endif -#include -#endif -#if defined(GLFW_EXPOSE_NATIVE_EGL) -#include -#endif -#if defined(GLFW_EXPOSE_NATIVE_OSMESA) -/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by - * default it also acts as an OpenGL header - * However, osmesa.h will include gl.h, which will define it unconditionally - */ -#if defined(GLFW_GLAPIENTRY_DEFINED) -#undef GLAPIENTRY -#undef GLFW_GLAPIENTRY_DEFINED -#endif -#include -#endif - -#endif /*GLFW_NATIVE_INCLUDE_NONE*/ - -/************************************************************************* - * Functions - *************************************************************************/ - -#if defined(GLFW_EXPOSE_NATIVE_WIN32) -/*! @brief Returns the adapter device name of the specified monitor. - * - * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) - * of the specified monitor, or `NULL` if an [error](@ref error_handling) - * occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI const char *glfwGetWin32Adapter(GLFWmonitor *monitor); - -/*! @brief Returns the display device name of the specified monitor. - * - * @return The UTF-8 encoded display device name (for example - * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI const char *glfwGetWin32Monitor(GLFWmonitor *monitor); - -/*! @brief Returns the `HWND` of the specified window. - * - * @return The `HWND` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark The `HDC` associated with the window can be queried with the - * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) - * function. - * @code - * HDC dc = GetDC(glfwGetWin32Window(window)); - * @endcode - * This DC is private and does not need to be released. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI HWND glfwGetWin32Window(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WGL) -/*! @brief Returns the `HGLRC` of the specified window. - * - * @return The `HGLRC` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @remark The `HDC` associated with the window can be queried with the - * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) - * function. - * @code - * HDC dc = GetDC(glfwGetWin32Window(window)); - * @endcode - * This DC is private and does not need to be released. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI HGLRC glfwGetWGLContext(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_COCOA) -/*! @brief Returns the `CGDirectDisplayID` of the specified monitor. - * - * @return The `CGDirectDisplayID` of the specified monitor, or - * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor *monitor); - -/*! @brief Returns the `NSWindow` of the specified window. - * - * @return The `NSWindow` of the specified window, or `nil` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI id glfwGetCocoaWindow(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_NSGL) -/*! @brief Returns the `NSOpenGLContext` of the specified window. - * - * @return The `NSOpenGLContext` of the specified window, or `nil` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI id glfwGetNSGLContext(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_X11) -/*! @brief Returns the `Display` used by GLFW. - * - * @return The `Display` used by GLFW, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI Display *glfwGetX11Display(void); - -/*! @brief Returns the `RRCrtc` of the specified monitor. - * - * @return The `RRCrtc` of the specified monitor, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI RRCrtc glfwGetX11Adapter(GLFWmonitor *monitor); - -/*! @brief Returns the `RROutput` of the specified monitor. - * - * @return The `RROutput` of the specified monitor, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI RROutput glfwGetX11Monitor(GLFWmonitor *monitor); - -/*! @brief Returns the `Window` of the specified window. - * - * @return The `Window` of the specified window, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI Window glfwGetX11Window(GLFWwindow *window); - -/*! @brief Sets the current primary selection to the specified string. - * - * @param[in] string A UTF-8 encoded string. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The specified string is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa glfwGetX11SelectionString - * @sa glfwSetClipboardString - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI void glfwSetX11SelectionString(const char *string); - -/*! @brief Returns the contents of the current primary selection as a string. - * - * If the selection is empty or if its contents cannot be converted, `NULL` - * is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated. - * - * @return The contents of the selection as a UTF-8 encoded string, or `NULL` - * if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the next call to @ref - * glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the - * library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa glfwSetX11SelectionString - * @sa glfwGetClipboardString - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI const char *glfwGetX11SelectionString(void); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_GLX) -/*! @brief Returns the `GLXContext` of the specified window. - * - * @return The `GLXContext` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI GLXContext glfwGetGLXContext(GLFWwindow *window); - -/*! @brief Returns the `GLXWindow` of the specified window. - * - * @return The `GLXWindow` of the specified window, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI GLXWindow glfwGetGLXWindow(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) -/*! @brief Returns the `struct wl_display*` used by GLFW. - * - * @return The `struct wl_display*` used by GLFW, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI struct wl_display *glfwGetWaylandDisplay(void); - -/*! @brief Returns the `struct wl_output*` of the specified monitor. - * - * @return The `struct wl_output*` of the specified monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI struct wl_output *glfwGetWaylandMonitor(GLFWmonitor *monitor); - -/*! @brief Returns the main `struct wl_surface*` of the specified window. - * - * @return The main `struct wl_surface*` of the specified window, or `NULL` if - * an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI struct wl_surface *glfwGetWaylandWindow(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_EGL) -/*! @brief Returns the `EGLDisplay` used by GLFW. - * - * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark Because EGL is initialized on demand, this function will return - * `EGL_NO_DISPLAY` until the first context has been created via EGL. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI EGLDisplay glfwGetEGLDisplay(void); - -/*! @brief Returns the `EGLContext` of the specified window. - * - * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI EGLContext glfwGetEGLContext(GLFWwindow *window); - -/*! @brief Returns the `EGLSurface` of the specified window. - * - * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI EGLSurface glfwGetEGLSurface(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_OSMESA) -/*! @brief Retrieves the color buffer associated with the specified window. - * - * @param[in] window The window whose color buffer to retrieve. - * @param[out] width Where to store the width of the color buffer, or `NULL`. - * @param[out] height Where to store the height of the color buffer, or `NULL`. - * @param[out] format Where to store the OSMesa pixel format of the color - * buffer, or `NULL`. - * @param[out] buffer Where to store the address of the color buffer, or - * `NULL`. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI int glfwGetOSMesaColorBuffer(GLFWwindow *window, int *width, int *height, int *format, - void **buffer); - -/*! @brief Retrieves the depth buffer associated with the specified window. - * - * @param[in] window The window whose depth buffer to retrieve. - * @param[out] width Where to store the width of the depth buffer, or `NULL`. - * @param[out] height Where to store the height of the depth buffer, or `NULL`. - * @param[out] bytesPerValue Where to store the number of bytes per depth - * buffer element, or `NULL`. - * @param[out] buffer Where to store the address of the depth buffer, or - * `NULL`. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI int glfwGetOSMesaDepthBuffer(GLFWwindow *window, int *width, int *height, int *bytesPerValue, - void **buffer); - -/*! @brief Returns the `OSMesaContext` of the specified window. - * - * @return The `OSMesaContext` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow *window); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _glfw3_native_h_ */ diff --git a/StgSharp.Native/sn-head/StgSharpNative.h b/StgSharp.Native/sn-head/StgSharpNative.h index 2ab0d76a..7d7d86f2 100644 --- a/StgSharp.Native/sn-head/StgSharpNative.h +++ b/StgSharp.Native/sn-head/StgSharpNative.h @@ -8,12 +8,12 @@ #include "sn_internal.h" #define STBIDEF SN_API -#include "stb_image.h" +#include "../lib/stbi/stb_image.h" #include "gl.h" #include "wgl.h" #define GLFWAPI INTERNAL -#include "..\glfw\glfw3.h" +#include "glfw\glfw3.h" #include #include #include diff --git a/StgSharp.Native/sn-head/glfw3.h b/StgSharp.Native/sn-head/glfw3.h deleted file mode 100644 index d4215c17..00000000 --- a/StgSharp.Native/sn-head/glfw3.h +++ /dev/null @@ -1,6440 +0,0 @@ -/************************************************************************* - * GLFW 3.4 - www.glfw->org - * A library for OpenGL, window and input - *------------------------------------------------------------------------ - * Copyright (c) 2002-2006 Marcus Geelnard - * Copyright (c) 2006-2019 Camilla Löwy org> - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would - * be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - *************************************************************************/ - -#ifndef _glfw3_h_ -#define _glfw3_h_ - -#ifdef __cplusplus -extern "C" { -#endif - - - /************************************************************************* - * Doxygen documentation - *************************************************************************/ - - /*! @file glfw3.h - * @brief The header of the GLFW 3 API. - * - * This is the header file of the GLFW 3 API. It defines all its types and - * declares all its functions. - * - * For more information about how to use this file, see @ref build_include. - */ - /*! @defgroup context Context reference - * @brief Functions and types related to OpenGL and OpenGL ES contexts. - * - * This is the reference documentation for OpenGL and OpenGL ES context related - * functions. For more task-oriented information, see the @ref context_guide. - */ - /*! @defgroup vulkan Vulkan support reference - * @brief Functions and types related to Vulkan. - * - * This is the reference documentation for Vulkan related functions and types. - * For more task-oriented information, see the @ref vulkan_guide. - */ - /*! @defgroup init Initialization, version and error reference - * @brief Functions and types related to initialization and error handling. - * - * This is the reference documentation for initialization and termination of - * the library, version management and error handling. For more task-oriented - * information, see the @ref intro_guide. - */ - /*! @defgroup input Input reference - * @brief Functions and types related to input handling. - * - * This is the reference documentation for input related functions and types. - * For more task-oriented information, see the @ref input_guide. - */ - /*! @defgroup monitor Monitor reference - * @brief Functions and types related to monitors. - * - * This is the reference documentation for monitor related functions and types. - * For more task-oriented information, see the @ref monitor_guide. - */ - /*! @defgroup window Window reference - * @brief Functions and types related to windows. - * - * This is the reference documentation for window related functions and types, - * including creation, deletion and event polling. For more task-oriented - * information, see the @ref window_guide. - */ - - - /************************************************************************* - * Compiler- and platform-specific preprocessor work - *************************************************************************/ - - /* If we are we on Windows, we want a single define for it. - */ -#if !defined(_WIN32) && (defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__)) -#define _WIN32 -#endif /* _WIN32 */ - - /* Include because most Windows GLU headers need wchar_t and - * the macOS OpenGL header blocks the definition of ptrdiff_t by glext.h. - * Include it unconditionally to avoid surprising side-effects. - */ -#include - - /* Include because it is needed by Vulkan and related functions. - * Include it unconditionally to avoid surprising side-effects. - */ -#include - -#if defined(GLFW_INCLUDE_VULKAN) -#include -#endif /* Vulkan header */ - - /* The Vulkan header may have indirectly included windows.h (because of - * VK_USE_PLATFORM_WIN32_KHR) so we offer our replacement symbols after it. - */ - - /* It is customary to use APIENTRY for OpenGL function pointer declarations on - * all platforms. Additionally, the Windows OpenGL header needs APIENTRY. - */ -#if !defined(APIENTRY) -#if defined(_WIN32) -#define APIENTRY _stdcall -#else -#define APIENTRY -#endif -#define GLFW_APIENTRY_DEFINED -#endif /* APIENTRY */ - - /* Some Windows OpenGL headers need this. - */ -#if !defined(WINGDIAPI) && defined(_WIN32) -#define WINGDIAPI __declspec(dllimport) -#define GLFW_WINGDIAPI_DEFINED -#endif /* WINGDIAPI */ - - /* Some Windows GLU headers need this. - */ -#if !defined(CALLBACK) && defined(_WIN32) -#define CALLBACK __stdcall -#define GLFW_CALLBACK_DEFINED -#endif /* CALLBACK */ - - /* Include the chosen OpenGL or OpenGL ES headers. - */ -#if defined(GLFW_INCLUDE_ES1) - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#elif defined(GLFW_INCLUDE_ES2) - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#elif defined(GLFW_INCLUDE_ES3) - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#elif defined(GLFW_INCLUDE_ES31) - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#elif defined(GLFW_INCLUDE_ES32) - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#elif defined(GLFW_INCLUDE_GLCOREARB) - -#if defined(__APPLE__) - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif /*GLFW_INCLUDE_GLEXT*/ - -#else /*__APPLE__*/ - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#endif /*__APPLE__*/ - -#elif defined(GLFW_INCLUDE_GLU) - -#if defined(__APPLE__) - -#if defined(GLFW_INCLUDE_GLU) -#include -#endif - -#else /*__APPLE__*/ - -#if defined(GLFW_INCLUDE_GLU) -#include -#endif - -#endif /*__APPLE__*/ - -#elif !defined(GLFW_INCLUDE_NONE) && \ - !defined(__gl_h_) && \ - !defined(__gles1_gl_h_) && \ - !defined(__gles2_gl2_h_) && \ - !defined(__gles2_gl3_h_) && \ - !defined(__gles2_gl31_h_) && \ - !defined(__gles2_gl32_h_) && \ - !defined(__gl_glcorearb_h_) && \ - !defined(__gl2_h_) /*legacy*/ && \ - !defined(__gl3_h_) /*legacy*/ && \ - !defined(__gl31_h_) /*legacy*/ && \ - !defined(__gl32_h_) /*legacy*/ && \ - !defined(__glcorearb_h_) /*legacy*/ && \ - !defined(__GL_H__) /*non-standard*/ && \ - !defined(__gltypes_h_) /*non-standard*/ && \ - !defined(__glee_h_) /*non-standard*/ - -#if defined(__APPLE__) - -#if !defined(GLFW_INCLUDE_GLEXT) -#define GL_GLEXT_LEGACY -#endif -#include - -#else /*__APPLE__*/ - -#include -#if defined(GLFW_INCLUDE_GLEXT) -#include -#endif - -#endif /*__APPLE__*/ - -#endif /* OpenGL and OpenGL ES headers */ - -#ifndef SSCAPI - -#include "ssgc_internal.h" - -#endif // ! SSCAPI - - - - //#if defined(GLFW_DLL) && defined(_GLFW_BUILD_DLL) - // /* GLFW_DLL must be defined by applications that are linking against the DLL - // * version of the GLFW library. _GLFW_BUILD_DLL is defined by the GLFW - // * configuration header when compiling the DLL version of the library. - // */ - //#error "You must not have both GLFW_DLL and _GLFW_BUILD_DLL defined" - //#endif - // - // /* SSCAPI is used to declare public API functions for export - // * from the DLL / shared library / dynamic library. - // */ - //#if defined(_WIN32) && defined(_GLFW_BUILD_DLL) - /* We are building GLFW as a Win32 DLL */ - //#define SSCAPI __declspec(dllexport) - //#elif defined(_WIN32) && defined(GLFW_DLL) - /* We are calling a GLFW Win32 DLL */ - //#define SSCAPI __declspec(dllimport) - //#elif defined(__GNUC__) && defined(_GLFW_BUILD_DLL) - /* We are building GLFW as a Unix shared library */ - //#define SSCAPI __attribute__((visibility("default"))) - //#else - //#define SSCAPI - //#endif - - -/************************************************************************* - * GLFW API tokens - *************************************************************************/ - - /*! @name GLFW version macros - * @{ */ - /*! @brief The major version number of the GLFW header. - * - * The major version number of the GLFW header. This is incremented when the - * API is changed in non-compatible ways. - * @ingroup init - */ -#define GLFW_VERSION_MAJOR 3 - /*! @brief The minor version number of the GLFW header. - * - * The minor version number of the GLFW header. This is incremented when - * features are added to the API but it remains backward-compatible. - * @ingroup init - */ -#define GLFW_VERSION_MINOR 4 - /*! @brief The revision number of the GLFW header. - * - * The revision number of the GLFW header. This is incremented when a bug fix - * release is made that does not contain any API changes. - * @ingroup init - */ -#define GLFW_VERSION_REVISION 0 - /*! @} */ - - /*! @brief One. - * - * This is only semantic sugar for the number 1. You can instead use `1` or - * `true` or `_True` or `GL_TRUE` or `VK_TRUE` or anything else that is equal - * to one. - * - * @ingroup init - */ -#define GLFW_TRUE 1 - /*! @brief Zero. - * - * This is only semantic sugar for the number 0. You can instead use `0` or - * `false` or `_False` or `GL_FALSE` or `VK_FALSE` or anything else that is - * equal to zero. - * - * @ingroup init - */ -#define GLFW_FALSE 0 - - /*! @name Key and button actions - * @{ */ - /*! @brief The key or mouse button was released. - * - * The key or mouse button was released. - * - * @ingroup input - */ -#define GLFW_RELEASE 0 - /*! @brief The key or mouse button was pressed. - * - * The key or mouse button was pressed. - * - * @ingroup input - */ -#define GLFW_PRESS 1 - /*! @brief The key was held down until it repeated. - * - * The key was held down until it repeated. - * - * @ingroup input - */ -#define GLFW_REPEAT 2 - /*! @} */ - - /*! @defgroup hat_state Joystick hat states - * @brief Joystick hat states. - * - * See [joystick hat input](@ref joystick_hat) for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_HAT_CENTERED 0 -#define GLFW_HAT_UP 1 -#define GLFW_HAT_RIGHT 2 -#define GLFW_HAT_DOWN 4 -#define GLFW_HAT_LEFT 8 -#define GLFW_HAT_RIGHT_UP (GLFW_HAT_RIGHT | GLFW_HAT_UP) -#define GLFW_HAT_RIGHT_DOWN (GLFW_HAT_RIGHT | GLFW_HAT_DOWN) -#define GLFW_HAT_LEFT_UP (GLFW_HAT_LEFT | GLFW_HAT_UP) -#define GLFW_HAT_LEFT_DOWN (GLFW_HAT_LEFT | GLFW_HAT_DOWN) - /*! @} */ - - /*! @defgroup keys Keyboard keys - * @brief Keyboard key IDs. - * - * See [key input](@ref input_key) for how these are used. - * - * These key codes are inspired by the _USB HID Usage Tables v1.12_ (p. 53-60), - * but re-arranged to map to 7-bit ASCII for printable keys (function keys are - * put in the 256+ range). - * - * The naming of the key codes follow these rules: - * - The US keyboard layout is used - * - Names of printable alphanumeric characters are used (e.g. "A", "R", - * "3", etc.) - * - For non-alphanumeric characters, Unicode:ish names are used (e.g. - * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not - * correspond to the Unicode standard (usually for brevity) - * - Keys that lack a clear US mapping are named "WORLD_x" - * - For non-printable keys, custom names are used (e.g. "F4", - * "BACKSPACE", etc.) - * - * @ingroup input - * @{ - */ - - /* The unknown key */ -#define GLFW_KEY_UNKNOWN -1 - -/* Printable keys */ -#define GLFW_KEY_SPACE 32 -#define GLFW_KEY_APOSTROPHE 39 /* ' */ -#define GLFW_KEY_COMMA 44 /* , */ -#define GLFW_KEY_MINUS 45 /* - */ -#define GLFW_KEY_PERIOD 46 /* . */ -#define GLFW_KEY_SLASH 47 /* / */ -#define GLFW_KEY_0 48 -#define GLFW_KEY_1 49 -#define GLFW_KEY_2 50 -#define GLFW_KEY_3 51 -#define GLFW_KEY_4 52 -#define GLFW_KEY_5 53 -#define GLFW_KEY_6 54 -#define GLFW_KEY_7 55 -#define GLFW_KEY_8 56 -#define GLFW_KEY_9 57 -#define GLFW_KEY_SEMICOLON 59 /* ; */ -#define GLFW_KEY_EQUAL 61 /* = */ -#define GLFW_KEY_A 65 -#define GLFW_KEY_B 66 -#define GLFW_KEY_C 67 -#define GLFW_KEY_D 68 -#define GLFW_KEY_E 69 -#define GLFW_KEY_F 70 -#define GLFW_KEY_G 71 -#define GLFW_KEY_H 72 -#define GLFW_KEY_I 73 -#define GLFW_KEY_J 74 -#define GLFW_KEY_K 75 -#define GLFW_KEY_L 76 -#define GLFW_KEY_M 77 -#define GLFW_KEY_N 78 -#define GLFW_KEY_O 79 -#define GLFW_KEY_P 80 -#define GLFW_KEY_Q 81 -#define GLFW_KEY_R 82 -#define GLFW_KEY_S 83 -#define GLFW_KEY_T 84 -#define GLFW_KEY_U 85 -#define GLFW_KEY_V 86 -#define GLFW_KEY_W 87 -#define GLFW_KEY_X 88 -#define GLFW_KEY_Y 89 -#define GLFW_KEY_Z 90 -#define GLFW_KEY_LEFT_BRACKET 91 /* [ */ -#define GLFW_KEY_BACKSLASH 92 /* \ */ -#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */ -#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */ -#define GLFW_KEY_WORLD_1 161 /* non-US #1 */ -#define GLFW_KEY_WORLD_2 162 /* non-US #2 */ - -/* Function keys */ -#define GLFW_KEY_ESCAPE 256 -#define GLFW_KEY_ENTER 257 -#define GLFW_KEY_TAB 258 -#define GLFW_KEY_BACKSPACE 259 -#define GLFW_KEY_INSERT 260 -#define GLFW_KEY_DELETE 261 -#define GLFW_KEY_RIGHT 262 -#define GLFW_KEY_LEFT 263 -#define GLFW_KEY_DOWN 264 -#define GLFW_KEY_UP 265 -#define GLFW_KEY_PAGE_UP 266 -#define GLFW_KEY_PAGE_DOWN 267 -#define GLFW_KEY_HOME 268 -#define GLFW_KEY_END 269 -#define GLFW_KEY_CAPS_LOCK 280 -#define GLFW_KEY_SCROLL_LOCK 281 -#define GLFW_KEY_NUM_LOCK 282 -#define GLFW_KEY_PRINT_SCREEN 283 -#define GLFW_KEY_PAUSE 284 -#define GLFW_KEY_F1 290 -#define GLFW_KEY_F2 291 -#define GLFW_KEY_F3 292 -#define GLFW_KEY_F4 293 -#define GLFW_KEY_F5 294 -#define GLFW_KEY_F6 295 -#define GLFW_KEY_F7 296 -#define GLFW_KEY_F8 297 -#define GLFW_KEY_F9 298 -#define GLFW_KEY_F10 299 -#define GLFW_KEY_F11 300 -#define GLFW_KEY_F12 301 -#define GLFW_KEY_F13 302 -#define GLFW_KEY_F14 303 -#define GLFW_KEY_F15 304 -#define GLFW_KEY_F16 305 -#define GLFW_KEY_F17 306 -#define GLFW_KEY_F18 307 -#define GLFW_KEY_F19 308 -#define GLFW_KEY_F20 309 -#define GLFW_KEY_F21 310 -#define GLFW_KEY_F22 311 -#define GLFW_KEY_F23 312 -#define GLFW_KEY_F24 313 -#define GLFW_KEY_F25 314 -#define GLFW_KEY_KP_0 320 -#define GLFW_KEY_KP_1 321 -#define GLFW_KEY_KP_2 322 -#define GLFW_KEY_KP_3 323 -#define GLFW_KEY_KP_4 324 -#define GLFW_KEY_KP_5 325 -#define GLFW_KEY_KP_6 326 -#define GLFW_KEY_KP_7 327 -#define GLFW_KEY_KP_8 328 -#define GLFW_KEY_KP_9 329 -#define GLFW_KEY_KP_DECIMAL 330 -#define GLFW_KEY_KP_DIVIDE 331 -#define GLFW_KEY_KP_MULTIPLY 332 -#define GLFW_KEY_KP_SUBTRACT 333 -#define GLFW_KEY_KP_ADD 334 -#define GLFW_KEY_KP_ENTER 335 -#define GLFW_KEY_KP_EQUAL 336 -#define GLFW_KEY_LEFT_SHIFT 340 -#define GLFW_KEY_LEFT_CONTROL 341 -#define GLFW_KEY_LEFT_ALT 342 -#define GLFW_KEY_LEFT_SUPER 343 -#define GLFW_KEY_RIGHT_SHIFT 344 -#define GLFW_KEY_RIGHT_CONTROL 345 -#define GLFW_KEY_RIGHT_ALT 346 -#define GLFW_KEY_RIGHT_SUPER 347 -#define GLFW_KEY_MENU 348 - -#define GLFW_KEY_LAST GLFW_KEY_MENU - -/*! @} */ - -/*! @defgroup mods Modifier key flags - * @brief Modifier key flags. - * - * See [key input](@ref input_key) for how these are used. - * - * @ingroup input - * @{ */ - - /*! @brief If this bit is set one or more Shift keys were held down. - * - * If this bit is set one or more Shift keys were held down. - */ -#define GLFW_MOD_SHIFT 0x0001 - /*! @brief If this bit is set one or more Control keys were held down. - * - * If this bit is set one or more Control keys were held down. - */ -#define GLFW_MOD_CONTROL 0x0002 - /*! @brief If this bit is set one or more Alt keys were held down. - * - * If this bit is set one or more Alt keys were held down. - */ -#define GLFW_MOD_ALT 0x0004 - /*! @brief If this bit is set one or more Super keys were held down. - * - * If this bit is set one or more Super keys were held down. - */ -#define GLFW_MOD_SUPER 0x0008 - /*! @brief If this bit is set the Caps Lock key is enabled. - * - * If this bit is set the Caps Lock key is enabled and the @ref - * GLFW_LOCK_KEY_MODS input mode is set. - */ -#define GLFW_MOD_CAPS_LOCK 0x0010 - /*! @brief If this bit is set the Num Lock key is enabled. - * - * If this bit is set the Num Lock key is enabled and the @ref - * GLFW_LOCK_KEY_MODS input mode is set. - */ -#define GLFW_MOD_NUM_LOCK 0x0020 - - /*! @} */ - - /*! @defgroup buttons Mouse buttons - * @brief Mouse button IDs. - * - * See [mouse button input](@ref input_mouse_button) for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_MOUSE_BUTTON_1 0 -#define GLFW_MOUSE_BUTTON_2 1 -#define GLFW_MOUSE_BUTTON_3 2 -#define GLFW_MOUSE_BUTTON_4 3 -#define GLFW_MOUSE_BUTTON_5 4 -#define GLFW_MOUSE_BUTTON_6 5 -#define GLFW_MOUSE_BUTTON_7 6 -#define GLFW_MOUSE_BUTTON_8 7 -#define GLFW_MOUSE_BUTTON_LAST GLFW_MOUSE_BUTTON_8 -#define GLFW_MOUSE_BUTTON_LEFT GLFW_MOUSE_BUTTON_1 -#define GLFW_MOUSE_BUTTON_RIGHT GLFW_MOUSE_BUTTON_2 -#define GLFW_MOUSE_BUTTON_MIDDLE GLFW_MOUSE_BUTTON_3 - /*! @} */ - - /*! @defgroup joysticks Joysticks - * @brief Joystick IDs. - * - * See [joystick input](@ref joystick) for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_JOYSTICK_1 0 -#define GLFW_JOYSTICK_2 1 -#define GLFW_JOYSTICK_3 2 -#define GLFW_JOYSTICK_4 3 -#define GLFW_JOYSTICK_5 4 -#define GLFW_JOYSTICK_6 5 -#define GLFW_JOYSTICK_7 6 -#define GLFW_JOYSTICK_8 7 -#define GLFW_JOYSTICK_9 8 -#define GLFW_JOYSTICK_10 9 -#define GLFW_JOYSTICK_11 10 -#define GLFW_JOYSTICK_12 11 -#define GLFW_JOYSTICK_13 12 -#define GLFW_JOYSTICK_14 13 -#define GLFW_JOYSTICK_15 14 -#define GLFW_JOYSTICK_16 15 -#define GLFW_JOYSTICK_LAST GLFW_JOYSTICK_16 - /*! @} */ - - /*! @defgroup gamepad_buttons Gamepad buttons - * @brief Gamepad buttons. - * - * See @ref gamepad for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_GAMEPAD_BUTTON_A 0 -#define GLFW_GAMEPAD_BUTTON_B 1 -#define GLFW_GAMEPAD_BUTTON_X 2 -#define GLFW_GAMEPAD_BUTTON_Y 3 -#define GLFW_GAMEPAD_BUTTON_LEFT_BUMPER 4 -#define GLFW_GAMEPAD_BUTTON_RIGHT_BUMPER 5 -#define GLFW_GAMEPAD_BUTTON_BACK 6 -#define GLFW_GAMEPAD_BUTTON_START 7 -#define GLFW_GAMEPAD_BUTTON_GUIDE 8 -#define GLFW_GAMEPAD_BUTTON_LEFT_THUMB 9 -#define GLFW_GAMEPAD_BUTTON_RIGHT_THUMB 10 -#define GLFW_GAMEPAD_BUTTON_DPAD_UP 11 -#define GLFW_GAMEPAD_BUTTON_DPAD_RIGHT 12 -#define GLFW_GAMEPAD_BUTTON_DPAD_DOWN 13 -#define GLFW_GAMEPAD_BUTTON_DPAD_LEFT 14 -#define GLFW_GAMEPAD_BUTTON_LAST GLFW_GAMEPAD_BUTTON_DPAD_LEFT - -#define GLFW_GAMEPAD_BUTTON_CROSS GLFW_GAMEPAD_BUTTON_A -#define GLFW_GAMEPAD_BUTTON_CIRCLE GLFW_GAMEPAD_BUTTON_B -#define GLFW_GAMEPAD_BUTTON_SQUARE GLFW_GAMEPAD_BUTTON_X -#define GLFW_GAMEPAD_BUTTON_TRIANGLE GLFW_GAMEPAD_BUTTON_Y - /*! @} */ - - /*! @defgroup gamepad_axes Gamepad axes - * @brief Gamepad axes. - * - * See @ref gamepad for how these are used. - * - * @ingroup input - * @{ */ -#define GLFW_GAMEPAD_AXIS_LEFT_X 0 -#define GLFW_GAMEPAD_AXIS_LEFT_Y 1 -#define GLFW_GAMEPAD_AXIS_RIGHT_X 2 -#define GLFW_GAMEPAD_AXIS_RIGHT_Y 3 -#define GLFW_GAMEPAD_AXIS_LEFT_TRIGGER 4 -#define GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER 5 -#define GLFW_GAMEPAD_AXIS_LAST GLFW_GAMEPAD_AXIS_RIGHT_TRIGGER - /*! @} */ - - /*! @defgroup errors Error codes - * @brief Error codes. - * - * See [error handling](@ref error_handling) for how these are used. - * - * @ingroup init - * @{ */ - /*! @brief No error has occurred. - * - * No error has occurred. - * - * @analysis Yay. - */ -#define GLFW_NO_ERROR 0 - /*! @brief GLFW has not been initialized. - * - * This occurs if a GLFW function was called that must not be called unless the - * library is [initialized](@ref intro_init). - * - * @analysis Application programmer error. Initialize GLFW before calling any - * function that requires initialization. - */ -#define GLFW_NOT_INITIALIZED 0x00010001 - /*! @brief No context is current for this thread. - * - * This occurs if a GLFW function was called that needs and operates on the - * current OpenGL or OpenGL ES context but no context is current on the calling - * thread. One such function is @ref glfwSwapInterval. - * - * @analysis Application programmer error. Ensure a context is current before - * calling functions that require a current context. - */ -#define GLFW_NO_CURRENT_CONTEXT 0x00010002 - /*! @brief One of the arguments to the function was an invalid enum value. - * - * One of the arguments to the function was an invalid enum value, for example - * requesting @ref GLFW_RED_BITS with @ref glfwGetWindowAttrib. - * - * @analysis Application programmer error. Fix the offending call. - */ -#define GLFW_INVALID_ENUM 0x00010003 - /*! @brief One of the arguments to the function was an invalid value. - * - * One of the arguments to the function was an invalid value, for example - * requesting a non-existent OpenGL or OpenGL ES version like 2.7. - * - * Requesting a valid but unavailable OpenGL or OpenGL ES version will instead - * result in a @ref GLFW_VERSION_UNAVAILABLE error. - * - * @analysis Application programmer error. Fix the offending call. - */ -#define GLFW_INVALID_VALUE 0x00010004 - /*! @brief A memory allocation failed. - * - * A memory allocation failed. - * - * @analysis A bug in GLFW or the underlying operating system. Report the bug - * to our [issue tracker](https://github.com/glfw/glfw/issues). - */ -#define GLFW_OUT_OF_MEMORY 0x00010005 - /*! @brief GLFW could not find support for the requested API on the system. - * - * GLFW could not find support for the requested API on the system. - * - * @analysis The installed graphics driver does not support the requested - * API, or does not support it via the chosen context creation API. - * Below are a few examples. - * - * @par - * Some pre-installed Windows graphics drivers do not support OpenGL. AMD only - * supports OpenGL ES via EGL, while Nvidia and Intel only support it via - * a WGL or GLX extension. macOS does not provide OpenGL ES at all. The Mesa - * EGL, OpenGL and OpenGL ES libraries do not interface with the Nvidia binary - * driver. Older graphics drivers do not support Vulkan. - */ -#define GLFW_API_UNAVAILABLE 0x00010006 - /*! @brief The requested OpenGL or OpenGL ES version is not available. - * - * The requested OpenGL or OpenGL ES version (including any requested context - * or framebuffer hints) is not available on this machine. - * - * @analysis The machine does not support your requirements. If your - * application is sufficiently flexible, downgrade your requirements and try - * again. Otherwise, inform the user that their machine does not match your - * requirements. - * - * @par - * Future invalid OpenGL and OpenGL ES versions, for example OpenGL 4.8 if 5.0 - * comes out before the 4.x series gets that far, also fail with this error and - * not @ref GLFW_INVALID_VALUE, because GLFW cannot know what future versions - * will exist. - */ -#define GLFW_VERSION_UNAVAILABLE 0x00010007 - /*! @brief A platform-specific error occurred that does not match any of the - * more specific categories. - * - * A platform-specific error occurred that does not match any of the more - * specific categories. - * - * @analysis A bug or configuration error in GLFW, the underlying operating - * system or its drivers, or a lack of required resources. Report the issue to - * our [issue tracker](https://github.com/glfw/glfw/issues). - */ -#define GLFW_PLATFORM_ERROR 0x00010008 - /*! @brief The requested format is not supported or available. - * - * If emitted during window creation, the requested pixel format is not - * supported. - * - * If emitted when querying the clipboard, the contents of the clipboard could - * not be converted to the requested format. - * - * @analysis If emitted during window creation, one or more - * [hard constraints](@ref window_hints_hard) did not match any of the - * available pixel formats. If your application is sufficiently flexible, - * downgrade your requirements and try again. Otherwise, inform the user that - * their machine does not match your requirements. - * - * @par - * If emitted when querying the clipboard, ignore the error or report it to - * the user, as appropriate. - */ -#define GLFW_FORMAT_UNAVAILABLE 0x00010009 - /*! @brief The specified window does not have an OpenGL or OpenGL ES context. - * - * A window that does not have an OpenGL or OpenGL ES context was passed to - * a function that requires it to have one. - * - * @analysis Application programmer error. Fix the offending call. - */ -#define GLFW_NO_WINDOW_CONTEXT 0x0001000A - /*! @brief The specified cursor shape is not available. - * - * The specified standard cursor shape is not available, either because the - * current platform cursor theme does not provide it or because it is not - * available on the platform. - * - * @analysis Platform or system settings limitation. Pick another - * [standard cursor shape](@ref shapes) or create a - * [custom cursor](@ref cursor_custom). - */ -#define GLFW_CURSOR_UNAVAILABLE 0x0001000B - /*! @brief The requested feature is not provided by the platform. - * - * The requested feature is not provided by the platform, so GLFW is unable to - * implement it. The documentation for each function notes if it could emit - * this error. - * - * @analysis Platform or platform version limitation. The error can be ignored - * unless the feature is critical to the application. - * - * @par - * A function call that emits this error has no effect other than the error and - * updating any existing out parameters. - */ -#define GLFW_FEATURE_UNAVAILABLE 0x0001000C - /*! @brief The requested feature is not implemented for the platform. - * - * The requested feature has not yet been implemented in GLFW for this platform. - * - * @analysis An incomplete implementation of GLFW for this platform, hopefully - * fixed in a future release. The error can be ignored unless the feature is - * critical to the application. - * - * @par - * A function call that emits this error has no effect other than the error and - * updating any existing out parameters. - */ -#define GLFW_FEATURE_UNIMPLEMENTED 0x0001000D - /*! @brief Platform unavailable or no matching platform was found. - * - * If emitted during initialization, no matching platform was found. If @ref - * GLFW_PLATFORM is set to `GLFW_ANY_PLATFORM`, GLFW could not detect any of the - * platforms supported by this library binary, except for the Null platform. If set to - * a specific platform, it is either not supported by this library binary or GLFW was not - * able to detect it. - * - * If emitted by a native access function, GLFW was initialized for a different platform - * than the function is for. - * - * @analysis Failure to detect any platform usually only happens on non-macOS Unix - * systems, either when no window system is running or the program was run from - * a terminal that does not have the necessary environment variables. Fall back to - * a different platform if possible or notify the user that no usable platform was - * detected. - * - * Failure to detect a specific platform may have the same cause as above or be because - * support for that platform was not compiled in. Call @ref glfwPlatformSupported to - * check whether a specific platform is supported by a library binary. - */ -#define GLFW_PLATFORM_UNAVAILABLE 0x0001000E - /*! @} */ - - /*! @addtogroup window - * @{ */ - /*! @brief Input focus window hint and attribute - * - * Input focus [window hint](@ref GLFW_FOCUSED_hint) or - * [window attribute](@ref GLFW_FOCUSED_attrib). - */ -#define GLFW_FOCUSED 0x00020001 - /*! @brief Window iconification window attribute - * - * Window iconification [window attribute](@ref GLFW_ICONIFIED_attrib). - */ -#define GLFW_ICONIFIED 0x00020002 - /*! @brief Window resize-ability window hint and attribute - * - * Window resize-ability [window hint](@ref GLFW_RESIZABLE_hint) and - * [window attribute](@ref GLFW_RESIZABLE_attrib). - */ -#define GLFW_RESIZABLE 0x00020003 - /*! @brief Window visibility window hint and attribute - * - * Window visibility [window hint](@ref GLFW_VISIBLE_hint) and - * [window attribute](@ref GLFW_VISIBLE_attrib). - */ -#define GLFW_VISIBLE 0x00020004 - /*! @brief Window decoration window hint and attribute - * - * Window decoration [window hint](@ref GLFW_DECORATED_hint) and - * [window attribute](@ref GLFW_DECORATED_attrib). - */ -#define GLFW_DECORATED 0x00020005 - /*! @brief Window auto-iconification window hint and attribute - * - * Window auto-iconification [window hint](@ref GLFW_AUTO_ICONIFY_hint) and - * [window attribute](@ref GLFW_AUTO_ICONIFY_attrib). - */ -#define GLFW_AUTO_ICONIFY 0x00020006 - /*! @brief Window decoration window hint and attribute - * - * Window decoration [window hint](@ref GLFW_FLOATING_hint) and - * [window attribute](@ref GLFW_FLOATING_attrib). - */ -#define GLFW_FLOATING 0x00020007 - /*! @brief Window maximization window hint and attribute - * - * Window maximization [window hint](@ref GLFW_MAXIMIZED_hint) and - * [window attribute](@ref GLFW_MAXIMIZED_attrib). - */ -#define GLFW_MAXIMIZED 0x00020008 - /*! @brief Cursor centering window hint - * - * Cursor centering [window hint](@ref GLFW_CENTER_CURSOR_hint). - */ -#define GLFW_CENTER_CURSOR 0x00020009 - /*! @brief Window framebuffer transparency hint and attribute - * - * Window framebuffer transparency - * [window hint](@ref GLFW_TRANSPARENT_FRAMEBUFFER_hint) and - * [window attribute](@ref GLFW_TRANSPARENT_FRAMEBUFFER_attrib). - */ -#define GLFW_TRANSPARENT_FRAMEBUFFER 0x0002000A - /*! @brief Mouse cursor hover window attribute. - * - * Mouse cursor hover [window attribute](@ref GLFW_HOVERED_attrib). - */ -#define GLFW_HOVERED 0x0002000B - /*! @brief Input focus on calling show window hint and attribute - * - * Input focus [window hint](@ref GLFW_FOCUS_ON_SHOW_hint) or - * [window attribute](@ref GLFW_FOCUS_ON_SHOW_attrib). - */ -#define GLFW_FOCUS_ON_SHOW 0x0002000C - - /*! @brief Mouse input transparency window hint and attribute - * - * Mouse input transparency [window hint](@ref GLFW_MOUSE_PASSTHROUGH_hint) or - * [window attribute](@ref GLFW_MOUSE_PASSTHROUGH_attrib). - */ -#define GLFW_MOUSE_PASSTHROUGH 0x0002000D - - /*! @brief Initial position x-coordinate window hint. - * - * Initial position x-coordinate [window hint](@ref GLFW_POSITION_X). - */ -#define GLFW_POSITION_X 0x0002000E - - /*! @brief Initial position y-coordinate window hint. - * - * Initial position y-coordinate [window hint](@ref GLFW_POSITION_Y). - */ -#define GLFW_POSITION_Y 0x0002000F - - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). - */ -#define GLFW_RED_BITS 0x00021001 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_GREEN_BITS). - */ -#define GLFW_GREEN_BITS 0x00021002 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_BLUE_BITS). - */ -#define GLFW_BLUE_BITS 0x00021003 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ALPHA_BITS). - */ -#define GLFW_ALPHA_BITS 0x00021004 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_DEPTH_BITS). - */ -#define GLFW_DEPTH_BITS 0x00021005 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_STENCIL_BITS). - */ -#define GLFW_STENCIL_BITS 0x00021006 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_RED_BITS). - */ -#define GLFW_ACCUM_RED_BITS 0x00021007 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_GREEN_BITS). - */ -#define GLFW_ACCUM_GREEN_BITS 0x00021008 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_BLUE_BITS). - */ -#define GLFW_ACCUM_BLUE_BITS 0x00021009 - /*! @brief Framebuffer bit depth hint. - * - * Framebuffer bit depth [hint](@ref GLFW_ACCUM_ALPHA_BITS). - */ -#define GLFW_ACCUM_ALPHA_BITS 0x0002100A - /*! @brief Framebuffer auxiliary buffer hint. - * - * Framebuffer auxiliary buffer [hint](@ref GLFW_AUX_BUFFERS). - */ -#define GLFW_AUX_BUFFERS 0x0002100B - /*! @brief OpenGL stereoscopic rendering hint. - * - * OpenGL stereoscopic rendering [hint](@ref GLFW_STEREO). - */ -#define GLFW_STEREO 0x0002100C - /*! @brief Framebuffer MSAA samples hint. - * - * Framebuffer MSAA samples [hint](@ref GLFW_SAMPLES). - */ -#define GLFW_SAMPLES 0x0002100D - /*! @brief Framebuffer sRGB hint. - * - * Framebuffer sRGB [hint](@ref GLFW_SRGB_CAPABLE). - */ -#define GLFW_SRGB_CAPABLE 0x0002100E - /*! @brief Monitor refresh rate hint. - * - * Monitor refresh rate [hint](@ref GLFW_REFRESH_RATE). - */ -#define GLFW_REFRESH_RATE 0x0002100F - /*! @brief Framebuffer double buffering hint and attribute. - * - * Framebuffer double buffering [hint](@ref GLFW_DOUBLEBUFFER_hint) and - * [attribute](@ref GLFW_DOUBLEBUFFER_attrib). - */ -#define GLFW_DOUBLEBUFFER 0x00021010 - - /*! @brief Context client API hint and attribute. - * - * Context client API [hint](@ref GLFW_CLIENT_API_hint) and - * [attribute](@ref GLFW_CLIENT_API_attrib). - */ -#define GLFW_CLIENT_API 0x00022001 - /*! @brief Context client API major version hint and attribute. - * - * Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint) - * and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib). - */ -#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 - /*! @brief Context client API minor version hint and attribute. - * - * Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint) - * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib). - */ -#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 - /*! @brief Context client API revision number attribute. - * - * Context client API revision number - * [attribute](@ref GLFW_CONTEXT_REVISION_attrib). - */ -#define GLFW_CONTEXT_REVISION 0x00022004 - /*! @brief Context robustness hint and attribute. - * - * Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint) - * and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib). - */ -#define GLFW_CONTEXT_ROBUSTNESS 0x00022005 - /*! @brief OpenGL forward-compatibility hint and attribute. - * - * OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint) - * and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib). - */ -#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006 - /*! @brief Debug mode context hint and attribute. - * - * Debug mode context [hint](@ref GLFW_CONTEXT_DEBUG_hint) and - * [attribute](@ref GLFW_CONTEXT_DEBUG_attrib). - */ -#define GLFW_CONTEXT_DEBUG 0x00022007 - /*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_OPENGL_DEBUG_CONTEXT GLFW_CONTEXT_DEBUG - /*! @brief OpenGL profile hint and attribute. - * - * OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and - * [attribute](@ref GLFW_OPENGL_PROFILE_attrib). - */ -#define GLFW_OPENGL_PROFILE 0x00022008 - /*! @brief Context flush-on-release hint and attribute. - * - * Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and - * [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib). - */ -#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 - /*! @brief Context error suppression hint and attribute. - * - * Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and - * [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib). - */ -#define GLFW_CONTEXT_NO_ERROR 0x0002200A - /*! @brief Context creation API hint and attribute. - * - * Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and - * [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib). - */ -#define GLFW_CONTEXT_CREATION_API 0x0002200B - /*! @brief Window content area scaling window - * [window hint](@ref GLFW_SCALE_TO_MONITOR). - */ -#define GLFW_SCALE_TO_MONITOR 0x0002200C - /*! @brief macOS specific - * [window hint](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint). - */ -#define GLFW_COCOA_RETINA_FRAMEBUFFER 0x00023001 - /*! @brief macOS specific - * [window hint](@ref GLFW_COCOA_FRAME_NAME_hint). - */ -#define GLFW_COCOA_FRAME_NAME 0x00023002 - /*! @brief macOS specific - * [window hint](@ref GLFW_COCOA_GRAPHICS_SWITCHING_hint). - */ -#define GLFW_COCOA_GRAPHICS_SWITCHING 0x00023003 - /*! @brief X11 specific - * [window hint](@ref GLFW_X11_CLASS_NAME_hint). - */ -#define GLFW_X11_CLASS_NAME 0x00024001 - /*! @brief X11 specific - * [window hint](@ref GLFW_X11_CLASS_NAME_hint). - */ -#define GLFW_X11_INSTANCE_NAME 0x00024002 -#define GLFW_WIN32_KEYBOARD_MENU 0x00025001 - /*! @brief Wayland specific - * [window hint](@ref GLFW_WAYLAND_APP_ID_hint). - * - * Allows specification of the Wayland app_id. - */ -#define GLFW_WAYLAND_APP_ID 0x00026001 - /*! @} */ - -#define GLFW_NO_API 0 -#define GLFW_OPENGL_API 0x00030001 -#define GLFW_OPENGL_ES_API 0x00030002 - -#define GLFW_NO_ROBUSTNESS 0 -#define GLFW_NO_RESET_NOTIFICATION 0x00031001 -#define GLFW_LOSE_CONTEXT_ON_RESET 0x00031002 - -#define GLFW_OPENGL_ANY_PROFILE 0 -#define GLFW_OPENGL_CORE_PROFILE 0x00032001 -#define GLFW_OPENGL_COMPAT_PROFILE 0x00032002 - -#define GLFW_CURSOR 0x00033001 -#define GLFW_STICKY_KEYS 0x00033002 -#define GLFW_STICKY_MOUSE_BUTTONS 0x00033003 -#define GLFW_LOCK_KEY_MODS 0x00033004 -#define GLFW_RAW_MOUSE_MOTION 0x00033005 - -#define GLFW_CURSOR_NORMAL 0x00034001 -#define GLFW_CURSOR_HIDDEN 0x00034002 -#define GLFW_CURSOR_DISABLED 0x00034003 -#define GLFW_CURSOR_CAPTURED 0x00034004 - -#define GLFW_ANY_RELEASE_BEHAVIOR 0 -#define GLFW_RELEASE_BEHAVIOR_FLUSH 0x00035001 -#define GLFW_RELEASE_BEHAVIOR_NONE 0x00035002 - -#define GLFW_NATIVE_CONTEXT_API 0x00036001 -#define GLFW_EGL_CONTEXT_API 0x00036002 -#define GLFW_OSMESA_CONTEXT_API 0x00036003 - -#define GLFW_ANGLE_PLATFORM_TYPE_NONE 0x00037001 -#define GLFW_ANGLE_PLATFORM_TYPE_OPENGL 0x00037002 -#define GLFW_ANGLE_PLATFORM_TYPE_OPENGLES 0x00037003 -#define GLFW_ANGLE_PLATFORM_TYPE_D3D9 0x00037004 -#define GLFW_ANGLE_PLATFORM_TYPE_D3D11 0x00037005 -#define GLFW_ANGLE_PLATFORM_TYPE_VULKAN 0x00037007 -#define GLFW_ANGLE_PLATFORM_TYPE_METAL 0x00037008 - -#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001 -#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002 - -#define GLFW_ANY_POSITION 0x80000000 - -/*! @defgroup shapes Standard cursor shapes - * @brief Standard system cursor shapes. - * - * These are the [standard cursor shapes](@ref cursor_standard) that can be - * requested from the platform (window system). - * - * @ingroup input - * @{ */ - - /*! @brief The regular arrow cursor shape. - * - * The regular arrow cursor shape. - */ -#define GLFW_ARROW_CURSOR 0x00036001 - /*! @brief The text input I-beam cursor shape. - * - * The text input I-beam cursor shape. - */ -#define GLFW_IBEAM_CURSOR 0x00036002 - /*! @brief The crosshair cursor shape. - * - * The crosshair cursor shape. - */ -#define GLFW_CROSSHAIR_CURSOR 0x00036003 - /*! @brief The pointing hand cursor shape. - * - * The pointing hand cursor shape. - */ -#define GLFW_POINTING_HAND_CURSOR 0x00036004 - /*! @brief The horizontal resize/move arrow shape. - * - * The horizontal resize/move arrow shape. This is usually a horizontal - * double-headed arrow. - */ -#define GLFW_RESIZE_EW_CURSOR 0x00036005 - /*! @brief The vertical resize/move arrow shape. - * - * The vertical resize/move shape. This is usually a vertical double-headed - * arrow. - */ -#define GLFW_RESIZE_NS_CURSOR 0x00036006 - /*! @brief The top-left to bottom-right diagonal resize/move arrow shape. - * - * The top-left to bottom-right diagonal resize/move shape. This is usually - * a diagonal double-headed arrow. - * - * @note @macos This shape is provided by a private system API and may fail - * with @ref GLFW_CURSOR_UNAVAILABLE in the future. - * - * @note @x11 This shape is provided by a newer standard not supported by all - * cursor themes. - * - * @note @wayland This shape is provided by a newer standard not supported by - * all cursor themes. - */ -#define GLFW_RESIZE_NWSE_CURSOR 0x00036007 - /*! @brief The top-right to bottom-left diagonal resize/move arrow shape. - * - * The top-right to bottom-left diagonal resize/move shape. This is usually - * a diagonal double-headed arrow. - * - * @note @macos This shape is provided by a private system API and may fail - * with @ref GLFW_CURSOR_UNAVAILABLE in the future. - * - * @note @x11 This shape is provided by a newer standard not supported by all - * cursor themes. - * - * @note @wayland This shape is provided by a newer standard not supported by - * all cursor themes. - */ -#define GLFW_RESIZE_NESW_CURSOR 0x00036008 - /*! @brief The omni-directional resize/move cursor shape. - * - * The omni-directional resize cursor/move shape. This is usually either - * a combined horizontal and vertical double-headed arrow or a grabbing hand. - */ -#define GLFW_RESIZE_ALL_CURSOR 0x00036009 - /*! @brief The operation-not-allowed shape. - * - * The operation-not-allowed shape. This is usually a circle with a diagonal - * line through it. - * - * @note @x11 This shape is provided by a newer standard not supported by all - * cursor themes. - * - * @note @wayland This shape is provided by a newer standard not supported by - * all cursor themes. - */ -#define GLFW_NOT_ALLOWED_CURSOR 0x0003600A - /*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_HRESIZE_CURSOR GLFW_RESIZE_EW_CURSOR - /*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_VRESIZE_CURSOR GLFW_RESIZE_NS_CURSOR - /*! @brief Legacy name for compatibility. - * - * This is an alias for compatibility with earlier versions. - */ -#define GLFW_HAND_CURSOR GLFW_POINTING_HAND_CURSOR - /*! @} */ - -#define GLFW_CONNECTED 0x00040001 -#define GLFW_DISCONNECTED 0x00040002 - -/*! @addtogroup init - * @{ */ - /*! @brief Joystick hat buttons init hint. - * - * Joystick hat buttons [init hint](@ref GLFW_JOYSTICK_HAT_BUTTONS). - */ -#define GLFW_JOYSTICK_HAT_BUTTONS 0x00050001 - /*! @brief ANGLE rendering backend init hint. - * - * ANGLE rendering backend [init hint](@ref GLFW_ANGLE_PLATFORM_TYPE_hint). - */ -#define GLFW_ANGLE_PLATFORM_TYPE 0x00050002 - /*! @brief Platform selection init hint. - * - * Platform selection [init hint](@ref GLFW_PLATFORM). - */ -#define GLFW_PLATFORM 0x00050003 - /*! @brief macOS specific init hint. - * - * macOS specific [init hint](@ref GLFW_COCOA_CHDIR_RESOURCES_hint). - */ -#define GLFW_COCOA_CHDIR_RESOURCES 0x00051001 - /*! @brief macOS specific init hint. - * - * macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint). - */ -#define GLFW_COCOA_MENUBAR 0x00051002 - /*! @brief X11 specific init hint. - * - * X11 specific [init hint](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint). - */ -#define GLFW_X11_XCB_VULKAN_SURFACE 0x00052001 - /*! @brief Wayland specific init hint. - * - * Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint). - */ -#define GLFW_WAYLAND_LIBDECOR 0x00053001 - /*! @} */ - - /*! @addtogroup init - * @{ */ - /*! @brief Hint value that enables automatic platform selection. - * - * Hint value for @ref GLFW_PLATFORM that enables automatic platform selection. - */ -#define GLFW_ANY_PLATFORM 0x00060000 -#define GLFW_PLATFORM_WIN32 0x00060001 -#define GLFW_PLATFORM_COCOA 0x00060002 -#define GLFW_PLATFORM_WAYLAND 0x00060003 -#define GLFW_PLATFORM_X11 0x00060004 -#define GLFW_PLATFORM_NULL 0x00060005 - /*! @} */ - -#define GLFW_DONT_CARE -1 - - -/************************************************************************* - * GLFW API types - *************************************************************************/ - - /*! @brief Client API function pointer type. - * - * Generic function pointer used for returning client API function pointers - * without forcing a cast from a regular pointer. - * - * @sa @ref context_glext - * @sa @ref glfwGetProcAddress - * - * @since Added in version 3.0. - * - * @ingroup context - */ - typedef void (*GLFWglproc)(void); - - /*! @brief Vulkan API function pointer type. - * - * Generic function pointer used for returning Vulkan API function pointers - * without forcing a cast from a regular pointer. - * - * @sa @ref vulkan_proc - * @sa @ref glfwGetInstanceProcAddress - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ - typedef void (*GLFWvkproc)(void); - - /*! @brief Opaque monitor object. - * - * Opaque monitor object. - * - * @see @ref monitor_object - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - typedef struct GLFWmonitor GLFWmonitor; - - /*! @brief Opaque window object. - * - * Opaque window object. - * - * @see @ref window_object - * - * @since Added in version 3.0. - * - * @ingroup window - */ - typedef struct GLFWwindow GLFWwindow; - - /*! @brief Opaque cursor object. - * - * Opaque cursor object. - * - * @see @ref cursor_object - * - * @since Added in version 3.1. - * - * @ingroup input - */ - typedef struct GLFWcursor GLFWcursor; - - /*! @brief The function pointer type for memory allocation callbacks. - * - * This is the function pointer type for memory allocation callbacks. A memory - * allocation callback function has the following signature: - * @code - * void* function_name(size_t size, void* user) - * @endcode - * - * This function must return either a memory block at least `size` bytes long, - * or `NULL` if allocation failed. Note that not all parts of GLFW handle allocation - * failures gracefully yet. - * - * This function may be called during @ref glfwInit but before the library is - * flagged as initialized, as well as during @ref glfwTerminate after the - * library is no longer flagged as initialized. - * - * Any memory allocated by this function will be deallocated during library - * termination or earlier. - * - * The size will always be greater than zero. Allocations of size zero are filtered out - * before reaching the custom allocator. - * - * @param[in] size The minimum size, in bytes, of the memory block. - * @param[in] user The user-defined pointer from the allocator. - * @return The address of the newly allocated memory block, or `NULL` if an - * error occurred. - * - * @pointer_lifetime The returned memory block must be valid at least until it - * is deallocated. - * - * @reentrancy This function should not call any GLFW function. - * - * @thread_safety This function may be called from any thread that calls GLFW functions. - * - * @sa @ref init_allocator - * @sa @ref GLFWallocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ - typedef void* (*GLFWallocatefun)(size_t size, void* user); - - /*! @brief The function pointer type for memory reallocation callbacks. - * - * This is the function pointer type for memory reallocation callbacks. - * A memory reallocation callback function has the following signature: - * @code - * void* function_name(void* block, size_t size, void* user) - * @endcode - * - * This function must return a memory block at least `size` bytes long, or - * `NULL` if allocation failed. Note that not all parts of GLFW handle allocation - * failures gracefully yet. - * - * This function may be called during @ref glfwInit but before the library is - * flagged as initialized, as well as during @ref glfwTerminate after the - * library is no longer flagged as initialized. - * - * Any memory allocated by this function will be deallocated during library - * termination or earlier. - * - * The block address will never be `NULL` and the size will always be greater than zero. - * Reallocations of a block to size zero are converted into deallocations. Reallocations - * of `NULL` to a non-zero size are converted into regular allocations. - * - * @param[in] block The address of the memory block to reallocate. - * @param[in] size The new minimum size, in bytes, of the memory block. - * @param[in] user The user-defined pointer from the allocator. - * @return The address of the newly allocated or resized memory block, or - * `NULL` if an error occurred. - * - * @pointer_lifetime The returned memory block must be valid at least until it - * is deallocated. - * - * @reentrancy This function should not call any GLFW function. - * - * @thread_safety This function may be called from any thread that calls GLFW functions. - * - * @sa @ref init_allocator - * @sa @ref GLFWallocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ - typedef void* (*GLFWreallocatefun)(void* block, size_t size, void* user); - - /*! @brief The function pointer type for memory deallocation callbacks. - * - * This is the function pointer type for memory deallocation callbacks. - * A memory deallocation callback function has the following signature: - * @code - * void function_name(void* block, void* user) - * @endcode - * - * This function may deallocate the specified memory block. This memory block - * will have been allocated with the same allocator. - * - * This function may be called during @ref glfwInit but before the library is - * flagged as initialized, as well as during @ref glfwTerminate after the - * library is no longer flagged as initialized. - * - * The block address will never be `NULL`. Deallocations of `NULL` are filtered out - * before reaching the custom allocator. - * - * @param[in] block The address of the memory block to deallocate. - * @param[in] user The user-defined pointer from the allocator. - * - * @pointer_lifetime The specified memory block will not be accessed by GLFW - * after this function is called. - * - * @reentrancy This function should not call any GLFW function. - * - * @thread_safety This function may be called from any thread that calls GLFW functions. - * - * @sa @ref init_allocator - * @sa @ref GLFWallocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ - typedef void (*GLFWdeallocatefun)(void* block, void* user); - - /*! @brief The function pointer type for error callbacks. - * - * This is the function pointer type for error callbacks. An error callback - * function has the following signature: - * @code - * void callback_name(int error_code, const char* description) - * @endcode - * - * @param[in] error_code An [error code](@ref errors). Future releases may add - * more error codes. - * @param[in] description A UTF-8 encoded string describing the error. - * - * @pointer_lifetime The error description string is valid until the callback - * function returns. - * - * @sa @ref error_handling - * @sa @ref glfwSetErrorCallback - * - * @since Added in version 3.0. - * - * @ingroup init - */ - typedef void (*GLFWerrorfun)(int error_code, const char* description); - - /*! @brief The function pointer type for window position callbacks. - * - * This is the function pointer type for window position callbacks. A window - * position callback function has the following signature: - * @code - * void callback_name(GLFWwindow* window, int xpos, int ypos) - * @endcode - * - * @param[in] window The window that was moved. - * @param[in] xpos The new x-coordinate, in screen coordinates, of the - * upper-left corner of the content area of the window. - * @param[in] ypos The new y-coordinate, in screen coordinates, of the - * upper-left corner of the content area of the window. - * - * @sa @ref window_pos - * @sa @ref glfwSetWindowPosCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ - typedef void (*GLFWwindowposfun)(GLFWwindow* window, int xpos, int ypos); - - /*! @brief The function pointer type for window size callbacks. - * - * This is the function pointer type for window size callbacks. A window size - * callback function has the following signature: - * @code - * void callback_name(GLFWwindow* window, int width, int height) - * @endcode - * - * @param[in] window The window that was resized. - * @param[in] width The new width, in screen coordinates, of the window. - * @param[in] height The new height, in screen coordinates, of the window. - * - * @sa @ref window_size - * @sa @ref glfwSetWindowSizeCallback - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - typedef void (*GLFWwindowsizefun)(GLFWwindow* window, int width, int height); - - /*! @brief The function pointer type for window close callbacks. - * - * This is the function pointer type for window close callbacks. A window - * close callback function has the following signature: - * @code - * void function_name(GLFWwindow* window) - * @endcode - * - * @param[in] window The window that the user attempted to close. - * - * @sa @ref window_close - * @sa @ref glfwSetWindowCloseCallback - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - typedef void (*GLFWwindowclosefun)(GLFWwindow* window); - - /*! @brief The function pointer type for window content refresh callbacks. - * - * This is the function pointer type for window content refresh callbacks. - * A window content refresh callback function has the following signature: - * @code - * void function_name(GLFWwindow* window); - * @endcode - * - * @param[in] window The window whose content needs to be refreshed. - * - * @sa @ref window_refresh - * @sa @ref glfwSetWindowRefreshCallback - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - typedef void (*GLFWwindowrefreshfun)(GLFWwindow* window); - - /*! @brief The function pointer type for window focus callbacks. - * - * This is the function pointer type for window focus callbacks. A window - * focus callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int focused) - * @endcode - * - * @param[in] window The window that gained or lost input focus. - * @param[in] focused `GLFW_TRUE` if the window was given input focus, or - * `GLFW_FALSE` if it lost it. - * - * @sa @ref window_focus - * @sa @ref glfwSetWindowFocusCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ - typedef void (*GLFWwindowfocusfun)(GLFWwindow* window, int focused); - - /*! @brief The function pointer type for window iconify callbacks. - * - * This is the function pointer type for window iconify callbacks. A window - * iconify callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int iconified) - * @endcode - * - * @param[in] window The window that was iconified or restored. - * @param[in] iconified `GLFW_TRUE` if the window was iconified, or - * `GLFW_FALSE` if it was restored. - * - * @sa @ref window_iconify - * @sa @ref glfwSetWindowIconifyCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ - typedef void (*GLFWwindowiconifyfun)(GLFWwindow* window, int iconified); - - /*! @brief The function pointer type for window maximize callbacks. - * - * This is the function pointer type for window maximize callbacks. A window - * maximize callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int maximized) - * @endcode - * - * @param[in] window The window that was maximized or restored. - * @param[in] maximized `GLFW_TRUE` if the window was maximized, or - * `GLFW_FALSE` if it was restored. - * - * @sa @ref window_maximize - * @sa glfwSetWindowMaximizeCallback - * - * @since Added in version 3.3. - * - * @ingroup window - */ - typedef void (*GLFWwindowmaximizefun)(GLFWwindow* window, int maximized); - - /*! @brief The function pointer type for framebuffer size callbacks. - * - * This is the function pointer type for framebuffer size callbacks. - * A framebuffer size callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int width, int height) - * @endcode - * - * @param[in] window The window whose framebuffer was resized. - * @param[in] width The new width, in pixels, of the framebuffer. - * @param[in] height The new height, in pixels, of the framebuffer. - * - * @sa @ref window_fbsize - * @sa @ref glfwSetFramebufferSizeCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ - typedef void (*GLFWframebuffersizefun)(GLFWwindow* window, int width, int height); - - /*! @brief The function pointer type for window content scale callbacks. - * - * This is the function pointer type for window content scale callbacks. - * A window content scale callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, float xscale, float yscale) - * @endcode - * - * @param[in] window The window whose content scale changed. - * @param[in] xscale The new x-axis content scale of the window. - * @param[in] yscale The new y-axis content scale of the window. - * - * @sa @ref window_scale - * @sa @ref glfwSetWindowContentScaleCallback - * - * @since Added in version 3.3. - * - * @ingroup window - */ - typedef void (*GLFWwindowcontentscalefun)(GLFWwindow* window, float xscale, float yscale); - - /*! @brief The function pointer type for mouse button callbacks. - * - * This is the function pointer type for mouse button callback functions. - * A mouse button callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int button, int action, int mods) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] button The [mouse button](@ref buttons) that was pressed or - * released. - * @param[in] action One of `GLFW_PRESS` or `GLFW_RELEASE`. Future releases - * may add more actions. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were - * held down. - * - * @sa @ref input_mouse_button - * @sa @ref glfwSetMouseButtonCallback - * - * @since Added in version 1.0. - * @glfw3 Added window handle and modifier mask parameters. - * - * @ingroup input - */ - typedef void (*GLFWmousebuttonfun)(GLFWwindow* window, int button, int action, int mods); - - /*! @brief The function pointer type for cursor position callbacks. - * - * This is the function pointer type for cursor position callbacks. A cursor - * position callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, double xpos, double ypos); - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] xpos The new cursor x-coordinate, relative to the left edge of - * the content area. - * @param[in] ypos The new cursor y-coordinate, relative to the top edge of the - * content area. - * - * @sa @ref cursor_pos - * @sa @ref glfwSetCursorPosCallback - * - * @since Added in version 3.0. Replaces `GLFWmouseposfun`. - * - * @ingroup input - */ - typedef void (*GLFWcursorposfun)(GLFWwindow* window, double xpos, double ypos); - - /*! @brief The function pointer type for cursor enter/leave callbacks. - * - * This is the function pointer type for cursor enter/leave callbacks. - * A cursor enter/leave callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int entered) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] entered `GLFW_TRUE` if the cursor entered the window's content - * area, or `GLFW_FALSE` if it left it. - * - * @sa @ref cursor_enter - * @sa @ref glfwSetCursorEnterCallback - * - * @since Added in version 3.0. - * - * @ingroup input - */ - typedef void (*GLFWcursorenterfun)(GLFWwindow* window, int entered); - - /*! @brief The function pointer type for scroll callbacks. - * - * This is the function pointer type for scroll callbacks. A scroll callback - * function has the following signature: - * @code - * void function_name(GLFWwindow* window, double xoffset, double yoffset) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] xoffset The scroll offset along the x-axis. - * @param[in] yoffset The scroll offset along the y-axis. - * - * @sa @ref scrolling - * @sa @ref glfwSetScrollCallback - * - * @since Added in version 3.0. Replaces `GLFWmousewheelfun`. - * - * @ingroup input - */ - typedef void (*GLFWscrollfun)(GLFWwindow* window, double xoffset, double yoffset); - - /*! @brief The function pointer type for keyboard key callbacks. - * - * This is the function pointer type for keyboard key callbacks. A keyboard - * key callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] key The [keyboard key](@ref keys) that was pressed or released. - * @param[in] scancode The platform-specific scancode of the key. - * @param[in] action `GLFW_PRESS`, `GLFW_RELEASE` or `GLFW_REPEAT`. Future - * releases may add more actions. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were - * held down. - * - * @sa @ref input_key - * @sa @ref glfwSetKeyCallback - * - * @since Added in version 1.0. - * @glfw3 Added window handle, scancode and modifier mask parameters. - * - * @ingroup input - */ - typedef void (*GLFWkeyfun)(GLFWwindow* window, int key, int scancode, int action, int mods); - - /*! @brief The function pointer type for Unicode character callbacks. - * - * This is the function pointer type for Unicode character callbacks. - * A Unicode character callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] codepoint The Unicode code point of the character. - * - * @sa @ref input_char - * @sa @ref glfwSetCharCallback - * - * @since Added in version 2.4. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ - typedef void (*GLFWcharfun)(GLFWwindow* window, unsigned int codepoint); - - /*! @brief The function pointer type for Unicode character with modifiers - * callbacks. - * - * This is the function pointer type for Unicode character with modifiers - * callbacks. It is called for each input character, regardless of what - * modifier keys are held down. A Unicode character with modifiers callback - * function has the following signature: - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint, int mods) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] codepoint The Unicode code point of the character. - * @param[in] mods Bit field describing which [modifier keys](@ref mods) were - * held down. - * - * @sa @ref input_char - * @sa @ref glfwSetCharModsCallback - * - * @deprecated Scheduled for removal in version 4.0. - * - * @since Added in version 3.1. - * - * @ingroup input - */ - typedef void (*GLFWcharmodsfun)(GLFWwindow* window, unsigned int codepoint, int mods); - - /*! @brief The function pointer type for path drop callbacks. - * - * This is the function pointer type for path drop callbacks. A path drop - * callback function has the following signature: - * @code - * void function_name(GLFWwindow* window, int path_count, const char* paths[]) - * @endcode - * - * @param[in] window The window that received the event. - * @param[in] path_count The number of dropped paths. - * @param[in] paths The UTF-8 encoded file and/or directory path names. - * - * @pointer_lifetime The path array and its strings are valid until the - * callback function returns. - * - * @sa @ref path_drop - * @sa @ref glfwSetDropCallback - * - * @since Added in version 3.1. - * - * @ingroup input - */ - typedef void (*GLFWdropfun)(GLFWwindow* window, int path_count, const char* paths[]); - - /*! @brief The function pointer type for monitor configuration callbacks. - * - * This is the function pointer type for monitor configuration callbacks. - * A monitor callback function has the following signature: - * @code - * void function_name(GLFWmonitor* monitor, int event) - * @endcode - * - * @param[in] monitor The monitor that was connected or disconnected. - * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future - * releases may add more events. - * - * @sa @ref monitor_event - * @sa @ref glfwSetMonitorCallback - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - typedef void (*GLFWmonitorfun)(GLFWmonitor* monitor, int event); - - /*! @brief The function pointer type for joystick configuration callbacks. - * - * This is the function pointer type for joystick configuration callbacks. - * A joystick configuration callback function has the following signature: - * @code - * void function_name(int jid, int event) - * @endcode - * - * @param[in] jid The joystick that was connected or disconnected. - * @param[in] event One of `GLFW_CONNECTED` or `GLFW_DISCONNECTED`. Future - * releases may add more events. - * - * @sa @ref joystick_event - * @sa @ref glfwSetJoystickCallback - * - * @since Added in version 3.2. - * - * @ingroup input - */ - typedef void (*GLFWjoystickfun)(int jid, int event); - - /*! @brief Video mode type. - * - * This describes a single video mode. - * - * @sa @ref monitor_modes - * @sa @ref glfwGetVideoMode - * @sa @ref glfwGetVideoModes - * - * @since Added in version 1.0. - * @glfw3 Added refresh rate member. - * - * @ingroup monitor - */ - typedef struct GLFWvidmode - { - /*! The width, in screen coordinates, of the video mode. - */ - int width; - /*! The height, in screen coordinates, of the video mode. - */ - int height; - /*! The bit depth of the red channel of the video mode. - */ - int redBits; - /*! The bit depth of the green channel of the video mode. - */ - int greenBits; - /*! The bit depth of the blue channel of the video mode. - */ - int blueBits; - /*! The refresh rate, in Hz, of the video mode. - */ - int refreshRate; - } GLFWvidmode; - - /*! @brief Gamma ramp. - * - * This describes the gamma ramp for a monitor. - * - * @sa @ref monitor_gamma - * @sa @ref glfwGetGammaRamp - * @sa @ref glfwSetGammaRamp - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - typedef struct GLFWgammaramp - { - /*! An array of value describing the response of the red channel. - */ - unsigned short* red; - /*! An array of value describing the response of the green channel. - */ - unsigned short* green; - /*! An array of value describing the response of the blue channel. - */ - unsigned short* blue; - /*! The number of elements in each array. - */ - unsigned int size; - } GLFWgammaramp; - - /*! @brief Image data. - * - * This describes a single 2D image. See the documentation for each related - * function what the expected pixel format is. - * - * @sa @ref cursor_custom - * @sa @ref window_icon - * - * @since Added in version 2.1. - * @glfw3 Removed format and bytes-per-pixel members. - * - * @ingroup window - */ - typedef struct GLFWimage - { - /*! The width, in pixels, of this image. - */ - int width; - /*! The height, in pixels, of this image. - */ - int height; - /*! The pixel data of this image, arranged left-to-right, top-to-bottom. - */ - unsigned char* pixels; - } GLFWimage; - - /*! @brief Gamepad input state - * - * This describes the input state of a gamepad. - * - * @sa @ref gamepad - * @sa @ref glfwGetGamepadState - * - * @since Added in version 3.3. - * - * @ingroup input - */ - typedef struct GLFWgamepadstate - { - /*! The states of each [gamepad button](@ref gamepad_buttons), `GLFW_PRESS` - * or `GLFW_RELEASE`. - */ - unsigned char buttons[15]; - /*! The states of each [gamepad axis](@ref gamepad_axes), in the range -1.0 - * to 1.0 inclusive. - */ - float axes[6]; - } GLFWgamepadstate; - - /*! @brief - * - * @sa @ref init_allocator - * @sa @ref glfwInitAllocator - * - * @since Added in version 3.4. - * - * @ingroup init - */ - typedef struct GLFWallocator - { - GLFWallocatefun allocate; - GLFWreallocatefun reallocate; - GLFWdeallocatefun deallocate; - void* user; - } GLFWallocator; - - - /************************************************************************* - * GLFW API functions - *************************************************************************/ - - /*! @brief Initializes the GLFW library. - * - * This function initializes the GLFW library. Before most GLFW functions can - * be used, GLFW must be initialized, and before an application terminates GLFW - * should be terminated in order to free any resources allocated during or - * after initialization. - * - * If this function fails, it calls @ref glfwTerminate before returning. If it - * succeeds, you should call @ref glfwTerminate before the application exits. - * - * Additional calls to this function after successful initialization but before - * termination will return `GLFW_TRUE` immediately. - * - * The @ref GLFW_PLATFORM init hint controls which platforms are considered during - * initialization. This also depends on which platforms the library was compiled to - * support. - * - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_PLATFORM_UNAVAILABLE and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @macos This function will change the current directory of the - * application to the `Contents/Resources` subdirectory of the application's - * bundle, if present. This can be disabled with the @ref - * GLFW_COCOA_CHDIR_RESOURCES init hint. - * - * @remark @macos This function will create the main menu and dock icon for the - * application. If GLFW finds a `MainMenu.nib` it is loaded and assumed to - * contain a menu bar. Otherwise a minimal menu bar is created manually with - * common commands like Hide, Quit and About. The About entry opens a minimal - * about dialog with information from the application's bundle. The menu bar - * and dock icon can be disabled entirely with the @ref GLFW_COCOA_MENUBAR init - * hint. - * - * @remark @x11 This function will set the `LC_CTYPE` category of the - * application locale according to the current environment if that category is - * still "C". This is because the "C" locale breaks Unicode text input. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref intro_init - * @sa @ref glfwInitHint - * @sa @ref glfwInitAllocator - * @sa @ref glfwTerminate - * - * @since Added in version 1.0. - * - * @ingroup init - */ - SSCAPI int glfwInit(void); - - /*! @brief Terminates the GLFW library. - * - * This function destroys all remaining windows and cursors, restores any - * modified gamma ramps and frees any other allocated resources. Once this - * function is called, you must again call @ref glfwInit successfully before - * you will be able to use most GLFW functions. - * - * If GLFW has been successfully initialized, this function should be called - * before the application exits. If initialization fails, there is no need to - * call this function, as it is called by @ref glfwInit before it returns - * failure. - * - * This function has no effect if GLFW is not initialized. - * - * @errors Possible errors include @ref GLFW_PLATFORM_ERROR. - * - * @remark This function may be called before @ref glfwInit. - * - * @warning The contexts of any remaining windows must not be current on any - * other thread when this function is called. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref intro_init - * @sa @ref glfwInit - * - * @since Added in version 1.0. - * - * @ingroup init - */ - SSCAPI void glfwTerminate(void); - - /*! @brief Sets the specified init hint to the desired value. - * - * This function sets hints for the next initialization of GLFW. - * - * The values you set hints to are never reset by GLFW, but they only take - * effect during initialization. Once GLFW has been initialized, any values - * you set will be ignored until the library is terminated and initialized - * again. - * - * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will ignore them. - * Setting these hints requires no platform specific headers or functions. - * - * @param[in] hint The [init hint](@ref init_hints) to set. - * @param[in] value The new value of the init hint. - * - * @errors Possible errors include @ref GLFW_INVALID_ENUM and @ref - * GLFW_INVALID_VALUE. - * - * @remarks This function may be called before @ref glfwInit. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa init_hints - * @sa glfwInit - * - * @since Added in version 3.3. - * - * @ingroup init - */ - SSCAPI void glfwInitHint(int hint, int value); - - /*! @brief Sets the init allocator to the desired value. - * - * To use the default allocator, call this function with a `NULL` argument. - * - * If you specify an allocator struct, every member must be a valid function - * pointer. If any member is `NULL`, this function emits @ref - * GLFW_INVALID_VALUE and the init allocator is unchanged. - * - * @param[in] allocator The allocator to use at the next initialization, or - * `NULL` to use the default one. - * - * @errors Possible errors include @ref GLFW_INVALID_VALUE. - * - * @pointer_lifetime The specified allocator is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref init_allocator - * @sa @ref glfwInit - * - * @since Added in version 3.4. - * - * @ingroup init - */ - SSCAPI void glfwInitAllocator(const GLFWallocator* allocator); - -#if defined(VK_VERSION_1_0) - - /*! @brief Sets the desired Vulkan `vkGetInstanceProcAddr` function. - * - * This function sets the `vkGetInstanceProcAddr` function that GLFW will use for all - * Vulkan related entry point queries. - * - * This feature is mostly useful on macOS, if your copy of the Vulkan loader is in - * a location where GLFW cannot find it through dynamic loading, or if you are still - * using the static library version of the loader. - * - * If set to `NULL`, GLFW will try to load the Vulkan loader dynamically by its standard - * name and get this function from there. This is the default behavior. - * - * The standard name of the loader is `vulkan-1.dll` on Windows, `libvulkan.so.1` on - * Linux and other Unix-like systems and `libvulkan.1.dylib` on macOS. If your code is - * also loading it via these names then you probably don't need to use this function. - * - * The function address you set is never reset by GLFW, but it only takes effect during - * initialization. Once GLFW has been initialized, any updates will be ignored until the - * library is terminated and initialized again. - * - * @param[in] loader The address of the function to use, or `NULL`. - * - * @par Loader function signature - * @code - * PFN_vkVoidFunction vkGetInstanceProcAddr(VkInstance instance, const char* name) - * @endcode - * For more information about this function, see the - * [Vulkan Registry](https://www.khronos.org/registry/vulkan/). - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref vulkan_loader - * @sa @ref glfwInit - * - * @since Added in version 3.4. - * - * @ingroup init - */ - SSCAPI void glfwInitVulkanLoader(PFN_vkGetInstanceProcAddr loader); - -#endif /*VK_VERSION_1_0*/ - - /*! @brief Retrieves the version of the GLFW library. - * - * This function retrieves the major, minor and revision numbers of the GLFW - * library. It is intended for when you are using GLFW as a shared library and - * want to ensure that you are using the minimum required version. - * - * Any or all of the version arguments may be `NULL`. - * - * @param[out] major Where to store the major version number, or `NULL`. - * @param[out] minor Where to store the minor version number, or `NULL`. - * @param[out] rev Where to store the revision number, or `NULL`. - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref intro_version - * @sa @ref glfwGetVersionString - * - * @since Added in version 1.0. - * - * @ingroup init - */ - SSCAPI void glfwGetVersion(int* major, int* minor, int* rev); - - /*! @brief Returns a string describing the compile-time configuration. - * - * This function returns the compile-time generated - * [version string](@ref intro_version_string) of the GLFW library binary. It describes - * the version, platforms, compiler and any platform or operating system specific - * compile-time options. It should not be confused with the OpenGL or OpenGL ES version - * string, queried with `glGetString`. - * - * __Do not use the version string__ to parse the GLFW library version. The - * @ref glfwGetVersion function provides the version of the running library - * binary in numerical format. - * - * __Do not use the version string__ to parse what platforms are supported. The @ref - * glfwPlatformSupported function lets you query platform support. - * - * @return The ASCII encoded GLFW version string. - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @pointer_lifetime The returned string is static and compile-time generated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref intro_version - * @sa @ref glfwGetVersion - * - * @since Added in version 3.0. - * - * @ingroup init - */ - SSCAPI const char* glfwGetVersionString(void); - - /*! @brief Returns and clears the last error for the calling thread. - * - * This function returns and clears the [error code](@ref errors) of the last - * error that occurred on the calling thread, and optionally a UTF-8 encoded - * human-readable description of it. If no error has occurred since the last - * call, it returns @ref GLFW_NO_ERROR (zero) and the description pointer is - * set to `NULL`. - * - * @param[in] description Where to store the error description pointer, or `NULL`. - * @return The last error code for the calling thread, or @ref GLFW_NO_ERROR - * (zero). - * - * @errors None. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is guaranteed to be valid only until the - * next error occurs or the library is terminated. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref error_handling - * @sa @ref glfwSetErrorCallback - * - * @since Added in version 3.3. - * - * @ingroup init - */ - SSCAPI int glfwGetError(const char** description); - - /*! @brief Sets the error callback. - * - * This function sets the error callback, which is called with an error code - * and a human-readable description each time a GLFW error occurs. - * - * The error code is set before the callback is called. Calling @ref - * glfwGetError from the error callback will return the same value as the error - * code argument. - * - * The error callback is called on the thread where the error occurred. If you - * are using GLFW from multiple threads, your error callback needs to be - * written accordingly. - * - * Because the description string may have been generated specifically for that - * error, it is not guaranteed to be valid after the callback has returned. If - * you wish to use it after the callback returns, you need to make a copy. - * - * Once set, the error callback remains set even after the library has been - * terminated. - * - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set. - * - * @callback_signature - * @code - * void callback_name(int error_code, const char* description) - * @endcode - * For more information about the callback parameters, see the - * [callback pointer type](@ref GLFWerrorfun). - * - * @errors None. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref error_handling - * @sa @ref glfwGetError - * - * @since Added in version 3.0. - * - * @ingroup init - */ - SSCAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun callback); - - /*! @brief Returns the currently selected platform. - * - * This function returns the platform that was selected during initialization. The - * returned value will be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, - * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`. - * - * @return The currently selected platform, or zero if an error occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref platform - * @sa @ref glfwPlatformSupported - * - * @since Added in version 3.4. - * - * @ingroup init - */ - SSCAPI int glfwGetPlatform(void); - - /*! @brief Returns whether the library includes support for the specified platform. - * - * This function returns whether the library was compiled with support for the specified - * platform. The platform must be one of `GLFW_PLATFORM_WIN32`, `GLFW_PLATFORM_COCOA`, - * `GLFW_PLATFORM_WAYLAND`, `GLFW_PLATFORM_X11` or `GLFW_PLATFORM_NULL`. - * - * @param[in] platform The platform to query. - * @return `GLFW_TRUE` if the platform is supported, or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_INVALID_ENUM. - * - * @remark This function may be called before @ref glfwInit. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref platform - * @sa @ref glfwGetPlatform - * - * @since Added in version 3.4. - * - * @ingroup init - */ - SSCAPI int glfwPlatformSupported(int platform); - - /*! @brief Returns the currently connected monitors. - * - * This function returns an array of handles for all currently connected - * monitors. The primary monitor is always first in the returned array. If no - * monitors were found, this function returns `NULL`. - * - * @param[out] count Where to store the number of monitors in the returned - * array. This is set to zero if an error occurred. - * @return An array of monitor handles, or `NULL` if no monitors were found or - * if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is guaranteed to be valid only until the - * monitor configuration changes or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_monitors - * @sa @ref monitor_event - * @sa @ref glfwGetPrimaryMonitor - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI GLFWmonitor** glfwGetMonitors(int* count); - - /*! @brief Returns the primary monitor. - * - * This function returns the primary monitor. This is usually the monitor - * where elements like the task bar or global menu bar are located. - * - * @return The primary monitor, or `NULL` if no monitors were found or if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @remark The primary monitor is always first in the array returned by @ref - * glfwGetMonitors. - * - * @sa @ref monitor_monitors - * @sa @ref glfwGetMonitors - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI GLFWmonitor* glfwGetPrimaryMonitor(void); - - /*! @brief Returns the position of the monitor's viewport on the virtual screen. - * - * This function returns the position, in screen coordinates, of the upper-left - * corner of the specified monitor. - * - * Any or all of the position arguments may be `NULL`. If an error occurs, all - * non-`NULL` position arguments will be set to zero. - * - * @param[in] monitor The monitor to query. - * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. - * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_properties - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI void glfwGetMonitorPos(GLFWmonitor* monitor, int* xpos, int* ypos); - - /*! @brief Retrieves the work area of the monitor. - * - * This function returns the position, in screen coordinates, of the upper-left - * corner of the work area of the specified monitor along with the work area - * size in screen coordinates. The work area is defined as the area of the - * monitor not occluded by the window system task bar where present. If no - * task bar exists then the work area is the monitor resolution in screen - * coordinates. - * - * Any or all of the position and size arguments may be `NULL`. If an error - * occurs, all non-`NULL` position and size arguments will be set to zero. - * - * @param[in] monitor The monitor to query. - * @param[out] xpos Where to store the monitor x-coordinate, or `NULL`. - * @param[out] ypos Where to store the monitor y-coordinate, or `NULL`. - * @param[out] width Where to store the monitor width, or `NULL`. - * @param[out] height Where to store the monitor height, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_workarea - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ - SSCAPI void glfwGetMonitorWorkarea(GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height); - - /*! @brief Returns the physical size of the monitor. - * - * This function returns the size, in millimetres, of the display area of the - * specified monitor. - * - * Some platforms do not provide accurate monitor size information, either - * because the monitor - * [EDID](https://en.wikipedia.org/wiki/Extended_display_identification_data) - * data is incorrect or because the driver does not report it accurately. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] monitor The monitor to query. - * @param[out] widthMM Where to store the width, in millimetres, of the - * monitor's display area, or `NULL`. - * @param[out] heightMM Where to store the height, in millimetres, of the - * monitor's display area, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark @win32 On Windows 8 and earlier the physical size is calculated from - * the current resolution and system DPI instead of querying the monitor EDID data. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_properties - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI void glfwGetMonitorPhysicalSize(GLFWmonitor* monitor, int* widthMM, int* heightMM); - - /*! @brief Retrieves the content scale for the specified monitor. - * - * This function retrieves the content scale for the specified monitor. The - * content scale is the ratio between the current DPI and the platform's - * default DPI. This is especially important for text and any UI elements. If - * the pixel dimensions of your UI scaled by this look appropriate on your - * machine then it should appear at a reasonable size on other machines - * regardless of their DPI and scaling settings. This relies on the system DPI - * and scaling settings being somewhat correct. - * - * The content scale may depend on both the monitor resolution and pixel - * density and on user settings. It may be very different from the raw DPI - * calculated from the physical size and current resolution. - * - * @param[in] monitor The monitor to query. - * @param[out] xscale Where to store the x-axis content scale, or `NULL`. - * @param[out] yscale Where to store the y-axis content scale, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_scale - * @sa @ref glfwGetWindowContentScale - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ - SSCAPI void glfwGetMonitorContentScale(GLFWmonitor* monitor, float* xscale, float* yscale); - - /*! @brief Returns the name of the specified monitor. - * - * This function returns a human-readable name, encoded as UTF-8, of the - * specified monitor. The name typically reflects the make and model of the - * monitor and is not guaranteed to be unique among the connected monitors. - * - * @param[in] monitor The monitor to query. - * @return The UTF-8 encoded name of the monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified monitor is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_properties - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI const char* glfwGetMonitorName(GLFWmonitor* monitor); - - /*! @brief Sets the user pointer of the specified monitor. - * - * This function sets the user-defined pointer of the specified monitor. The - * current value is retained until the monitor is disconnected. The initial - * value is `NULL`. - * - * This function may be called from the monitor callback, even for a monitor - * that is being disconnected. - * - * @param[in] monitor The monitor whose pointer to set. - * @param[in] pointer The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref monitor_userptr - * @sa @ref glfwGetMonitorUserPointer - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ - SSCAPI void glfwSetMonitorUserPointer(GLFWmonitor* monitor, void* pointer); - - /*! @brief Returns the user pointer of the specified monitor. - * - * This function returns the current value of the user-defined pointer of the - * specified monitor. The initial value is `NULL`. - * - * This function may be called from the monitor callback, even for a monitor - * that is being disconnected. - * - * @param[in] monitor The monitor whose pointer to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref monitor_userptr - * @sa @ref glfwSetMonitorUserPointer - * - * @since Added in version 3.3. - * - * @ingroup monitor - */ - SSCAPI void* glfwGetMonitorUserPointer(GLFWmonitor* monitor); - - /*! @brief Sets the monitor configuration callback. - * - * This function sets the monitor configuration callback, or removes the - * currently set callback. This is called when a monitor is connected to or - * disconnected from the system. - * - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWmonitor* monitor, int event) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWmonitorfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_event - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI GLFWmonitorfun glfwSetMonitorCallback(GLFWmonitorfun callback); - - /*! @brief Returns the available video modes for the specified monitor. - * - * This function returns an array of all video modes supported by the specified - * monitor. The returned array is sorted in ascending order, first by color - * bit depth (the sum of all channel depths), then by resolution area (the - * product of width and height), then resolution width and finally by refresh - * rate. - * - * @param[in] monitor The monitor to query. - * @param[out] count Where to store the number of video modes in the returned - * array. This is set to zero if an error occurred. - * @return An array of video modes, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified monitor is - * disconnected, this function is called again for that monitor or the library - * is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_modes - * @sa @ref glfwGetVideoMode - * - * @since Added in version 1.0. - * @glfw3 Changed to return an array of modes for a specific monitor. - * - * @ingroup monitor - */ - SSCAPI const GLFWvidmode* glfwGetVideoModes(GLFWmonitor* monitor, int* count); - - /*! @brief Returns the current mode of the specified monitor. - * - * This function returns the current video mode of the specified monitor. If - * you have created a full screen window for that monitor, the return value - * will depend on whether that window is iconified. - * - * @param[in] monitor The monitor to query. - * @return The current mode of the monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified monitor is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_modes - * @sa @ref glfwGetVideoModes - * - * @since Added in version 3.0. Replaces `glfwGetDesktopMode`. - * - * @ingroup monitor - */ - SSCAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor); - - /*! @brief Generates a gamma ramp and sets it for the specified monitor. - * - * This function generates an appropriately sized gamma ramp from the specified - * exponent and then calls @ref glfwSetGammaRamp with it. The value must be - * a finite number greater than zero. - * - * The software controlled gamma ramp is applied _in addition_ to the hardware - * gamma correction, which today is usually 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. - * - * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref - * GLFW_SRGB_CAPABLE hint. - * - * @param[in] monitor The monitor whose gamma ramp to set. - * @param[in] gamma The desired exponent. - * - * @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. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_gamma - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma); - - /*! @brief Returns the current gamma ramp for the specified monitor. - * - * This function returns the current gamma ramp of the specified monitor. - * - * @param[in] monitor The monitor to query. - * @return The current gamma ramp, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @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 - * returning `NULL`. - * - * @pointer_lifetime The returned structure and its arrays are allocated and - * freed by GLFW. You should not free them yourself. They are valid until the - * specified monitor is disconnected, this function is called again for that - * monitor or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_gamma - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor); - - /*! @brief Sets the current gamma ramp for the specified monitor. - * - * This function sets the current gamma ramp for the specified monitor. The - * original gamma ramp for that monitor is saved by GLFW the first time this - * function is called and is restored by @ref glfwTerminate. - * - * The software controlled gamma ramp is applied _in addition_ to the hardware - * gamma correction, which today is usually 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. - * - * For gamma correct rendering with OpenGL or OpenGL ES, see the @ref - * GLFW_SRGB_CAPABLE hint. - * - * @param[in] monitor The monitor whose gamma ramp to set. - * @param[in] ramp The gamma ramp to use. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref GLFW_PLATFORM_ERROR - * and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @remark The size of the specified gamma ramp should match the size of the - * current ramp for that 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. - * - * @pointer_lifetime The specified gamma ramp is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref monitor_gamma - * - * @since Added in version 3.0. - * - * @ingroup monitor - */ - SSCAPI void glfwSetGammaRamp(GLFWmonitor* monitor, const GLFWgammaramp* ramp); - - /*! @brief Resets all window hints to their default values. - * - * This function resets all window hints to their - * [default values](@ref window_hints_values). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hints - * @sa @ref glfwWindowHint - * @sa @ref glfwWindowHintString - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwDefaultWindowHints(void); - - /*! @brief Sets the specified window hint to the desired value. - * - * This function sets hints for the next call to @ref glfwCreateWindow. The - * hints, once set, retain their values until changed by a call to this - * function or @ref glfwDefaultWindowHints, or until the library is terminated. - * - * Only integer value hints can be set with this function. String value hints - * are set with @ref glfwWindowHintString. - * - * This function does not check whether the specified hint values are valid. - * If you set hints to invalid values this will instead be reported by the next - * call to @ref glfwCreateWindow. - * - * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will ignore them. - * Setting these hints requires no platform specific headers or functions. - * - * @param[in] hint The [window hint](@ref window_hints) to set. - * @param[in] value The new value of the window hint. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hints - * @sa @ref glfwWindowHintString - * @sa @ref glfwDefaultWindowHints - * - * @since Added in version 3.0. Replaces `glfwOpenWindowHint`. - * - * @ingroup window - */ - SSCAPI void glfwWindowHint(int hint, int value); - - /*! @brief Sets the specified window hint to the desired value. - * - * This function sets hints for the next call to @ref glfwCreateWindow. The - * hints, once set, retain their values until changed by a call to this - * function or @ref glfwDefaultWindowHints, or until the library is terminated. - * - * Only string type hints can be set with this function. Integer value hints - * are set with @ref glfwWindowHint. - * - * This function does not check whether the specified hint values are valid. - * If you set hints to invalid values this will instead be reported by the next - * call to @ref glfwCreateWindow. - * - * Some hints are platform specific. These may be set on any platform but they - * will only affect their specific platform. Other platforms will ignore them. - * Setting these hints requires no platform specific headers or functions. - * - * @param[in] hint The [window hint](@ref window_hints) to set. - * @param[in] value The new value of the window hint. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @pointer_lifetime The specified string is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hints - * @sa @ref glfwWindowHint - * @sa @ref glfwDefaultWindowHints - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI void glfwWindowHintString(int hint, const char* value); - - /*! @brief Creates a window and its associated context. - * - * This function creates a window and its associated OpenGL or OpenGL ES - * context. Most of the options controlling how the window and its context - * should be created are specified with [window hints](@ref window_hints). - * - * Successful creation does not change which context is current. Before you - * can use the newly created context, you need to - * [make it current](@ref context_current). For information about the `share` - * parameter, see @ref context_sharing. - * - * The created window, framebuffer and context may differ from what you - * requested, as not all parameters and hints are - * [hard constraints](@ref window_hints_hard). This includes the size of the - * window, especially for full screen windows. To query the actual attributes - * of the created window, framebuffer and context, see @ref - * glfwGetWindowAttrib, @ref glfwGetWindowSize and @ref glfwGetFramebufferSize. - * - * To create a full screen window, you need to specify the monitor the window - * will cover. If no monitor is specified, the window will be windowed mode. - * Unless you have a way for the user to choose a specific monitor, it is - * recommended that you pick the primary monitor. For more information on how - * to query connected monitors, see @ref monitor_monitors. - * - * For full screen windows, the specified size becomes the resolution of the - * window's _desired video mode_. As long as a full screen window is not - * iconified, the supported video mode most closely matching the desired video - * mode is set for the specified monitor. For more information about full - * screen windows, including the creation of so called _windowed full screen_ - * or _borderless full screen_ windows, see @ref window_windowed_full_screen. - * - * Once you have created the window, you can switch it between windowed and - * full screen mode with @ref glfwSetWindowMonitor. This will not affect its - * OpenGL or OpenGL ES context. - * - * By default, newly created windows use the placement recommended by the - * window system. To create the window at a specific position, set the @ref - * GLFW_POSITION_X and @ref GLFW_POSITION_Y window hints before creation. To - * restore the default behavior, set either or both hints back to - * `GLFW_ANY_POSITION`. - * - * As long as at least one full screen window is not iconified, the screensaver - * is prohibited from starting. - * - * Window systems put limits on window sizes. Very large or very small window - * dimensions may be overridden by the window system on creation. Check the - * actual [size](@ref window_size) after creation. - * - * The [swap interval](@ref buffer_swap) is not set during window creation and - * the initial value may vary depending on driver settings and defaults. - * - * @param[in] width The desired width, in screen coordinates, of the window. - * This must be greater than zero. - * @param[in] height The desired height, in screen coordinates, of the window. - * This must be greater than zero. - * @param[in] title The initial, UTF-8 encoded window title. - * @param[in] monitor The monitor to use for full screen mode, or `NULL` for - * windowed mode. - * @param[in] share The window whose context to share resources with, or `NULL` - * to not share resources. - * @return The handle of the created window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_API_UNAVAILABLE, @ref - * GLFW_VERSION_UNAVAILABLE, @ref GLFW_FORMAT_UNAVAILABLE and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @win32 Window creation will fail if the Microsoft GDI software - * OpenGL implementation is the only one available. - * - * @remark @win32 If the executable has an icon resource named `GLFW_ICON,` it - * will be set as the initial icon for the window. If no such icon is present, - * the `IDI_APPLICATION` icon will be used instead. To set a different icon, - * see @ref glfwSetWindowIcon. - * - * @remark @win32 The context to share resources with must not be current on - * any other thread. - * - * @remark @macos The OS only supports core profile contexts for OpenGL - * versions 3.2 and later. Before creating an OpenGL context of version 3.2 or - * later you must set the [GLFW_OPENGL_PROFILE](@ref GLFW_OPENGL_PROFILE_hint) - * hint accordingly. OpenGL 3.0 and 3.1 contexts are not supported at all - * on macOS. - * - * @remark @macos The GLFW window has no icon, as it is not a document - * window, but the dock icon will be the same as the application bundle's icon. - * For more information on bundles, see the - * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) - * in the Mac Developer Library. - * - * @remark @macos On OS X 10.10 and later the window frame will not be rendered - * at full resolution on Retina displays unless the - * [GLFW_COCOA_RETINA_FRAMEBUFFER](@ref GLFW_COCOA_RETINA_FRAMEBUFFER_hint) - * hint is `GLFW_TRUE` and the `NSHighResolutionCapable` key is enabled in the - * application bundle's `Info.plist`. For more information, see - * [High Resolution Guidelines for OS X](https://developer.apple.com/library/mac/documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Explained/Explained.html) - * in the Mac Developer Library. The GLFW test and example programs use - * a custom `Info.plist` template for this, which can be found as - * `CMake/Info.plist.in` in the source tree. - * - * @remark @macos When activating frame autosaving with - * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified - * window size and position may be overridden by previously saved values. - * - * @remark @x11 Some window managers will not respect the placement of - * initially hidden windows. - * - * @remark @x11 Due to the asynchronous nature of X11, it may take a moment for - * a window to reach its requested state. This means you may not be able to - * query the final size, position or other attributes directly after window - * creation. - * - * @remark @x11 The class part of the `WM_CLASS` window property will by - * default be set to the window title passed to this function. The instance - * part will use the contents of the `RESOURCE_NAME` environment variable, if - * present and not empty, or fall back to the window title. Set the - * [GLFW_X11_CLASS_NAME](@ref GLFW_X11_CLASS_NAME_hint) and - * [GLFW_X11_INSTANCE_NAME](@ref GLFW_X11_INSTANCE_NAME_hint) window hints to - * override this. - * - * @remark @wayland Compositors should implement the xdg-decoration protocol - * for GLFW to decorate the window properly. If this protocol isn't - * supported, or if the compositor prefers client-side decorations, a very - * simple fallback frame will be drawn using the wp_viewporter protocol. A - * compositor can still emit close, maximize or fullscreen events, using for - * instance a keybind mechanism. If neither of these protocols is supported, - * the window won't be decorated. - * - * @remark @wayland A full screen window will not attempt to change the mode, - * no matter what the requested size or refresh rate. - * - * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol - * to be implemented in the user's compositor. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_creation - * @sa @ref glfwDestroyWindow - * - * @since Added in version 3.0. Replaces `glfwOpenWindow`. - * - * @ingroup window - */ - SSCAPI GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwindow* share); - - /*! @brief Destroys the specified window and its context. - * - * This function destroys the specified window and its context. On calling - * this function, no further callbacks will be called for that window. - * - * If the context of the specified window is current on the main thread, it is - * detached before being destroyed. - * - * @param[in] window The window to destroy. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @note The context of the specified window must not be current on any other - * thread when this function is called. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_creation - * @sa @ref glfwCreateWindow - * - * @since Added in version 3.0. Replaces `glfwCloseWindow`. - * - * @ingroup window - */ - SSCAPI void glfwDestroyWindow(GLFWwindow* window); - - /*! @brief Checks the close flag of the specified window. - * - * This function returns the value of the close flag of the specified window. - * - * @param[in] window The window to query. - * @return The value of the close flag. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_close - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI int glfwWindowShouldClose(GLFWwindow* window); - - /*! @brief Sets the close flag of the specified window. - * - * This function sets the value of the close flag of the specified window. - * This can be used to override the user's attempt to close the window, or - * to signal that it should be closed. - * - * @param[in] window The window whose flag to change. - * @param[in] value The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_close - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowShouldClose(GLFWwindow* window, int value); - - /*! @brief Sets the title of the specified window. - * - * This function sets the window title, encoded as UTF-8, of the specified - * window. - * - * @param[in] window The window whose title to change. - * @param[in] title The UTF-8 encoded window title. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @macos The window title will not be updated until the next time you - * process events. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_title - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowTitle(GLFWwindow* window, const char* title); - - /*! @brief Sets the icon for the specified window. - * - * This function sets the icon of the specified window. If passed an array of - * candidate images, those of or closest to the sizes desired by the system are - * selected. If no images are specified, the window reverts to its default - * icon. - * - * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight - * bits per channel with the red channel first. They are arranged canonically - * as packed sequential rows, starting from the top-left corner. - * - * The desired image sizes varies depending on platform and system settings. - * The selected images will be rescaled as needed. Good sizes include 16x16, - * 32x32 and 48x48. - * - * @param[in] window The window whose icon to set. - * @param[in] count The number of images in the specified array, or zero to - * revert to the default window icon. - * @param[in] images The images to create the icon from. This is ignored if - * count is zero. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref - * GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @pointer_lifetime The specified image data is copied before this function - * returns. - * - * @remark @macos Regular windows do not have icons on macOS. This function - * will emit @ref GLFW_FEATURE_UNAVAILABLE. The dock icon will be the same as - * the application bundle's icon. For more information on bundles, see the - * [Bundle Programming Guide](https://developer.apple.com/library/mac/documentation/CoreFoundation/Conceptual/CFBundles/) - * in the Mac Developer Library. - * - * @remark @wayland There is no existing protocol to change an icon, the - * window will thus inherit the one defined in the application's desktop file. - * This function will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_icon - * - * @since Added in version 3.2. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowIcon(GLFWwindow* window, int count, const GLFWimage* images); - - /*! @brief Retrieves the position of the content area of the specified window. - * - * This function retrieves the position, in screen coordinates, of the - * upper-left corner of the content area of the specified window. - * - * Any or all of the position arguments may be `NULL`. If an error occurs, all - * non-`NULL` position arguments will be set to zero. - * - * @param[in] window The window to query. - * @param[out] xpos Where to store the x-coordinate of the upper-left corner of - * the content area, or `NULL`. - * @param[out] ypos Where to store the y-coordinate of the upper-left corner of - * the content area, or `NULL`. - * - * @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 - * GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_pos - * @sa @ref glfwSetWindowPos - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwGetWindowPos(GLFWwindow* window, int* xpos, int* ypos); - - /*! @brief Sets the position of the content area of the specified window. - * - * This function sets the position, in screen coordinates, of the upper-left - * corner of the content area of the specified windowed mode window. If the - * window is a full screen window, this function does nothing. - * - * __Do not use this function__ to move an already visible window unless you - * have very good reasons for doing so, as it will confuse and annoy the user. - * - * The window manager may put limits on what positions are allowed. GLFW - * cannot and should not override these limits. - * - * @param[in] window The window to query. - * @param[in] xpos The x-coordinate of the upper-left corner of the content area. - * @param[in] ypos The y-coordinate of the upper-left corner of the content area. - * - * @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 - * GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_pos - * @sa @ref glfwGetWindowPos - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowPos(GLFWwindow* window, int xpos, int ypos); - - /*! @brief Retrieves the size of the content area of the specified window. - * - * This function retrieves the size, in screen coordinates, of the content area - * of the specified window. If you wish to retrieve the size of the - * framebuffer of the window in pixels, see @ref glfwGetFramebufferSize. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] window The window whose size to retrieve. - * @param[out] width Where to store the width, in screen coordinates, of the - * content area, or `NULL`. - * @param[out] height Where to store the height, in screen coordinates, of the - * content area, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * @sa @ref glfwSetWindowSize - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwGetWindowSize(GLFWwindow* window, int* width, int* height); - - /*! @brief Sets the size limits of the specified window. - * - * This function sets the size limits of the content area of the specified - * window. If the window is full screen, the size limits only take effect - * once it is made windowed. If the window is not resizable, this function - * does nothing. - * - * The size limits are applied immediately to a windowed mode window and may - * cause it to be resized. - * - * The maximum dimensions must be greater than or equal to the minimum - * dimensions and all must be greater than or equal to zero. - * - * @param[in] window The window to set limits for. - * @param[in] minwidth The minimum width, in screen coordinates, of the content - * area, or `GLFW_DONT_CARE`. - * @param[in] minheight The minimum height, in screen coordinates, of the - * content area, or `GLFW_DONT_CARE`. - * @param[in] maxwidth The maximum width, in screen coordinates, of the content - * area, or `GLFW_DONT_CARE`. - * @param[in] maxheight The maximum height, in screen coordinates, of the - * content area, or `GLFW_DONT_CARE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @remark If you set size limits and an aspect ratio that conflict, the - * results are undefined. - * - * @remark @wayland The size limits will not be applied until the window is - * actually resized, either by the user or by the compositor. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_sizelimits - * @sa @ref glfwSetWindowAspectRatio - * - * @since Added in version 3.2. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowSizeLimits(GLFWwindow* window, int minwidth, int minheight, int maxwidth, int maxheight); - - /*! @brief Sets the aspect ratio of the specified window. - * - * This function sets the required aspect ratio of the content area of the - * specified window. If the window is full screen, the aspect ratio only takes - * effect once it is made windowed. If the window is not resizable, this - * function does nothing. - * - * The aspect ratio is specified as a numerator and a denominator and both - * values must be greater than zero. For example, the common 16:9 aspect ratio - * is specified as 16 and 9, respectively. - * - * If the numerator and denominator is set to `GLFW_DONT_CARE` then the aspect - * ratio limit is disabled. - * - * The aspect ratio is applied immediately to a windowed mode window and may - * cause it to be resized. - * - * @param[in] window The window to set limits for. - * @param[in] numer The numerator of the desired aspect ratio, or - * `GLFW_DONT_CARE`. - * @param[in] denom The denominator of the desired aspect ratio, or - * `GLFW_DONT_CARE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @remark If you set size limits and an aspect ratio that conflict, the - * results are undefined. - * - * @remark @wayland The aspect ratio will not be applied until the window is - * actually resized, either by the user or by the compositor. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_sizelimits - * @sa @ref glfwSetWindowSizeLimits - * - * @since Added in version 3.2. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowAspectRatio(GLFWwindow* window, int numer, int denom); - - /*! @brief Sets the size of the content area of the specified window. - * - * This function sets the size, in screen coordinates, of the content area of - * the specified window. - * - * For full screen windows, this function updates the resolution of its desired - * video mode and switches to the video mode closest to it, without affecting - * the window's context. As the context is unaffected, the bit depths of the - * framebuffer remain unchanged. - * - * If you wish to update the refresh rate of the desired video mode in addition - * to its resolution, see @ref glfwSetWindowMonitor. - * - * The window manager may put limits on what sizes are allowed. GLFW cannot - * and should not override these limits. - * - * @param[in] window The window to resize. - * @param[in] width The desired width, in screen coordinates, of the window - * content area. - * @param[in] height The desired height, in screen coordinates, of the window - * content area. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland A full screen window will not attempt to change the mode, - * no matter what the requested size. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * @sa @ref glfwGetWindowSize - * @sa @ref glfwSetWindowMonitor - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowSize(GLFWwindow* window, int width, int height); - - /*! @brief Retrieves the size of the framebuffer of the specified window. - * - * This function retrieves the size, in pixels, of the framebuffer of the - * specified window. If you wish to retrieve the size of the window in screen - * coordinates, see @ref glfwGetWindowSize. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] window The window whose framebuffer to query. - * @param[out] width Where to store the width, in pixels, of the framebuffer, - * or `NULL`. - * @param[out] height Where to store the height, in pixels, of the framebuffer, - * or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_fbsize - * @sa @ref glfwSetFramebufferSizeCallback - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwGetFramebufferSize(GLFWwindow* window, int* width, int* height); - - /*! @brief Retrieves the size of the frame of the window. - * - * This function retrieves the size, in screen coordinates, of each edge of the - * frame of the specified window. This size includes the title bar, if the - * window has one. The size of the frame may vary depending on the - * [window-related hints](@ref window_hints_wnd) used to create it. - * - * Because this function retrieves the size of each window frame edge and not - * the offset along a particular coordinate axis, the retrieved values will - * always be zero or positive. - * - * Any or all of the size arguments may be `NULL`. If an error occurs, all - * non-`NULL` size arguments will be set to zero. - * - * @param[in] window The window whose frame size to query. - * @param[out] left Where to store the size, in screen coordinates, of the left - * edge of the window frame, or `NULL`. - * @param[out] top Where to store the size, in screen coordinates, of the top - * edge of the window frame, or `NULL`. - * @param[out] right Where to store the size, in screen coordinates, of the - * right edge of the window frame, or `NULL`. - * @param[out] bottom Where to store the size, in screen coordinates, of the - * bottom edge of the window frame, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * - * @since Added in version 3.1. - * - * @ingroup window - */ - SSCAPI void glfwGetWindowFrameSize(GLFWwindow* window, int* left, int* top, int* right, int* bottom); - - /*! @brief Retrieves the content scale for the specified window. - * - * This function retrieves the content scale for the specified window. The - * content scale is the ratio between the current DPI and the platform's - * default DPI. This is especially important for text and any UI elements. If - * the pixel dimensions of your UI scaled by this look appropriate on your - * machine then it should appear at a reasonable size on other machines - * regardless of their DPI and scaling settings. This relies on the system DPI - * and scaling settings being somewhat correct. - * - * On platforms where each monitors can have its own content scale, the window - * content scale will depend on which monitor the system considers the window - * to be on. - * - * @param[in] window The window to query. - * @param[out] xscale Where to store the x-axis content scale, or `NULL`. - * @param[out] yscale Where to store the y-axis content scale, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_scale - * @sa @ref glfwSetWindowContentScaleCallback - * @sa @ref glfwGetMonitorContentScale - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI void glfwGetWindowContentScale(GLFWwindow* window, float* xscale, float* yscale); - - /*! @brief Returns the opacity of the whole window. - * - * This function returns the opacity of the window, including any decorations. - * - * The opacity (or alpha) value is a positive finite number between zero and - * one, where zero is fully transparent and one is fully opaque. If the system - * does not support whole window transparency, this function always returns one. - * - * The initial opacity value for newly created windows is one. - * - * @param[in] window The window to query. - * @return The opacity value of the specified window. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_transparency - * @sa @ref glfwSetWindowOpacity - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI float glfwGetWindowOpacity(GLFWwindow* window); - - /*! @brief Sets the opacity of the whole window. - * - * This function sets the opacity of the window, including any decorations. - * - * The opacity (or alpha) value is a positive finite number between zero and - * one, where zero is fully transparent and one is fully opaque. - * - * The initial opacity value for newly created windows is one. - * - * A window created with framebuffer transparency may not use whole window - * transparency. The results of doing this are undefined. - * - * @param[in] window The window to set the opacity for. - * @param[in] opacity The desired opacity of the specified window. - * - * @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 to set an opacity factor for a window. - * This function will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_transparency - * @sa @ref glfwGetWindowOpacity - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowOpacity(GLFWwindow* window, float opacity); - - /*! @brief Iconifies the specified window. - * - * This function iconifies (minimizes) the specified window if it was - * previously restored. If the window is already iconified, this function does - * nothing. - * - * If the specified window is a full screen window, GLFW restores the original - * video mode of the monitor. The window's desired video mode is set again - * when the window is restored. - * - * @param[in] window The window to iconify. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland Once a window is iconified, @ref glfwRestoreWindow won’t - * 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 - * @sa @ref glfwRestoreWindow - * @sa @ref glfwMaximizeWindow - * - * @since Added in version 2.1. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwIconifyWindow(GLFWwindow* window); - - /*! @brief Restores the specified window. - * - * This function restores the specified window if it was previously iconified - * (minimized) or maximized. If the window is already restored, this function - * does nothing. - * - * If the specified window is an iconified full screen window, its desired - * video mode is set again for its monitor when the window is restored. - * - * @param[in] window The window to restore. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_iconify - * @sa @ref glfwIconifyWindow - * @sa @ref glfwMaximizeWindow - * - * @since Added in version 2.1. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwRestoreWindow(GLFWwindow* window); - - /*! @brief Maximizes the specified window. - * - * This function maximizes the specified window if it was previously not - * maximized. If the window is already maximized, this function does nothing. - * - * If the specified window is a full screen window, this function does nothing. - * - * @param[in] window The window to maximize. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @par Thread Safety - * This function may only be called from the main thread. - * - * @sa @ref window_iconify - * @sa @ref glfwIconifyWindow - * @sa @ref glfwRestoreWindow - * - * @since Added in GLFW 3.2. - * - * @ingroup window - */ - SSCAPI void glfwMaximizeWindow(GLFWwindow* window); - - /*! @brief Makes the specified window visible. - * - * This function makes the specified window visible if it was previously - * hidden. If the window is already visible or is in full screen mode, this - * function does nothing. - * - * By default, windowed mode windows are focused when shown - * Set the [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) window hint - * to change this behavior for all newly created windows, or change the - * behavior for an existing window with @ref glfwSetWindowAttrib. - * - * @param[in] window The window to make visible. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @wayland Because Wayland wants every frame of the desktop to be - * complete, this function does not immediately make the window visible. - * Instead it will become visible the next time the window framebuffer is - * updated after this call. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hide - * @sa @ref glfwHideWindow - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwShowWindow(GLFWwindow* window); - - /*! @brief Hides the specified window. - * - * This function hides the specified window if it was previously visible. If - * the window is already hidden or is in full screen mode, this function does - * nothing. - * - * @param[in] window The window to hide. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_hide - * @sa @ref glfwShowWindow - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwHideWindow(GLFWwindow* window); - - /*! @brief Brings the specified window to front and sets input focus. - * - * This function brings the specified window to front and sets input focus. - * The window should already be visible and not iconified. - * - * By default, both windowed and full screen mode windows are focused when - * initially created. Set the [GLFW_FOCUSED](@ref GLFW_FOCUSED_hint) to - * disable this behavior. - * - * Also by default, windowed mode windows are focused when shown - * with @ref glfwShowWindow. Set the - * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_hint) to disable this behavior. - * - * __Do not use this function__ to steal focus from other applications unless - * you are certain that is what the user wants. Focus stealing can be - * extremely disruptive. - * - * For a less disruptive way of getting the user's attention, see - * [attention requests](@ref window_attention). - * - * @param[in] window The window to give input focus. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @remark @wayland It is not possible for an application to set the input - * focus. This function will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_focus - * @sa @ref window_attention - * - * @since Added in version 3.2. - * - * @ingroup window - */ - SSCAPI void glfwFocusWindow(GLFWwindow* window); - - /*! @brief Requests user attention to the specified window. - * - * This function requests user attention to the specified window. On - * platforms where this is not supported, attention is requested to the - * application as a whole. - * - * Once the user has given attention, usually by focusing the window or - * application, the system will end the request automatically. - * - * @param[in] window The window to request attention to. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark @macos Attention is requested to the application as a whole, not the - * specific window. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_attention - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI void glfwRequestWindowAttention(GLFWwindow* window); - - /*! @brief Returns the monitor that the window uses for full screen mode. - * - * This function returns the handle of the monitor that the specified window is - * in full screen on. - * - * @param[in] window The window to query. - * @return The monitor, or `NULL` if the window is in windowed mode or an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_monitor - * @sa @ref glfwSetWindowMonitor - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI GLFWmonitor* glfwGetWindowMonitor(GLFWwindow* window); - - /*! @brief Sets the mode, monitor, video mode and placement of a window. - * - * This function sets the monitor that the window uses for full screen mode or, - * if the monitor is `NULL`, makes it windowed mode. - * - * When setting a monitor, this function updates the width, height and refresh - * rate of the desired video mode and switches to the video mode closest to it. - * The window position is ignored when setting a monitor. - * - * When the monitor is `NULL`, the position, width and height are used to - * place the window content area. The refresh rate is ignored when no monitor - * is specified. - * - * If you only wish to update the resolution of a full screen window or the - * size of a windowed mode window, see @ref glfwSetWindowSize. - * - * When a window transitions from full screen to windowed mode, this function - * restores any previous window settings such as whether it is decorated, - * floating, resizable, has size or aspect ratio limits, etc. - * - * @param[in] window The window whose monitor, size or video mode to set. - * @param[in] monitor The desired monitor, or `NULL` to set windowed mode. - * @param[in] xpos The desired x-coordinate of the upper-left corner of the - * content area. - * @param[in] ypos The desired y-coordinate of the upper-left corner of the - * content area. - * @param[in] width The desired with, in screen coordinates, of the content - * area or video mode. - * @param[in] height The desired height, in screen coordinates, of the content - * area or video mode. - * @param[in] refreshRate The desired refresh rate, in Hz, of the video mode, - * or `GLFW_DONT_CARE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark The OpenGL or OpenGL ES context will not be destroyed or otherwise - * 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 Setting the window to full screen will not attempt to - * change the mode, no matter what the requested size or refresh rate. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_monitor - * @sa @ref window_full_screen - * @sa @ref glfwGetWindowMonitor - * @sa @ref glfwSetWindowSize - * - * @since Added in version 3.2. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowMonitor(GLFWwindow* window, GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); - - /*! @brief Returns an attribute of the specified window. - * - * This function returns the value of an attribute of the specified window or - * its OpenGL or OpenGL ES context. - * - * @param[in] window The window to query. - * @param[in] attrib The [window attribute](@ref window_attribs) whose value to - * return. - * @return The value of the attribute, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @remark Framebuffer related hints are not window attributes. See @ref - * window_attribs_fb for more information. - * - * @remark Zero is a valid value for many window and context related - * attributes so you cannot use a return value of zero as an indication of - * 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`. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_attribs - * @sa @ref glfwSetWindowAttrib - * - * @since Added in version 3.0. Replaces `glfwGetWindowParam` and - * `glfwGetGLVersion`. - * - * @ingroup window - */ - SSCAPI int glfwGetWindowAttrib(GLFWwindow* window, int attrib); - - /*! @brief Sets an attribute of the specified window. - * - * This function sets the value of an attribute of the specified window. - * - * The supported attributes are [GLFW_DECORATED](@ref GLFW_DECORATED_attrib), - * [GLFW_RESIZABLE](@ref GLFW_RESIZABLE_attrib), - * [GLFW_FLOATING](@ref GLFW_FLOATING_attrib), - * [GLFW_AUTO_ICONIFY](@ref GLFW_AUTO_ICONIFY_attrib) and - * [GLFW_FOCUS_ON_SHOW](@ref GLFW_FOCUS_ON_SHOW_attrib). - * [GLFW_MOUSE_PASSTHROUGH](@ref GLFW_MOUSE_PASSTHROUGH_attrib) - * - * Some of these attributes are ignored for full screen windows. The new - * value will take effect if the window is later made windowed. - * - * Some of these attributes are ignored for windowed mode windows. The new - * value will take effect if the window is later made full screen. - * - * @param[in] window The window to set the attribute for. - * @param[in] attrib A supported window attribute. - * @param[in] value `GLFW_TRUE` or `GLFW_FALSE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_INVALID_VALUE, @ref GLFW_PLATFORM_ERROR and @ref - * GLFW_FEATURE_UNAVAILABLE. - * - * @remark Calling @ref glfwGetWindowAttrib will always return the latest - * value, even if that value is ignored by the current mode of the window. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_attribs - * @sa @ref glfwGetWindowAttrib - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowAttrib(GLFWwindow* window, int attrib, int value); - - /*! @brief Sets the user pointer of the specified window. - * - * This function sets the user-defined pointer of the specified window. The - * current value is retained until the window is destroyed. The initial value - * is `NULL`. - * - * @param[in] window The window whose pointer to set. - * @param[in] pointer The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_userptr - * @sa @ref glfwGetWindowUserPointer - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void glfwSetWindowUserPointer(GLFWwindow* window, void* pointer); - - /*! @brief Returns the user pointer of the specified window. - * - * This function returns the current value of the user-defined pointer of the - * specified window. The initial value is `NULL`. - * - * @param[in] window The window whose pointer to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref window_userptr - * @sa @ref glfwSetWindowUserPointer - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI void* glfwGetWindowUserPointer(GLFWwindow* window); - - /*! @brief Sets the position callback for the specified window. - * - * This function sets the position callback of the specified window, which is - * called when the window is moved. The callback is provided with the - * position, in screen coordinates, of the upper-left corner of the content - * area of the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int xpos, int ypos) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowposfun). - * - * @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. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_pos - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI GLFWwindowposfun glfwSetWindowPosCallback(GLFWwindow* window, GLFWwindowposfun callback); - - /*! @brief Sets the size callback for the specified window. - * - * This function sets the size callback of the specified window, which is - * called when the window is resized. The callback is provided with the size, - * in screen coordinates, of the content area of the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int width, int height) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowsizefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_size - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup window - */ - SSCAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwindowsizefun callback); - - /*! @brief Sets the close callback for the specified window. - * - * This function sets the close callback of the specified window, which is - * called when the user attempts to close the window, for example by clicking - * the close widget in the title bar. - * - * The close flag is set before this callback is called, but you can modify it - * at any time with @ref glfwSetWindowShouldClose. - * - * The close callback is not triggered by @ref glfwDestroyWindow. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowclosefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark @macos Selecting Quit from the application menu will trigger the - * close callback for all windows. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_close - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup window - */ - SSCAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback); - - /*! @brief Sets the refresh callback for the specified window. - * - * This function sets the refresh callback of the specified window, which is - * called when the content area of the window needs to be redrawn, for example - * if the window has been exposed after having been covered by another window. - * - * On compositing window systems such as Aero, Compiz, Aqua or Wayland, where - * the window contents are saved off-screen, this callback may be called only - * very infrequently or never at all. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window); - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowrefreshfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_refresh - * - * @since Added in version 2.5. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup window - */ - SSCAPI GLFWwindowrefreshfun glfwSetWindowRefreshCallback(GLFWwindow* window, GLFWwindowrefreshfun callback); - - /*! @brief Sets the focus callback for the specified window. - * - * This function sets the focus callback of the specified window, which is - * called when the window gains or loses input focus. - * - * After the focus callback is called for a window that lost input focus, - * synthetic key and mouse button release events will be generated for all such - * that had been pressed. For more information, see @ref glfwSetKeyCallback - * and @ref glfwSetMouseButtonCallback. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int focused) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowfocusfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_focus - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI GLFWwindowfocusfun glfwSetWindowFocusCallback(GLFWwindow* window, GLFWwindowfocusfun callback); - - /*! @brief Sets the iconify callback for the specified window. - * - * This function sets the iconification callback of the specified window, which - * is called when the window is iconified or restored. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int iconified) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowiconifyfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_iconify - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI GLFWwindowiconifyfun glfwSetWindowIconifyCallback(GLFWwindow* window, GLFWwindowiconifyfun callback); - - /*! @brief Sets the maximize callback for the specified window. - * - * This function sets the maximization callback of the specified window, which - * is called when the window is maximized or restored. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int maximized) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowmaximizefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_maximize - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI GLFWwindowmaximizefun glfwSetWindowMaximizeCallback(GLFWwindow* window, GLFWwindowmaximizefun callback); - - /*! @brief Sets the framebuffer resize callback for the specified window. - * - * This function sets the framebuffer resize callback of the specified window, - * which is called when the framebuffer of the specified window is resized. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int width, int height) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWframebuffersizefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_fbsize - * - * @since Added in version 3.0. - * - * @ingroup window - */ - SSCAPI GLFWframebuffersizefun glfwSetFramebufferSizeCallback(GLFWwindow* window, GLFWframebuffersizefun callback); - - /*! @brief Sets the window content scale callback for the specified window. - * - * This function sets the window content scale callback of the specified window, - * which is called when the content scale of the specified window changes. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, float xscale, float yscale) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWwindowcontentscalefun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref window_scale - * @sa @ref glfwGetWindowContentScale - * - * @since Added in version 3.3. - * - * @ingroup window - */ - SSCAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow* window, GLFWwindowcontentscalefun callback); - - /*! @brief Processes all pending events. - * - * This function processes only those events that are already in the event - * queue and then returns immediately. Processing events will cause the window - * and input callbacks associated with those events to be called. - * - * On some platforms, a window move, resize or menu operation will cause event - * processing to block. This is due to how event processing is designed on - * those platforms. You can use the - * [window refresh callback](@ref window_refresh) to redraw the contents of - * your window when necessary during such operations. - * - * Do not assume that callbacks you set will _only_ be called in response to - * event processing functions like this one. While it is necessary to poll for - * events, window systems that require GLFW to register callbacks of its own - * can pass events to GLFW in response to many window system function calls. - * GLFW will pass those events on to the application callbacks before - * returning. - * - * Event processing is not required for joystick input to work. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref events - * @sa @ref glfwWaitEvents - * @sa @ref glfwWaitEventsTimeout - * - * @since Added in version 1.0. - * - * @ingroup window - */ - SSCAPI void glfwPollEvents(void); - - /*! @brief Waits until events are queued and processes them. - * - * This function puts the calling thread to sleep until at least one event is - * available in the event queue. Once one or more events are available, - * it behaves exactly like @ref glfwPollEvents, i.e. the events in the queue - * are processed and the function then returns immediately. Processing events - * will cause the window and input callbacks associated with those events to be - * called. - * - * Since not all events are associated with callbacks, this function may return - * without a callback having been called even if you are monitoring all - * callbacks. - * - * On some platforms, a window move, resize or menu operation will cause event - * processing to block. This is due to how event processing is designed on - * those platforms. You can use the - * [window refresh callback](@ref window_refresh) to redraw the contents of - * your window when necessary during such operations. - * - * Do not assume that callbacks you set will _only_ be called in response to - * event processing functions like this one. While it is necessary to poll for - * events, window systems that require GLFW to register callbacks of its own - * can pass events to GLFW in response to many window system function calls. - * GLFW will pass those events on to the application callbacks before - * returning. - * - * Event processing is not required for joystick input to work. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref events - * @sa @ref glfwPollEvents - * @sa @ref glfwWaitEventsTimeout - * - * @since Added in version 2.5. - * - * @ingroup window - */ - SSCAPI void glfwWaitEvents(void); - - /*! @brief Waits with timeout until events are queued and processes them. - * - * This function puts the calling thread to sleep until at least one event is - * available in the event queue, or until the specified timeout is reached. If - * one or more events are available, it behaves exactly like @ref - * glfwPollEvents, i.e. the events in the queue are processed and the function - * then returns immediately. Processing events will cause the window and input - * callbacks associated with those events to be called. - * - * The timeout value must be a positive finite number. - * - * Since not all events are associated with callbacks, this function may return - * without a callback having been called even if you are monitoring all - * callbacks. - * - * On some platforms, a window move, resize or menu operation will cause event - * processing to block. This is due to how event processing is designed on - * those platforms. You can use the - * [window refresh callback](@ref window_refresh) to redraw the contents of - * your window when necessary during such operations. - * - * Do not assume that callbacks you set will _only_ be called in response to - * event processing functions like this one. While it is necessary to poll for - * events, window systems that require GLFW to register callbacks of its own - * can pass events to GLFW in response to many window system function calls. - * GLFW will pass those events on to the application callbacks before - * returning. - * - * Event processing is not required for joystick input to work. - * - * @param[in] timeout The maximum amount of time, in seconds, to wait. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref events - * @sa @ref glfwPollEvents - * @sa @ref glfwWaitEvents - * - * @since Added in version 3.2. - * - * @ingroup window - */ - SSCAPI void glfwWaitEventsTimeout(double timeout); - - /*! @brief Posts an empty event to the event queue. - * - * This function posts an empty event from the current thread to the event - * queue, causing @ref glfwWaitEvents or @ref glfwWaitEventsTimeout to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref events - * @sa @ref glfwWaitEvents - * @sa @ref glfwWaitEventsTimeout - * - * @since Added in version 3.1. - * - * @ingroup window - */ - SSCAPI void glfwPostEmptyEvent(void); - - /*! @brief Returns the value of an input option for the specified window. - * - * This function returns the value of an input option for the specified window. - * The mode must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_MOUSE_MOTION. - * - * @param[in] window The window to query. - * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or - * `GLFW_RAW_MOUSE_MOTION`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref glfwSetInputMode - * - * @since Added in version 3.0. - * - * @ingroup input - */ - SSCAPI int glfwGetInputMode(GLFWwindow* window, int mode); - - /*! @brief Sets an input option for the specified window. - * - * This function sets an input mode option for the specified window. The mode - * must be one of @ref GLFW_CURSOR, @ref GLFW_STICKY_KEYS, - * @ref GLFW_STICKY_MOUSE_BUTTONS, @ref GLFW_LOCK_KEY_MODS or - * @ref GLFW_RAW_MOUSE_MOTION. - * - * If the mode is `GLFW_CURSOR`, the value must be one of the following cursor - * modes: - * - `GLFW_CURSOR_NORMAL` makes the cursor visible and behaving normally. - * - `GLFW_CURSOR_HIDDEN` makes the cursor invisible when it is over the - * content area of the window but does not restrict the cursor from leaving. - * - `GLFW_CURSOR_DISABLED` hides and grabs the cursor, providing virtual - * and unlimited cursor movement. This is useful for implementing for - * example 3D camera controls. - * - `GLFW_CURSOR_CAPTURED` makes the cursor visible and confines it to the - * content area of the window. - * - * If the mode is `GLFW_STICKY_KEYS`, the value must be either `GLFW_TRUE` to - * enable sticky keys, or `GLFW_FALSE` to disable it. If sticky keys are - * enabled, a key press will ensure that @ref glfwGetKey returns `GLFW_PRESS` - * the next time it is called even if the key had been released before the - * call. This is useful when you are only interested in whether keys have been - * pressed but not when or in which order. - * - * If the mode is `GLFW_STICKY_MOUSE_BUTTONS`, the value must be either - * `GLFW_TRUE` to enable sticky mouse buttons, or `GLFW_FALSE` to disable it. - * If sticky mouse buttons are enabled, a mouse button press will ensure that - * @ref glfwGetMouseButton returns `GLFW_PRESS` the next time it is called even - * if the mouse button had been released before the call. This is useful when - * you are only interested in whether mouse buttons have been pressed but not - * when or in which order. - * - * If the mode is `GLFW_LOCK_KEY_MODS`, the value must be either `GLFW_TRUE` to - * enable lock key modifier bits, or `GLFW_FALSE` to disable them. If enabled, - * callbacks that receive modifier bits will also have the @ref - * GLFW_MOD_CAPS_LOCK bit set when the event was generated with Caps Lock on, - * and the @ref GLFW_MOD_NUM_LOCK bit when Num Lock was on. - * - * If the mode is `GLFW_RAW_MOUSE_MOTION`, the value must be either `GLFW_TRUE` - * to enable raw (unscaled and unaccelerated) mouse motion when the cursor is - * disabled, or `GLFW_FALSE` to disable it. If raw motion is not supported, - * attempting to set this will emit @ref GLFW_FEATURE_UNAVAILABLE. Call @ref - * glfwRawMouseMotionSupported to check for support. - * - * @param[in] window The window whose input mode to set. - * @param[in] mode One of `GLFW_CURSOR`, `GLFW_STICKY_KEYS`, - * `GLFW_STICKY_MOUSE_BUTTONS`, `GLFW_LOCK_KEY_MODS` or - * `GLFW_RAW_MOUSE_MOTION`. - * @param[in] value The new value of the specified input mode. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_PLATFORM_ERROR and @ref - * GLFW_FEATURE_UNAVAILABLE (see above). - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref glfwGetInputMode - * - * @since Added in version 3.0. Replaces `glfwEnable` and `glfwDisable`. - * - * @ingroup input - */ - SSCAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value); - - /*! @brief Returns whether raw mouse motion is supported. - * - * This function returns whether raw mouse motion is supported on the current - * system. This status does not change after GLFW has been initialized so you - * only need to check this once. If you attempt to enable raw motion on - * a system that does not support it, @ref GLFW_PLATFORM_ERROR will be emitted. - * - * Raw mouse motion is closer to the actual motion of the mouse across - * a surface. It is not affected by the scaling and acceleration applied to - * the motion of the desktop cursor. That processing is suitable for a cursor - * while raw motion is better for controlling for example a 3D camera. Because - * of this, raw mouse motion is only provided when the cursor is disabled. - * - * @return `GLFW_TRUE` if raw mouse motion is supported on the current machine, - * or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref raw_mouse_motion - * @sa @ref glfwSetInputMode - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI int glfwRawMouseMotionSupported(void); - - /*! @brief Returns the layout-specific name of the specified printable key. - * - * This function returns the name of the specified printable key, encoded as - * UTF-8. This is typically the character that key would produce without any - * modifier keys, intended for displaying key bindings to the user. For dead - * keys, it is typically the diacritic it would add to a character. - * - * __Do not use this function__ for [text input](@ref input_char). You will - * break text input for many languages even if it happens to work for yours. - * - * If the key is `GLFW_KEY_UNKNOWN`, the scancode is used to identify the key, - * otherwise the scancode is ignored. If you specify a non-printable key, or - * `GLFW_KEY_UNKNOWN` and a scancode that maps to a non-printable key, this - * function returns `NULL` but does not emit an error. - * - * This behavior allows you to always pass in the arguments in the - * [key callback](@ref input_key) without modification. - * - * The printable keys are: - * - `GLFW_KEY_APOSTROPHE` - * - `GLFW_KEY_COMMA` - * - `GLFW_KEY_MINUS` - * - `GLFW_KEY_PERIOD` - * - `GLFW_KEY_SLASH` - * - `GLFW_KEY_SEMICOLON` - * - `GLFW_KEY_EQUAL` - * - `GLFW_KEY_LEFT_BRACKET` - * - `GLFW_KEY_RIGHT_BRACKET` - * - `GLFW_KEY_BACKSLASH` - * - `GLFW_KEY_WORLD_1` - * - `GLFW_KEY_WORLD_2` - * - `GLFW_KEY_0` to `GLFW_KEY_9` - * - `GLFW_KEY_A` to `GLFW_KEY_Z` - * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` - * - `GLFW_KEY_KP_DECIMAL` - * - `GLFW_KEY_KP_DIVIDE` - * - `GLFW_KEY_KP_MULTIPLY` - * - `GLFW_KEY_KP_SUBTRACT` - * - `GLFW_KEY_KP_ADD` - * - `GLFW_KEY_KP_EQUAL` - * - * Names for printable keys depend on keyboard layout, while names for - * non-printable keys are the same across layouts but depend on the application - * language and should be localized along with other user interface text. - * - * @param[in] key The key to query, or `GLFW_KEY_UNKNOWN`. - * @param[in] scancode The scancode of the key to query. - * @return The UTF-8 encoded, layout-specific name of the key, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @remark The contents of the returned string may change when a keyboard - * layout change event is received. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_key_name - * - * @since Added in version 3.2. - * - * @ingroup input - */ - SSCAPI const char* glfwGetKeyName(int key, int scancode); - - /*! @brief Returns the platform-specific scancode of the specified key. - * - * This function returns the platform-specific scancode of the specified key. - * - * If the key is `GLFW_KEY_UNKNOWN` or does not exist on the keyboard this - * method will return `-1`. - * - * @param[in] key Any [named key](@ref keys). - * @return The platform-specific scancode for the key, or `-1` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref input_key - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI int glfwGetKeyScancode(int key); - - /*! @brief Returns the last reported state of a keyboard key for the specified - * window. - * - * This function returns the last state reported for the specified key to the - * specified window. The returned state is one of `GLFW_PRESS` or - * `GLFW_RELEASE`. The action `GLFW_REPEAT` is only reported to the key callback. - * - * If the @ref GLFW_STICKY_KEYS input mode is enabled, this function returns - * `GLFW_PRESS` the first time you call it for a key that was pressed, even if - * that key has already been released. - * - * The key functions deal with physical keys, with [key tokens](@ref keys) - * named after their use on the standard US keyboard layout. If you want to - * input text, use the Unicode character callback instead. - * - * The [modifier key bit masks](@ref mods) are not key tokens and cannot be - * used with this function. - * - * __Do not use this function__ to implement [text input](@ref input_char). - * - * @param[in] window The desired window. - * @param[in] key The desired [keyboard key](@ref keys). `GLFW_KEY_UNKNOWN` is - * not a valid key for this function. - * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_key - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ - SSCAPI int glfwGetKey(GLFWwindow* window, int key); - - /*! @brief Returns the last reported state of a mouse button for the specified - * window. - * - * This function returns the last state reported for the specified mouse button - * to the specified window. The returned state is one of `GLFW_PRESS` or - * `GLFW_RELEASE`. - * - * If the @ref GLFW_STICKY_MOUSE_BUTTONS input mode is enabled, this function - * returns `GLFW_PRESS` the first time you call it for a mouse button that was - * pressed, even if that mouse button has already been released. - * - * @param[in] window The desired window. - * @param[in] button The desired [mouse button](@ref buttons). - * @return One of `GLFW_PRESS` or `GLFW_RELEASE`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_mouse_button - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup input - */ - SSCAPI int glfwGetMouseButton(GLFWwindow* window, int button); - - /*! @brief Retrieves the position of the cursor relative to the content area of - * the window. - * - * This function returns the position of the cursor, in screen coordinates, - * relative to the upper-left corner of the content area of the specified - * window. - * - * If the cursor is disabled (with `GLFW_CURSOR_DISABLED`) then the cursor - * position is unbounded and limited only by the minimum and maximum values of - * a `double`. - * - * The coordinate can be converted to their integer equivalents with the - * `floor` function. Casting directly to an integer type works for positive - * coordinates, but fails for negative ones. - * - * Any or all of the position arguments may be `NULL`. If an error occurs, all - * non-`NULL` position arguments will be set to zero. - * - * @param[in] window The desired window. - * @param[out] xpos Where to store the cursor x-coordinate, relative to the - * left edge of the content area, or `NULL`. - * @param[out] ypos Where to store the cursor y-coordinate, relative to the to - * top edge of the content area, or `NULL`. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_pos - * @sa @ref glfwSetCursorPos - * - * @since Added in version 3.0. Replaces `glfwGetMousePos`. - * - * @ingroup input - */ - SSCAPI void glfwGetCursorPos(GLFWwindow* window, double* xpos, double* ypos); - - /*! @brief Sets the position of the cursor, relative to the content area of the - * window. - * - * This function sets the position, in screen coordinates, of the cursor - * relative to the upper-left corner of the content area of the specified - * window. The window must have input focus. If the window does not have - * input focus when this function is called, it fails silently. - * - * __Do not use this function__ to implement things like camera controls. GLFW - * already provides the `GLFW_CURSOR_DISABLED` cursor mode that hides the - * cursor, transparently re-centers it and provides unconstrained cursor - * motion. See @ref glfwSetInputMode for more information. - * - * If the cursor mode is `GLFW_CURSOR_DISABLED` then the cursor position is - * unconstrained and limited only by the minimum and maximum values of - * a `double`. - * - * @param[in] window The desired window. - * @param[in] xpos The desired x-coordinate, relative to the left edge of the - * content area. - * @param[in] ypos The desired y-coordinate, relative to the top edge of the - * content area. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_PLATFORM_ERROR and @ref GLFW_FEATURE_UNAVAILABLE (see remarks). - * - * @remark @wayland This function will only work when the cursor mode is - * `GLFW_CURSOR_DISABLED`, otherwise it will emit @ref GLFW_FEATURE_UNAVAILABLE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_pos - * @sa @ref glfwGetCursorPos - * - * @since Added in version 3.0. Replaces `glfwSetMousePos`. - * - * @ingroup input - */ - SSCAPI void glfwSetCursorPos(GLFWwindow* window, double xpos, double ypos); - - /*! @brief Creates a custom cursor. - * - * Creates a new custom cursor image that can be set for a window with @ref - * glfwSetCursor. The cursor can be destroyed with @ref glfwDestroyCursor. - * Any remaining cursors are destroyed by @ref glfwTerminate. - * - * The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight - * bits per channel with the red channel first. They are arranged canonically - * as packed sequential rows, starting from the top-left corner. - * - * The cursor hotspot is specified in pixels, relative to the upper-left corner - * of the cursor image. Like all other coordinate systems in GLFW, the X-axis - * points to the right and the Y-axis points down. - * - * @param[in] image The desired cursor image. - * @param[in] xhot The desired x-coordinate, in pixels, of the cursor hotspot. - * @param[in] yhot The desired y-coordinate, in pixels, of the cursor hotspot. - * @return The handle of the created cursor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The specified image data is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_object - * @sa @ref glfwDestroyCursor - * @sa @ref glfwCreateStandardCursor - * - * @since Added in version 3.1. - * - * @ingroup input - */ - SSCAPI GLFWcursor* glfwCreateCursor(const GLFWimage* image, int xhot, int yhot); - - /*! @brief Creates a cursor with a standard shape. - * - * Returns a cursor with a standard shape, that can be set for a window with - * @ref glfwSetCursor. The images for these cursors come from the system - * cursor theme and their exact appearance will vary between platforms. - * - * Most of these shapes are guaranteed to exist on every supported platform but - * a few may not be present. See the table below for details. - * - * Cursor shape | Windows | macOS | X11 | Wayland - * ------------------------------ | ------- | ----- | ------ | ------- - * @ref GLFW_ARROW_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_IBEAM_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_CROSSHAIR_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_POINTING_HAND_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_RESIZE_EW_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_RESIZE_NS_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_RESIZE_NWSE_CURSOR | Yes | Yes1 | Maybe2 | Maybe2 - * @ref GLFW_RESIZE_NESW_CURSOR | Yes | Yes1 | Maybe2 | Maybe2 - * @ref GLFW_RESIZE_ALL_CURSOR | Yes | Yes | Yes | Yes - * @ref GLFW_NOT_ALLOWED_CURSOR | Yes | Yes | Maybe2 | Maybe2 - * - * 1) This uses a private system API and may fail in the future. - * - * 2) This uses a newer standard that not all cursor themes support. - * - * If the requested shape is not available, this function emits a @ref - * GLFW_CURSOR_UNAVAILABLE error and returns `NULL`. - * - * @param[in] shape One of the [standard shapes](@ref shapes). - * @return A new cursor ready to use or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM, @ref GLFW_CURSOR_UNAVAILABLE and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_standard - * @sa @ref glfwCreateCursor - * - * @since Added in version 3.1. - * - * @ingroup input - */ - SSCAPI GLFWcursor* glfwCreateStandardCursor(int shape); - - /*! @brief Destroys a cursor. - * - * This function destroys a cursor previously created with @ref - * glfwCreateCursor. Any remaining cursors will be destroyed by @ref - * glfwTerminate. - * - * If the specified cursor is current for any window, that window will be - * reverted to the default cursor. This does not affect the cursor mode. - * - * @param[in] cursor The cursor object to destroy. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @reentrancy This function must not be called from a callback. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_object - * @sa @ref glfwCreateCursor - * - * @since Added in version 3.1. - * - * @ingroup input - */ - SSCAPI void glfwDestroyCursor(GLFWcursor* cursor); - - /*! @brief Sets the cursor for the window. - * - * This function sets the cursor image to be used when the cursor is over the - * content area of the specified window. The set cursor will only be visible - * when the [cursor mode](@ref cursor_mode) of the window is - * `GLFW_CURSOR_NORMAL`. - * - * On some platforms, the set cursor may not be visible unless the window also - * has input focus. - * - * @param[in] window The window to set the cursor for. - * @param[in] cursor The cursor to set, or `NULL` to switch back to the default - * arrow cursor. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_object - * - * @since Added in version 3.1. - * - * @ingroup input - */ - SSCAPI void glfwSetCursor(GLFWwindow* window, GLFWcursor* cursor); - - /*! @brief Sets the key callback. - * - * This function sets the key callback of the specified window, which is called - * when a key is pressed, repeated or released. - * - * The key functions deal with physical keys, with layout independent - * [key tokens](@ref keys) named after their values in the standard US keyboard - * layout. If you want to input text, use the - * [character callback](@ref glfwSetCharCallback) instead. - * - * When a window loses input focus, it will generate synthetic key release - * events for all pressed keys. You can tell these events from user-generated - * events by the fact that the synthetic ones are generated after the focus - * loss event has been processed, i.e. after the - * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. - * - * The scancode of a key is specific to that platform or sometimes even to that - * machine. Scancodes are intended to allow users to bind keys that don't have - * a GLFW key token. Such keys have `key` set to `GLFW_KEY_UNKNOWN`, their - * state is not saved and so it cannot be queried with @ref glfwGetKey. - * - * Sometimes GLFW needs to generate synthetic key events, in which case the - * scancode may be zero. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new key callback, or `NULL` to remove the currently - * set callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int key, int scancode, int action, int mods) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWkeyfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_key - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup input - */ - SSCAPI GLFWkeyfun glfwSetKeyCallback(GLFWwindow* window, GLFWkeyfun callback); - - /*! @brief Sets the Unicode character callback. - * - * This function sets the character callback of the specified window, which is - * called when a Unicode character is input. - * - * The character callback is intended for Unicode text input. As it deals with - * characters, it is keyboard layout dependent, whereas the - * [key callback](@ref glfwSetKeyCallback) is not. Characters do not map 1:1 - * to physical keys, as a key may produce zero, one or more characters. If you - * want to know whether a specific physical key was pressed or released, see - * the key callback instead. - * - * The character callback behaves as system text input normally does and will - * not be called if modifier keys are held down that would prevent normal text - * input on that platform, for example a Super (Command) key on macOS or Alt key - * on Windows. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcharfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_char - * - * @since Added in version 2.4. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup input - */ - SSCAPI GLFWcharfun glfwSetCharCallback(GLFWwindow* window, GLFWcharfun callback); - - /*! @brief Sets the Unicode character with modifiers callback. - * - * This function sets the character with modifiers callback of the specified - * window, which is called when a Unicode character is input regardless of what - * modifier keys are used. - * - * The character with modifiers callback is intended for implementing custom - * Unicode character input. For regular Unicode text input, see the - * [character callback](@ref glfwSetCharCallback). Like the character - * callback, the character with modifiers callback deals with characters and is - * keyboard layout dependent. Characters do not map 1:1 to physical keys, as - * a key may produce zero, one or more characters. If you want to know whether - * a specific physical key was pressed or released, see the - * [key callback](@ref glfwSetKeyCallback) instead. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or an - * [error](@ref error_handling) occurred. - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, unsigned int codepoint, int mods) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcharmodsfun). - * - * @deprecated Scheduled for removal in version 4.0. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_char - * - * @since Added in version 3.1. - * - * @ingroup input - */ - SSCAPI GLFWcharmodsfun glfwSetCharModsCallback(GLFWwindow* window, GLFWcharmodsfun callback); - - /*! @brief Sets the mouse button callback. - * - * This function sets the mouse button callback of the specified window, which - * is called when a mouse button is pressed or released. - * - * When a window loses input focus, it will generate synthetic mouse button - * release events for all pressed mouse buttons. You can tell these events - * from user-generated events by the fact that the synthetic ones are generated - * after the focus loss event has been processed, i.e. after the - * [window focus callback](@ref glfwSetWindowFocusCallback) has been called. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int button, int action, int mods) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWmousebuttonfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref input_mouse_button - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter and return value. - * - * @ingroup input - */ - SSCAPI GLFWmousebuttonfun glfwSetMouseButtonCallback(GLFWwindow* window, GLFWmousebuttonfun callback); - - /*! @brief Sets the cursor position callback. - * - * This function sets the cursor position callback of the specified window, - * which is called when the cursor is moved. The callback is provided with the - * position, in screen coordinates, relative to the upper-left corner of the - * content area of the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, double xpos, double ypos); - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcursorposfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_pos - * - * @since Added in version 3.0. Replaces `glfwSetMousePosCallback`. - * - * @ingroup input - */ - SSCAPI GLFWcursorposfun glfwSetCursorPosCallback(GLFWwindow* window, GLFWcursorposfun callback); - - /*! @brief Sets the cursor enter/leave callback. - * - * This function sets the cursor boundary crossing callback of the specified - * window, which is called when the cursor enters or leaves the content area of - * the window. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int entered) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWcursorenterfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref cursor_enter - * - * @since Added in version 3.0. - * - * @ingroup input - */ - SSCAPI GLFWcursorenterfun glfwSetCursorEnterCallback(GLFWwindow* window, GLFWcursorenterfun callback); - - /*! @brief Sets the scroll callback. - * - * This function sets the scroll callback of the specified window, which is - * called when a scrolling device is used, such as a mouse wheel or scrolling - * area of a touchpad. - * - * The scroll callback receives all scrolling input, like that from a mouse - * wheel or a touchpad scrolling area. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new scroll callback, or `NULL` to remove the - * currently set callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, double xoffset, double yoffset) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWscrollfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref scrolling - * - * @since Added in version 3.0. Replaces `glfwSetMouseWheelCallback`. - * - * @ingroup input - */ - SSCAPI GLFWscrollfun glfwSetScrollCallback(GLFWwindow* window, GLFWscrollfun callback); - - /*! @brief Sets the path drop callback. - * - * This function sets the path drop callback of the specified window, which is - * called when one or more dragged paths are dropped on the window. - * - * Because the path array and its strings may have been generated specifically - * for that event, they are not guaranteed to be valid after the callback has - * returned. If you wish to use them after the callback returns, you need to - * make a deep copy. - * - * @param[in] window The window whose callback to set. - * @param[in] callback The new file drop callback, or `NULL` to remove the - * currently set callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(GLFWwindow* window, int path_count, const char* paths[]) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWdropfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark @wayland File drop is currently unimplemented. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref path_drop - * - * @since Added in version 3.1. - * - * @ingroup input - */ - SSCAPI GLFWdropfun glfwSetDropCallback(GLFWwindow* window, GLFWdropfun callback); - - /*! @brief Returns whether the specified joystick is present. - * - * This function returns whether the specified joystick is present. - * - * There is no need to call this function before other functions that accept - * a joystick ID, as they all check for presence before performing any other - * work. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return `GLFW_TRUE` if the joystick is present, or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick - * - * @since Added in version 3.0. Replaces `glfwGetJoystickParam`. - * - * @ingroup input - */ - SSCAPI int glfwJoystickPresent(int jid); - - /*! @brief Returns the values of all axes of the specified joystick. - * - * This function returns the values of all axes of the specified joystick. - * Each element in the array is a value between -1.0 and 1.0. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] count Where to store the number of axis values in the returned - * array. This is set to zero if the joystick is not present or an error - * occurred. - * @return An array of axis values, or `NULL` if the joystick is not present or - * an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_axis - * - * @since Added in version 3.0. Replaces `glfwGetJoystickPos`. - * - * @ingroup input - */ - SSCAPI const float* glfwGetJoystickAxes(int jid, int* count); - - /*! @brief Returns the state of all buttons of the specified joystick. - * - * This function returns the state of all buttons of the specified joystick. - * Each element in the array is either `GLFW_PRESS` or `GLFW_RELEASE`. - * - * For backward compatibility with earlier versions that did not have @ref - * glfwGetJoystickHats, the button array also includes all hats, each - * represented as four buttons. The hats are in the same order as returned by - * __glfwGetJoystickHats__ and are in the order _up_, _right_, _down_ and - * _left_. To disable these extra buttons, set the @ref - * GLFW_JOYSTICK_HAT_BUTTONS init hint before initialization. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] count Where to store the number of button states in the returned - * array. This is set to zero if the joystick is not present or an error - * occurred. - * @return An array of button states, or `NULL` if the joystick is not present - * or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_button - * - * @since Added in version 2.2. - * @glfw3 Changed to return a dynamic array. - * - * @ingroup input - */ - SSCAPI const unsigned char* glfwGetJoystickButtons(int jid, int* count); - - /*! @brief Returns the state of all hats of the specified joystick. - * - * This function returns the state of all hats of the specified joystick. - * Each element in the array is one of the following values: - * - * Name | Value - * ---- | ----- - * `GLFW_HAT_CENTERED` | 0 - * `GLFW_HAT_UP` | 1 - * `GLFW_HAT_RIGHT` | 2 - * `GLFW_HAT_DOWN` | 4 - * `GLFW_HAT_LEFT` | 8 - * `GLFW_HAT_RIGHT_UP` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_UP` - * `GLFW_HAT_RIGHT_DOWN` | `GLFW_HAT_RIGHT` \| `GLFW_HAT_DOWN` - * `GLFW_HAT_LEFT_UP` | `GLFW_HAT_LEFT` \| `GLFW_HAT_UP` - * `GLFW_HAT_LEFT_DOWN` | `GLFW_HAT_LEFT` \| `GLFW_HAT_DOWN` - * - * The diagonal directions are bitwise combinations of the primary (up, right, - * down and left) directions and you can test for these individually by ANDing - * it with the corresponding direction. - * - * @code - * if (hats[2] & GLFW_HAT_RIGHT) - * { - * // State of hat 2 could be right-up, right or right-down - * } - * @endcode - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] count Where to store the number of hat states in the returned - * array. This is set to zero if the joystick is not present or an error - * occurred. - * @return An array of hat states, or `NULL` if the joystick is not present - * or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected, this function is called again for that joystick or the library - * is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_hat - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI const unsigned char* glfwGetJoystickHats(int jid, int* count); - - /*! @brief Returns the name of the specified joystick. - * - * This function returns the name, encoded as UTF-8, of the specified joystick. - * The returned string is allocated and freed by GLFW. You should not free it - * yourself. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return The UTF-8 encoded name of the joystick, or `NULL` if the joystick - * is not present or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_name - * - * @since Added in version 3.0. - * - * @ingroup input - */ - SSCAPI const char* glfwGetJoystickName(int jid); - - /*! @brief Returns the SDL compatible GUID of the specified joystick. - * - * This function returns the SDL compatible GUID, as a UTF-8 encoded - * hexadecimal string, of the specified joystick. The returned string is - * allocated and freed by GLFW. You should not free it yourself. - * - * The GUID is what connects a joystick to a gamepad mapping. A connected - * joystick will always have a GUID even if there is no gamepad mapping - * assigned to it. - * - * If the specified joystick is not present this function will return `NULL` - * but will not generate an error. This can be used instead of first calling - * @ref glfwJoystickPresent. - * - * The GUID uses the format introduced in SDL 2.0.5. This GUID tries to - * uniquely identify the make and model of a joystick but does not identify - * a specific unit, e.g. all wired Xbox 360 controllers will have the same - * GUID on that platform. The GUID for a unit may vary between platforms - * depending on what hardware information the platform specific APIs provide. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return The UTF-8 encoded GUID of the joystick, or `NULL` if the joystick - * is not present or an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_INVALID_ENUM and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI const char* glfwGetJoystickGUID(int jid); - - /*! @brief Sets the user pointer of the specified joystick. - * - * This function sets the user-defined pointer of the specified joystick. The - * current value is retained until the joystick is disconnected. The initial - * value is `NULL`. - * - * This function may be called from the joystick callback, even for a joystick - * that is being disconnected. - * - * @param[in] jid The joystick whose pointer to set. - * @param[in] pointer The new value. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref joystick_userptr - * @sa @ref glfwGetJoystickUserPointer - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI void glfwSetJoystickUserPointer(int jid, void* pointer); - - /*! @brief Returns the user pointer of the specified joystick. - * - * This function returns the current value of the user-defined pointer of the - * specified joystick. The initial value is `NULL`. - * - * This function may be called from the joystick callback, even for a joystick - * that is being disconnected. - * - * @param[in] jid The joystick whose pointer to return. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @sa @ref joystick_userptr - * @sa @ref glfwSetJoystickUserPointer - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI void* glfwGetJoystickUserPointer(int jid); - - /*! @brief Returns whether the specified joystick has a gamepad mapping. - * - * This function returns whether the specified joystick is both present and has - * a gamepad mapping. - * - * If the specified joystick is present but does not have a gamepad mapping - * this function will return `GLFW_FALSE` but will not generate an error. Call - * @ref glfwJoystickPresent to check if a joystick is present regardless of - * whether it has a mapping. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return `GLFW_TRUE` if a joystick is both present and has a gamepad mapping, - * or `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwGetGamepadState - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI int glfwJoystickIsGamepad(int jid); - - /*! @brief Sets the joystick configuration callback. - * - * This function sets the joystick configuration callback, or removes the - * currently set callback. This is called when a joystick is connected to or - * disconnected from the system. - * - * For joystick connection and disconnection events to be delivered on all - * platforms, you need to call one of the [event processing](@ref events) - * functions. Joystick disconnection may also be detected and the callback - * called by joystick functions. The function will then return whatever it - * returns if the joystick is not present. - * - * @param[in] callback The new callback, or `NULL` to remove the currently set - * callback. - * @return The previously set callback, or `NULL` if no callback was set or the - * library had not been [initialized](@ref intro_init). - * - * @callback_signature - * @code - * void function_name(int jid, int event) - * @endcode - * For more information about the callback parameters, see the - * [function pointer type](@ref GLFWjoystickfun). - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref joystick_event - * - * @since Added in version 3.2. - * - * @ingroup input - */ - SSCAPI GLFWjoystickfun glfwSetJoystickCallback(GLFWjoystickfun callback); - - /*! @brief Adds the specified SDL_GameControllerDB gamepad mappings. - * - * This function parses the specified ASCII encoded string and updates the - * internal list with any gamepad mappings it finds. This string may - * contain either a single gamepad mapping or many mappings separated by - * newlines. The parser supports the full format of the `gamecontrollerdb.txt` - * source file including empty lines and comments. - * - * See @ref gamepad_mapping for a description of the format. - * - * If there is already a gamepad mapping for a given GUID in the internal list, - * it will be replaced by the one passed to this function. If the library is - * terminated and re-initialized the internal list will revert to the built-in - * default. - * - * @param[in] string The string containing the gamepad mappings. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_VALUE. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwJoystickIsGamepad - * @sa @ref glfwGetGamepadName - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI int glfwUpdateGamepadMappings(const char* string); - - /*! @brief Returns the human-readable gamepad name for the specified joystick. - * - * This function returns the human-readable name of the gamepad from the - * gamepad mapping assigned to the specified joystick. - * - * If the specified joystick is not present or does not have a gamepad mapping - * this function will return `NULL` but will not generate an error. Call - * @ref glfwJoystickPresent to check whether it is present regardless of - * whether it has a mapping. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @return The UTF-8 encoded name of the gamepad, or `NULL` if the - * joystick is not present, does not have a mapping or an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref GLFW_INVALID_ENUM. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the specified joystick is - * disconnected, the gamepad mappings are updated or the library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwJoystickIsGamepad - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI const char* glfwGetGamepadName(int jid); - - /*! @brief Retrieves the state of the specified joystick remapped as a gamepad. - * - * This function retrieves the state of the specified joystick remapped to - * an Xbox-like gamepad. - * - * If the specified joystick is not present or does not have a gamepad mapping - * this function will return `GLFW_FALSE` but will not generate an error. Call - * @ref glfwJoystickPresent to check whether it is present regardless of - * whether it has a mapping. - * - * The Guide button may not be available for input as it is often hooked by the - * system or the Steam client. - * - * Not all devices have all the buttons or axes provided by @ref - * GLFWgamepadstate. Unavailable buttons and axes will always report - * `GLFW_RELEASE` and 0.0 respectively. - * - * @param[in] jid The [joystick](@ref joysticks) to query. - * @param[out] state The gamepad input state of the joystick. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if no joystick is - * connected, it has no gamepad mapping or an [error](@ref error_handling) - * occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_ENUM. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref gamepad - * @sa @ref glfwUpdateGamepadMappings - * @sa @ref glfwJoystickIsGamepad - * - * @since Added in version 3.3. - * - * @ingroup input - */ - SSCAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state); - - /*! @brief Sets the clipboard to the specified string. - * - * This function sets the system clipboard to the specified, UTF-8 encoded - * string. - * - * @param[in] window Deprecated. Any valid window or `NULL`. - * @param[in] string A UTF-8 encoded string. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The specified string is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa @ref glfwGetClipboardString - * - * @since Added in version 3.0. - * - * @ingroup input - */ - SSCAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); - - /*! @brief Returns the contents of the clipboard as a string. - * - * This function returns the contents of the system clipboard, if it contains - * or is convertible to a UTF-8 encoded string. If the clipboard is empty or - * if its contents cannot be converted, `NULL` is returned and a @ref - * GLFW_FORMAT_UNAVAILABLE error is generated. - * - * @param[in] window Deprecated. Any valid window or `NULL`. - * @return The contents of the clipboard as a UTF-8 encoded string, or `NULL` - * if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the next call to @ref - * glfwGetClipboardString or @ref glfwSetClipboardString, or until the library - * is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa @ref glfwSetClipboardString - * - * @since Added in version 3.0. - * - * @ingroup input - */ - SSCAPI const char* glfwGetClipboardString(GLFWwindow* window); - - /*! @brief Returns the GLFW time. - * - * This function returns the current GLFW time, in seconds. Unless the time - * has been set using @ref glfwSetTime it measures time elapsed since GLFW was - * initialized. - * - * This function and @ref glfwSetTime are helper functions on top of @ref - * glfwGetTimerFrequency and @ref glfwGetTimerValue. - * - * The resolution of the timer is system dependent, but is usually on the order - * of a few micro- or nanoseconds. It uses the highest-resolution monotonic - * time source on each operating system. - * - * @return The current time, in seconds, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Reading and - * writing of the internal base time is not atomic, so it needs to be - * externally synchronized with calls to @ref glfwSetTime. - * - * @sa @ref time - * - * @since Added in version 1.0. - * - * @ingroup input - */ - SSCAPI double glfwGetTime(void); - - /*! @brief Sets the GLFW time. - * - * This function sets the current GLFW time, in seconds. The value must be - * a positive finite number less than or equal to 18446744073.0, which is - * approximately 584.5 years. - * - * This function and @ref glfwGetTime are helper functions on top of @ref - * glfwGetTimerFrequency and @ref glfwGetTimerValue. - * - * @param[in] time The new value, in seconds. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_INVALID_VALUE. - * - * @remark The upper limit of GLFW time is calculated as - * floor((264 - 1) / 109) and is due to implementations - * storing nanoseconds in 64 bits. The limit may be increased in the future. - * - * @thread_safety This function may be called from any thread. Reading and - * writing of the internal base time is not atomic, so it needs to be - * externally synchronized with calls to @ref glfwGetTime. - * - * @sa @ref time - * - * @since Added in version 2.2. - * - * @ingroup input - */ - SSCAPI void glfwSetTime(double time); - - /*! @brief Returns the current value of the raw timer. - * - * This function returns the current value of the raw timer, measured in - * 1 / frequency seconds. To get the frequency, call @ref - * glfwGetTimerFrequency. - * - * @return The value of the timer, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref time - * @sa @ref glfwGetTimerFrequency - * - * @since Added in version 3.2. - * - * @ingroup input - */ - SSCAPI uint64_t glfwGetTimerValue(void); - - /*! @brief Returns the frequency, in Hz, of the raw timer. - * - * This function returns the frequency, in Hz, of the raw timer. - * - * @return The frequency of the timer, in Hz, or zero if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref time - * @sa @ref glfwGetTimerValue - * - * @since Added in version 3.2. - * - * @ingroup input - */ - SSCAPI uint64_t glfwGetTimerFrequency(void); - - /*! @brief Makes the context of the specified window current for the calling - * thread. - * - * This function makes the OpenGL or OpenGL ES context of the specified window - * current on the calling thread. A context must only be made current on - * a single thread at a time and each thread can have only a single current - * context at a time. - * - * When moving a context between threads, you must make it non-current on the - * old thread before making it current on the new one. - * - * By default, making a context non-current implicitly forces a pipeline flush. - * On machines that support `GL_KHR_context_flush_control`, you can control - * whether a context performs this flush by setting the - * [GLFW_CONTEXT_RELEASE_BEHAVIOR](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) - * hint. - * - * The specified window must have an OpenGL or OpenGL ES context. Specifying - * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT - * error. - * - * @param[in] window The window whose context to make current, or `NULL` to - * detach the current context. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_current - * @sa @ref glfwGetCurrentContext - * - * @since Added in version 3.0. - * - * @ingroup context - */ - SSCAPI void glfwMakeContextCurrent(GLFWwindow* window); - - /*! @brief Returns the window whose context is current on the calling thread. - * - * This function returns the window whose OpenGL or OpenGL ES context is - * current on the calling thread. - * - * @return The window whose context is current, or `NULL` if no window's - * context is current. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_current - * @sa @ref glfwMakeContextCurrent - * - * @since Added in version 3.0. - * - * @ingroup context - */ - SSCAPI GLFWwindow* glfwGetCurrentContext(void); - - /*! @brief Swaps the front and back buffers of the specified window. - * - * This function swaps the front and back buffers of the specified window when - * rendering with OpenGL or OpenGL ES. If the swap interval is greater than - * zero, the GPU driver waits the specified number of screen updates before - * swapping the buffers. - * - * The specified window must have an OpenGL or OpenGL ES context. Specifying - * a window without a context will generate a @ref GLFW_NO_WINDOW_CONTEXT - * error. - * - * This function does not apply to Vulkan. If you are rendering with Vulkan, - * see `vkQueuePresentKHR` instead. - * - * @param[in] window The window whose buffers to swap. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_WINDOW_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark __EGL:__ The context of the specified window must be current on the - * calling thread. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref buffer_swap - * @sa @ref glfwSwapInterval - * - * @since Added in version 1.0. - * @glfw3 Added window handle parameter. - * - * @ingroup window - */ - SSCAPI void glfwSwapBuffers(GLFWwindow* window); - - /*! @brief Sets the swap interval for the current context. - * - * This function sets the swap interval for the current OpenGL or OpenGL ES - * context, i.e. the number of screen updates to wait from the time @ref - * glfwSwapBuffers was called before swapping the buffers and returning. This - * is sometimes called _vertical synchronization_, _vertical retrace - * synchronization_ or just _vsync_. - * - * A context that supports either of the `WGL_EXT_swap_control_tear` and - * `GLX_EXT_swap_control_tear` extensions also accepts _negative_ swap - * intervals, which allows the driver to swap immediately even if a frame - * arrives a little bit late. You can check for these extensions with @ref - * glfwExtensionSupported. - * - * A context must be current on the calling thread. Calling this function - * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. - * - * This function does not apply to Vulkan. If you are rendering with Vulkan, - * see the present mode of your swapchain instead. - * - * @param[in] interval The minimum number of screen updates to wait for - * until the buffers are swapped by @ref glfwSwapBuffers. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark This function is not called during context creation, leaving the - * swap interval set to whatever is the default for that API. This is done - * because some swap interval extensions used by GLFW do not allow the swap - * interval to be reset to zero once it has been set to a non-zero value. - * - * @remark Some GPU drivers do not honor the requested swap interval, either - * because of a user setting that overrides the application's request or due to - * bugs in the driver. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref buffer_swap - * @sa @ref glfwSwapBuffers - * - * @since Added in version 1.0. - * - * @ingroup context - */ - SSCAPI void glfwSwapInterval(int interval); - - /*! @brief Returns whether the specified extension is available. - * - * This function returns whether the specified - * [API extension](@ref context_glext) is supported by the current OpenGL or - * OpenGL ES context. It searches both for client API extension and context - * creation API extensions. - * - * A context must be current on the calling thread. Calling this function - * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. - * - * As this functions retrieves and searches one or more extension strings each - * call, it is recommended that you cache its results if it is going to be used - * frequently. The extension strings will not change during the lifetime of - * a context, so there is no danger in doing this. - * - * This function does not apply to Vulkan. If you are using Vulkan, see @ref - * glfwGetRequiredInstanceExtensions, `vkEnumerateInstanceExtensionProperties` - * and `vkEnumerateDeviceExtensionProperties` instead. - * - * @param[in] extension The ASCII encoded name of the extension. - * @return `GLFW_TRUE` if the extension is available, or `GLFW_FALSE` - * otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_CURRENT_CONTEXT, @ref GLFW_INVALID_VALUE and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_glext - * @sa @ref glfwGetProcAddress - * - * @since Added in version 1.0. - * - * @ingroup context - */ - SSCAPI int glfwExtensionSupported(const char* extension); - - /*! @brief Returns the address of the specified function for the current - * context. - * - * This function returns the address of the specified OpenGL or OpenGL ES - * [core or extension function](@ref context_glext), if it is supported - * by the current context. - * - * A context must be current on the calling thread. Calling this function - * without a current context will cause a @ref GLFW_NO_CURRENT_CONTEXT error. - * - * This function does not apply to Vulkan. If you are rendering with Vulkan, - * see @ref glfwGetInstanceProcAddress, `vkGetInstanceProcAddr` and - * `vkGetDeviceProcAddr` instead. - * - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_NO_CURRENT_CONTEXT and @ref GLFW_PLATFORM_ERROR. - * - * @remark The address of a given function is not guaranteed to be the same - * between contexts. - * - * @remark This function may return a non-`NULL` address despite the - * associated version or extension not being available. Always check the - * context version or extension string first. - * - * @pointer_lifetime The returned function pointer is valid until the context - * is destroyed or the library is terminated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref context_glext - * @sa @ref glfwExtensionSupported - * - * @since Added in version 1.0. - * - * @ingroup context - */ - SSCAPI GLFWglproc glfwGetProcAddress(const char* procname); - - /*! @brief Returns whether the Vulkan loader and an ICD have been found. - * - * This function returns whether the Vulkan loader and any minimally functional - * ICD have been found. - * - * The availability of a Vulkan loader and even an ICD does not by itself guarantee that - * surface creation or even instance creation is possible. Call @ref - * glfwGetRequiredInstanceExtensions to check whether the extensions necessary for Vulkan - * surface creation are available and @ref glfwGetPhysicalDevicePresentationSupport to - * check whether a queue family of a physical device supports image presentation. - * - * @return `GLFW_TRUE` if Vulkan is minimally available, or `GLFW_FALSE` - * otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref vulkan_support - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ - SSCAPI int glfwVulkanSupported(void); - - /*! @brief Returns the Vulkan instance extensions required by GLFW. - * - * This function returns an array of names of Vulkan instance extensions required - * by GLFW for creating Vulkan surfaces for GLFW windows. If successful, the - * list will always contain `VK_KHR_surface`, so if you don't require any - * additional extensions you can pass this list directly to the - * `VkInstanceCreateInfo` struct. - * - * If Vulkan is not available on the machine, this function returns `NULL` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported - * to check whether Vulkan is at least minimally available. - * - * If Vulkan is available but no set of extensions allowing window surface - * creation was found, this function returns `NULL`. You may still use Vulkan - * for off-screen rendering and compute work. - * - * @param[out] count Where to store the number of extensions in the returned - * array. This is set to zero if an error occurred. - * @return An array of ASCII encoded extension names, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_API_UNAVAILABLE. - * - * @remark Additional extensions may be required by future versions of GLFW. - * You should check if any extensions you wish to enable are already in the - * returned array, as it is an error to specify an extension more than once in - * the `VkInstanceCreateInfo` struct. - * - * @pointer_lifetime The returned array is allocated and freed by GLFW. You - * should not free it yourself. It is guaranteed to be valid only until the - * library is terminated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref vulkan_ext - * @sa @ref glfwCreateWindowSurface - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ - SSCAPI const char** glfwGetRequiredInstanceExtensions(uint32_t* count); - -#if defined(VK_VERSION_1_0) - - /*! @brief Returns the address of the specified Vulkan instance function. - * - * This function returns the address of the specified Vulkan core or extension - * function for the specified instance. If instance is set to `NULL` it can - * return any function exported from the Vulkan loader, including at least the - * following functions: - * - * - `vkEnumerateInstanceExtensionProperties` - * - `vkEnumerateInstanceLayerProperties` - * - `vkCreateInstance` - * - `vkGetInstanceProcAddr` - * - * If Vulkan is not available on the machine, this function returns `NULL` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported - * to check whether Vulkan is at least minimally available. - * - * This function is equivalent to calling `vkGetInstanceProcAddr` with - * a platform-specific query of the Vulkan loader as a fallback. - * - * @param[in] instance The Vulkan instance to query, or `NULL` to retrieve - * functions related to instance creation. - * @param[in] procname The ASCII encoded name of the function. - * @return The address of the function, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_API_UNAVAILABLE. - * - * @pointer_lifetime The returned function pointer is valid until the library - * is terminated. - * - * @thread_safety This function may be called from any thread. - * - * @sa @ref vulkan_proc - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ - SSCAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance, const char* procname); - - /*! @brief Returns whether the specified queue family can present images. - * - * This function returns whether the specified queue family of the specified - * physical device supports presentation to the platform GLFW was built for. - * - * If Vulkan or the required window surface creation instance extensions are - * not available on the machine, or if the specified instance was not created - * with the required extensions, this function returns `GLFW_FALSE` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported - * to check whether Vulkan is at least minimally available and @ref - * glfwGetRequiredInstanceExtensions to check what instance extensions are - * required. - * - * @param[in] instance The instance that the physical device belongs to. - * @param[in] device The physical device that the queue family belongs to. - * @param[in] queuefamily The index of the queue family to query. - * @return `GLFW_TRUE` if the queue family supports presentation, or - * `GLFW_FALSE` otherwise. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_API_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. - * - * @remark @macos This function currently always returns `GLFW_TRUE`, as the - * `VK_MVK_macos_surface` and `VK_EXT_metal_surface` extensions do not provide - * a `vkGetPhysicalDevice*PresentationSupport` type function. - * - * @thread_safety This function may be called from any thread. For - * synchronization details of Vulkan objects, see the Vulkan specification. - * - * @sa @ref vulkan_present - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ - SSCAPI int glfwGetPhysicalDevicePresentationSupport(VkInstance instance, VkPhysicalDevice device, uint32_t queuefamily); - - /*! @brief Creates a Vulkan surface for the specified window. - * - * This function creates a Vulkan surface for the specified window. - * - * If the Vulkan loader or at least one minimally functional ICD were not found, - * this function returns `VK_ERROR_INITIALIZATION_FAILED` and generates a @ref - * GLFW_API_UNAVAILABLE error. Call @ref glfwVulkanSupported to check whether - * Vulkan is at least minimally available. - * - * If the required window surface creation instance extensions are not - * available or if the specified instance was not created with these extensions - * enabled, this function returns `VK_ERROR_EXTENSION_NOT_PRESENT` and - * generates a @ref GLFW_API_UNAVAILABLE error. Call @ref - * glfwGetRequiredInstanceExtensions to check what instance extensions are - * required. - * - * The window surface cannot be shared with another API so the window must - * have been created with the [client api hint](@ref GLFW_CLIENT_API_attrib) - * set to `GLFW_NO_API` otherwise it generates a @ref GLFW_INVALID_VALUE error - * and returns `VK_ERROR_NATIVE_WINDOW_IN_USE_KHR`. - * - * The window surface must be destroyed before the specified Vulkan instance. - * It is the responsibility of the caller to destroy the window surface. GLFW - * does not destroy it for you. Call `vkDestroySurfaceKHR` to destroy the - * surface. - * - * @param[in] instance The Vulkan instance to create the surface in. - * @param[in] window The window to create the surface for. - * @param[in] allocator The allocator to use, or `NULL` to use the default - * allocator. - * @param[out] surface Where to store the handle of the surface. This is set - * to `VK_NULL_HANDLE` if an error occurred. - * @return `VK_SUCCESS` if successful, or a Vulkan error code if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref - * GLFW_API_UNAVAILABLE, @ref GLFW_PLATFORM_ERROR and @ref GLFW_INVALID_VALUE - * - * @remark If an error occurs before the creation call is made, GLFW returns - * the Vulkan error code most appropriate for the error. Appropriate use of - * @ref glfwVulkanSupported and @ref glfwGetRequiredInstanceExtensions should - * eliminate almost all occurrences of these errors. - * - * @remark @macos GLFW prefers the `VK_EXT_metal_surface` extension, with the - * `VK_MVK_macos_surface` extension as a fallback. The name of the selected - * extension, if any, is included in the array returned by @ref - * glfwGetRequiredInstanceExtensions. - * - * @remark @macos This function creates and sets a `CAMetalLayer` instance for - * the window content view, which is required for MoltenVK to function. - * - * @remark @x11 By default GLFW prefers the `VK_KHR_xcb_surface` extension, - * with the `VK_KHR_xlib_surface` extension as a fallback. You can make - * `VK_KHR_xlib_surface` the preferred extension by setting the - * [GLFW_X11_XCB_VULKAN_SURFACE](@ref GLFW_X11_XCB_VULKAN_SURFACE_hint) init - * hint. The name of the selected extension, if any, is included in the array - * returned by @ref glfwGetRequiredInstanceExtensions. - * - * @thread_safety This function may be called from any thread. For - * synchronization details of Vulkan objects, see the Vulkan specification. - * - * @sa @ref vulkan_surface - * @sa @ref glfwGetRequiredInstanceExtensions - * - * @since Added in version 3.2. - * - * @ingroup vulkan - */ - SSCAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window, const VkAllocationCallbacks* allocator, VkSurfaceKHR* surface); - -#endif /*VK_VERSION_1_0*/ - - - /************************************************************************* - * Global definition cleanup - *************************************************************************/ - - /* ------------------- BEGIN SYSTEM/COMPILER SPECIFIC -------------------- */ - -#ifdef GLFW_WINGDIAPI_DEFINED -#undef WINGDIAPI -#undef GLFW_WINGDIAPI_DEFINED -#endif - -#ifdef GLFW_CALLBACK_DEFINED -#undef CALLBACK -#undef GLFW_CALLBACK_DEFINED -#endif - -/* Some OpenGL related headers need GLAPIENTRY, but it is unconditionally - * defined by some gl.h variants (OpenBSD) so define it after if needed. - */ -#ifndef GLAPIENTRY -#define GLAPIENTRY APIENTRY -#define GLFW_GLAPIENTRY_DEFINED -#endif - - /* -------------------- END SYSTEM/COMPILER SPECIFIC --------------------- */ - - -#ifdef __cplusplus -} -#endif - -#endif /* _glfw3_h_ */ - diff --git a/StgSharp.Native/sn-head/glfw3native.h b/StgSharp.Native/sn-head/glfw3native.h deleted file mode 100644 index a97c9840..00000000 --- a/StgSharp.Native/sn-head/glfw3native.h +++ /dev/null @@ -1,632 +0,0 @@ -/************************************************************************* - * GLFW 3.4 - www.glfw->org - * A library for OpenGL, window and input - *------------------------------------------------------------------------ - * Copyright (c) 2002-2006 Marcus Geelnard - * Copyright (c) 2006-2018 Camilla Löwy org> - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would - * be appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not - * be misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source - * distribution. - * - *************************************************************************/ - -#ifndef _glfw3_native_h_ -#define _glfw3_native_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -/************************************************************************* - * Doxygen documentation - *************************************************************************/ - -/*! @file glfw3native.h - * @brief The header of the native access functions. - * - * This is the header file of the native access functions. See @ref native for - * more information. - */ -/*! @defgroup native Native access - * @brief Functions related to accessing native handles. - * - * **By using the native access functions you assert that you know what you're - * doing and how to fix problems caused by using them. If you don't, you - * shouldn't be using them.** - * - * Before the inclusion of @ref glfw3native.h, you may define zero or more - * window system API macro and zero or more context creation API macros. - * - * The chosen backends must match those the library was compiled for. Failure - * to do this will cause a link-time error. - * - * The available window API macros are: - * * `GLFW_EXPOSE_NATIVE_WIN32` - * * `GLFW_EXPOSE_NATIVE_COCOA` - * * `GLFW_EXPOSE_NATIVE_X11` - * * `GLFW_EXPOSE_NATIVE_WAYLAND` - * - * The available context API macros are: - * * `GLFW_EXPOSE_NATIVE_WGL` - * * `GLFW_EXPOSE_NATIVE_NSGL` - * * `GLFW_EXPOSE_NATIVE_GLX` - * * `GLFW_EXPOSE_NATIVE_EGL` - * * `GLFW_EXPOSE_NATIVE_OSMESA` - * - * These macros select which of the native access functions that are declared - * and which platform-specific headers to include. It is then up your (by - * definition platform-specific) code to handle which of these should be - * defined. - * - * If you do not want the platform-specific headers to be included, define - * `GLFW_NATIVE_INCLUDE_NONE` before including the @ref glfw3native.h header. - * - * @code - * #define GLFW_EXPOSE_NATIVE_WIN32 - * #define GLFW_EXPOSE_NATIVE_WGL - * #define GLFW_NATIVE_INCLUDE_NONE - * #include - * @endcode - */ - -/************************************************************************* - * System headers and types - *************************************************************************/ - -#if !defined(GLFW_NATIVE_INCLUDE_NONE) - -#if defined(GLFW_EXPOSE_NATIVE_WIN32) || defined(GLFW_EXPOSE_NATIVE_WGL) -/* This is a workaround for the fact that glfw3.h needs to export APIENTRY (for - * example to allow applications to correctly declare a GL_KHR_debug callback) - * but windows.h assumes no one will define APIENTRY before it does - */ -#if defined(GLFW_APIENTRY_DEFINED) -#undef APIENTRY -#undef GLFW_APIENTRY_DEFINED -#endif -#include -#endif - -#if defined(GLFW_EXPOSE_NATIVE_COCOA) || defined(GLFW_EXPOSE_NATIVE_NSGL) -#if defined(__OBJC__) -#import -#else -#include -#include -#endif -#endif - -#if defined(GLFW_EXPOSE_NATIVE_X11) || defined(GLFW_EXPOSE_NATIVE_GLX) -#include -#include -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) -#include -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WGL) -/* WGL is declared by windows.h */ -#endif -#if defined(GLFW_EXPOSE_NATIVE_NSGL) -/* NSGL is declared by Cocoa.h */ -#endif -#if defined(GLFW_EXPOSE_NATIVE_GLX) -/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by - * default it also acts as an OpenGL header - * However, glx.h will include gl.h, which will define it unconditionally - */ -#if defined(GLFW_GLAPIENTRY_DEFINED) -#undef GLAPIENTRY -#undef GLFW_GLAPIENTRY_DEFINED -#endif -#include -#endif -#if defined(GLFW_EXPOSE_NATIVE_EGL) -#include -#endif -#if defined(GLFW_EXPOSE_NATIVE_OSMESA) -/* This is a workaround for the fact that glfw3.h defines GLAPIENTRY because by - * default it also acts as an OpenGL header - * However, osmesa.h will include gl.h, which will define it unconditionally - */ -#if defined(GLFW_GLAPIENTRY_DEFINED) -#undef GLAPIENTRY -#undef GLFW_GLAPIENTRY_DEFINED -#endif -#include -#endif - -#endif /*GLFW_NATIVE_INCLUDE_NONE*/ - -/************************************************************************* - * Functions - *************************************************************************/ - -#if defined(GLFW_EXPOSE_NATIVE_WIN32) -/*! @brief Returns the adapter device name of the specified monitor. - * - * @return The UTF-8 encoded adapter device name (for example `\\.\DISPLAY1`) - * of the specified monitor, or `NULL` if an [error](@ref error_handling) - * occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI const char *glfwGetWin32Adapter(GLFWmonitor *monitor); - -/*! @brief Returns the display device name of the specified monitor. - * - * @return The UTF-8 encoded display device name (for example - * `\\.\DISPLAY1\Monitor0`) of the specified monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI const char *glfwGetWin32Monitor(GLFWmonitor *monitor); - -/*! @brief Returns the `HWND` of the specified window. - * - * @return The `HWND` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark The `HDC` associated with the window can be queried with the - * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) - * function. - * @code - * HDC dc = GetDC(glfwGetWin32Window(window)); - * @endcode - * This DC is private and does not need to be released. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI HWND glfwGetWin32Window(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WGL) -/*! @brief Returns the `HGLRC` of the specified window. - * - * @return The `HGLRC` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @remark The `HDC` associated with the window can be queried with the - * [GetDC](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getdc) - * function. - * @code - * HDC dc = GetDC(glfwGetWin32Window(window)); - * @endcode - * This DC is private and does not need to be released. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI HGLRC glfwGetWGLContext(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_COCOA) -/*! @brief Returns the `CGDirectDisplayID` of the specified monitor. - * - * @return The `CGDirectDisplayID` of the specified monitor, or - * `kCGNullDirectDisplay` if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI CGDirectDisplayID glfwGetCocoaMonitor(GLFWmonitor *monitor); - -/*! @brief Returns the `NSWindow` of the specified window. - * - * @return The `NSWindow` of the specified window, or `nil` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI id glfwGetCocoaWindow(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_NSGL) -/*! @brief Returns the `NSOpenGLContext` of the specified window. - * - * @return The `NSOpenGLContext` of the specified window, or `nil` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI id glfwGetNSGLContext(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_X11) -/*! @brief Returns the `Display` used by GLFW. - * - * @return The `Display` used by GLFW, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI Display *glfwGetX11Display(void); - -/*! @brief Returns the `RRCrtc` of the specified monitor. - * - * @return The `RRCrtc` of the specified monitor, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI RRCrtc glfwGetX11Adapter(GLFWmonitor *monitor); - -/*! @brief Returns the `RROutput` of the specified monitor. - * - * @return The `RROutput` of the specified monitor, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.1. - * - * @ingroup native - */ -SSCAPI RROutput glfwGetX11Monitor(GLFWmonitor *monitor); - -/*! @brief Returns the `Window` of the specified window. - * - * @return The `Window` of the specified window, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI Window glfwGetX11Window(GLFWwindow *window); - -/*! @brief Sets the current primary selection to the specified string. - * - * @param[in] string A UTF-8 encoded string. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The specified string is copied before this function - * returns. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa glfwGetX11SelectionString - * @sa glfwSetClipboardString - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI void glfwSetX11SelectionString(const char *string); - -/*! @brief Returns the contents of the current primary selection as a string. - * - * If the selection is empty or if its contents cannot be converted, `NULL` - * is returned and a @ref GLFW_FORMAT_UNAVAILABLE error is generated. - * - * @return The contents of the selection as a UTF-8 encoded string, or `NULL` - * if an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @pointer_lifetime The returned string is allocated and freed by GLFW. You - * should not free it yourself. It is valid until the next call to @ref - * glfwGetX11SelectionString or @ref glfwSetX11SelectionString, or until the - * library is terminated. - * - * @thread_safety This function must only be called from the main thread. - * - * @sa @ref clipboard - * @sa glfwSetX11SelectionString - * @sa glfwGetClipboardString - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI const char *glfwGetX11SelectionString(void); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_GLX) -/*! @brief Returns the `GLXContext` of the specified window. - * - * @return The `GLXContext` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI GLXContext glfwGetGLXContext(GLFWwindow *window); - -/*! @brief Returns the `GLXWindow` of the specified window. - * - * @return The `GLXWindow` of the specified window, or `None` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI GLXWindow glfwGetGLXWindow(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_WAYLAND) -/*! @brief Returns the `struct wl_display*` used by GLFW. - * - * @return The `struct wl_display*` used by GLFW, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI struct wl_display *glfwGetWaylandDisplay(void); - -/*! @brief Returns the `struct wl_output*` of the specified monitor. - * - * @return The `struct wl_output*` of the specified monitor, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI struct wl_output *glfwGetWaylandMonitor(GLFWmonitor *monitor); - -/*! @brief Returns the main `struct wl_surface*` of the specified window. - * - * @return The main `struct wl_surface*` of the specified window, or `NULL` if - * an [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.2. - * - * @ingroup native - */ -SSCAPI struct wl_surface *glfwGetWaylandWindow(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_EGL) -/*! @brief Returns the `EGLDisplay` used by GLFW. - * - * @return The `EGLDisplay` used by GLFW, or `EGL_NO_DISPLAY` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED. - * - * @remark Because EGL is initialized on demand, this function will return - * `EGL_NO_DISPLAY` until the first context has been created via EGL. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI EGLDisplay glfwGetEGLDisplay(void); - -/*! @brief Returns the `EGLContext` of the specified window. - * - * @return The `EGLContext` of the specified window, or `EGL_NO_CONTEXT` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI EGLContext glfwGetEGLContext(GLFWwindow *window); - -/*! @brief Returns the `EGLSurface` of the specified window. - * - * @return The `EGLSurface` of the specified window, or `EGL_NO_SURFACE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.0. - * - * @ingroup native - */ -SSCAPI EGLSurface glfwGetEGLSurface(GLFWwindow *window); -#endif - -#if defined(GLFW_EXPOSE_NATIVE_OSMESA) -/*! @brief Retrieves the color buffer associated with the specified window. - * - * @param[in] window The window whose color buffer to retrieve. - * @param[out] width Where to store the width of the color buffer, or `NULL`. - * @param[out] height Where to store the height of the color buffer, or `NULL`. - * @param[out] format Where to store the OSMesa pixel format of the color - * buffer, or `NULL`. - * @param[out] buffer Where to store the address of the color buffer, or - * `NULL`. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI int glfwGetOSMesaColorBuffer(GLFWwindow *window, int *width, int *height, int *format, - void **buffer); - -/*! @brief Retrieves the depth buffer associated with the specified window. - * - * @param[in] window The window whose depth buffer to retrieve. - * @param[out] width Where to store the width of the depth buffer, or `NULL`. - * @param[out] height Where to store the height of the depth buffer, or `NULL`. - * @param[out] bytesPerValue Where to store the number of bytes per depth - * buffer element, or `NULL`. - * @param[out] buffer Where to store the address of the depth buffer, or - * `NULL`. - * @return `GLFW_TRUE` if successful, or `GLFW_FALSE` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI int glfwGetOSMesaDepthBuffer(GLFWwindow *window, int *width, int *height, int *bytesPerValue, - void **buffer); - -/*! @brief Returns the `OSMesaContext` of the specified window. - * - * @return The `OSMesaContext` of the specified window, or `NULL` if an - * [error](@ref error_handling) occurred. - * - * @errors Possible errors include @ref GLFW_NO_WINDOW_CONTEXT and @ref - * GLFW_NOT_INITIALIZED. - * - * @thread_safety This function may be called from any thread. Access is not - * synchronized. - * - * @since Added in version 3.3. - * - * @ingroup native - */ -SSCAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow *window); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _glfw3_native_h_ */ diff --git a/StgSharp.Native/sn-head/glfw_function.h b/StgSharp.Native/sn-head/glfw_function.h index edea6c83..ca17ae83 100644 --- a/StgSharp.Native/sn-head/glfw_function.h +++ b/StgSharp.Native/sn-head/glfw_function.h @@ -1,7 +1,7 @@ #ifndef GLFW_FUNCTION_TABLE_H #define GLFW_FUNCTION_TABLE_H -#include "../glfw/glfw3.h" +#include "../lib/glfw/glfw3.h" #ifdef __cplusplus extern "C" { @@ -142,4 +142,4 @@ typedef struct GLFWFunctionTable { } #endif -#endif \ No newline at end of file +#endif diff --git a/StgSharp.Native/sn-head/stb_image.h b/StgSharp.Native/sn-head/stb_image.h deleted file mode 100644 index ae870bf6..00000000 --- a/StgSharp.Native/sn-head/stb_image.h +++ /dev/null @@ -1,787 +0,0 @@ -/* stb_image - v2.28 - public domain image loader - http://nothings.org/stb - no warranty implied; use at your own risk - - Do this: - #define STB_IMAGE_IMPLEMENTATION - before you include this file in *one* C or C++ file to create the implementation. - - // i.e. it should look like this: - #include ... - #include ... - #include ... - #define STB_IMAGE_IMPLEMENTATION - #include "stb_image.h" - - You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. - And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free - - - QUICK NOTES: - Primarily of interest to game developers and other people who can - avoid problematic images and only need the trivial interface - - JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) - PNG 1/2/4/8/16-bit-per-channel - - TGA (not sure what subset, if a subset) - BMP non-1bpp, non-RLE - PSD (composited view only, no extra channels, 8/16 bit-per-channel) - - GIF (*comp always reports as 4-channel) - HDR (radiance rgbE format) - PIC (Softimage PIC) - PNM (PPM and PGM binary only) - - Animated GIF still needs a proper API, but here's one way to do it: - http://gist.github.com/urraka/685d9a6340b26b830d49 - - - decode from memory or through FILE (define STBI_NO_STDIO to remove code) - - decode from arbitrary I/O callbacks - - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) - - Full documentation under "DOCUMENTATION" below. - - -LICENSE - - See end of file for license information. - -RECENT REVISION HISTORY: - - 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff - 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes - 2.26 (2020-07-13) many minor fixes - 2.25 (2020-02-02) fix warnings - 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically - 2.23 (2019-08-11) fix clang static analysis warning - 2.22 (2019-03-04) gif fixes, fix warnings - 2.21 (2019-02-25) fix typo in comment - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs - 2.19 (2018-02-11) fix warning - 2.18 (2018-01-30) fix warnings - 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings - 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes - 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC - 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs - 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes - 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes - 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 - RGB-format JPEG; remove white matting in PSD; - allocate large structures on the stack; - correct channel count for PNG & BMP - 2.10 (2016-01-22) avoid warning introduced in 2.09 - 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED - - See end of file for full revision history. - - - ============================ Contributors ========================= - - Image formats Extensions, features - Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) - Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) - Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) - Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) - Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) - Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) - Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) - github:urraka (animated gif) Junggon Kim (PNM comments) - Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) - socks-the-fox (16-bit PNG) - Jeremy Sawicki (handle all ImageNet JPGs) - Optimizations & bugfixes Mikhail Morozov (1-bit BMP) - Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) - Arseny Kapoulkine Simon Breuss (16-bit PNM) - John-Mark Allen - Carmelo J Fdez-Aguera - - Bug & warning fixes - Marc LeBlanc David Woo Guillaume George Martins Mozeiko - Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski - Phil Jordan Dave Moore Roy Eltham - Hayaki Saito Nathan Reed Won Chun - Luke Graham Johan Duparc Nick Verigakis the Horde3D community - Thomas Ruf Ronny Chevalier github:rlyeh - Janez Zemva John Bartholomew Michal Cichon github:romigrou - Jonathan Blow Ken Hamada Tero Hanninen github:svdijk - Eugene Golushkov Laurent Gomila Cort Stratton github:snagar - Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex - Cass Everitt Ryamond Barbiero github:grim210 - Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw - Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus - Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo - Julian Raschke Gregory Mullen Christian Floisand github:darealshinji - Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 - Brad Weinberger Matvey Cherevko github:mosra - Luca Sas Alexander Veselov Zack Middleton [reserved] - Ryan C. Gordon [reserved] [reserved] - DO NOT ADD YOUR NAME HERE - - Jacko Dirks - - To add your name to the credits, pick a random blank space in the middle and fill it. - 80% of merge conflicts on stb PRs are due to people adding their name at the end - of the credits. -*/ - -#pragma once - -#ifndef STBI_INCLUDE_STB_IMAGE_H -#define STBI_INCLUDE_STB_IMAGE_H - -// DOCUMENTATION -// -// Limitations: -// - no 12-bit-per-channel JPEG -// - no JPEGs with arithmetic coding -// - GIF always returns *comp=4 -// -// Basic usage (see HDR discussion below for HDR usage): -// int x,y,n; -// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); -// // ... process data if not NULL ... -// // ... x = width, y = height, n = # 8-bit components per pixel ... -// // ... replace '0' with '1'..'4' to force that many components per pixel -// // ... but 'n' will always be the number that it would have been if you said 0 -// stbi_image_free(data); -// -// Standard parameters: -// int *x -- outputs image width in pixels -// int *y -- outputs image height in pixels -// int *channels_in_file -- outputs # of image components in image file -// int desired_channels -- if non-zero, # of image components requested in result -// -// The return value from an image loader is an 'unsigned char *' which points -// to the pixel data, or NULL on an allocation failure or if the image is -// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, -// with each pixel consisting of N interleaved 8-bit components; the first -// pixel pointed to is top-left-most in the image. There is no padding between -// image scanlines or between pixels, regardless of format. The number of -// components N is 'desired_channels' if desired_channels is non-zero, or -// *channels_in_file otherwise. If desired_channels is non-zero, -// *channels_in_file has the number of components that _would_ have been -// output otherwise. E.g. if you set desired_channels to 4, you will always -// get RGBA output, but you can check *channels_in_file to see if it's trivially -// opaque because e.g. there were only 3 channels in the source image. -// -// An output image with N components has the following components interleaved -// in this order in each pixel: -// -// N=#comp components -// 1 grey -// 2 grey, alpha -// 3 red, green, blue -// 4 red, green, blue, alpha -// -// If image loading fails for any reason, the return value will be NULL, -// and *x, *y, *channels_in_file will be unchanged. The function -// stbi_failure_reason() can be queried for an extremely brief, end-user -// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS -// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly -// more user-friendly ones. -// -// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. -// -// To query the width, height and component count of an image without having to -// decode the full file, you can use the stbi_info family of functions: -// -// int x,y,n,ok; -// ok = stbi_info(filename, &x, &y, &n); -// // returns ok=1 and sets x, y, n if image is a supported format, -// // 0 otherwise. -// -// Note that stb_image pervasively uses ints in its public API for sizes, -// including sizes of memory buffers. This is now part of the API and thus -// hard to change without causing breakage. As a result, the various image -// loaders all have certain limits on image size; these differ somewhat -// by format but generally boil down to either just under 2GB or just under -// 1GB. When the decoded image would be larger than this, stb_image decoding -// will fail. -// -// Additionally, stb_image will reject image files that have any of their -// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, -// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, -// the only way to have an image with such dimensions load correctly -// is for it to have a rather extreme aspect ratio. Either way, the -// assumption here is that such larger images are likely to be malformed -// or malicious. If you do need to load an image with individual dimensions -// larger than that, and it still fits in the overall size limit, you can -// #define STBI_MAX_DIMENSIONS on your own to be something larger. -// -// =========================================================================== -// -// UNICODE: -// -// If compiling for Windows and you wish to use Unicode filenames, compile -// with -// #define STBI_WINDOWS_UTF8 -// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert -// Windows wchar_t filenames to utf8. -// -// =========================================================================== -// -// Philosophy -// -// stb libraries are designed with the following priorities: -// -// 1. easy to use -// 2. easy to maintain -// 3. good performance -// -// Sometimes I let "good performance" creep up in priority over "easy to maintain", -// and for best performance I may provide less-easy-to-use APIs that give higher -// performance, in addition to the easy-to-use ones. Nevertheless, it's important -// to keep in mind that from the standpoint of you, a client of this library, -// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. -// -// Some secondary priorities arise directly from the first two, some of which -// provide more explicit reasons why performance can't be emphasized. -// -// - Portable ("ease of use") -// - Small source code footprint ("easy to maintain") -// - No dependencies ("ease of use") -// -// =========================================================================== -// -// I/O callbacks -// -// I/O callbacks allow you to read from arbitrary sources, like packaged -// files or some other source. Data read from callbacks are processed -// through a small internal buffer (currently 128 bytes) to try to reduce -// overhead. -// -// The three functions you must define are "read" (reads some bytes of data), -// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). -// -// =========================================================================== -// -// SIMD support -// -// The JPEG decoder will try to automatically use SIMD kernels on x86 when -// supported by the compiler. For ARM Neon support, you must explicitly -// request it. -// -// (The old do-it-yourself SIMD API is no longer supported in the current -// code.) -// -// On x86, SSE2 will automatically be used when available based on a run-time -// test; if not, the generic C versions are used as a fall-back. On ARM targets, -// the typical path is to have separate builds for NEON and non-NEON devices -// (at least this is true for iOS and Android). Therefore, the NEON support is -// toggled by a build flag: define STBI_NEON to get NEON loops. -// -// If for some reason you do not want to use any of SIMD code, or if -// you have issues compiling it, you can disable it entirely by -// defining STBI_NO_SIMD. -// -// =========================================================================== -// -// HDR image support (disable by defining STBI_NO_HDR) -// -// stb_image supports loading HDR images in general, and currently the Radiance -// .HDR file format specifically. You can still load any file through the existing -// interface; if you attempt to load an HDR file, it will be automatically remapped -// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; -// both of these constants can be reconfigured through this interface: -// -// stbi_hdr_to_ldr_gamma(2.2f); -// stbi_hdr_to_ldr_scale(1.0f); -// -// (note, do not use _inverse_ constants; stbi_image will invert them -// appropriately). -// -// Additionally, there is a new, parallel interface for loading files as -// (linear) floats to preserve the full dynamic range: -// -// float *data = stbi_loadf(filename, &x, &y, &n, 0); -// -// If you load LDR images through this interface, those images will -// be promoted to floating point values, run through the inverse of -// constants corresponding to the above: -// -// stbi_ldr_to_hdr_scale(1.0f); -// stbi_ldr_to_hdr_gamma(2.2f); -// -// Finally, given a filename (or an open file or memory block--see header -// file for details) containing image data, you can query for the "most -// appropriate" interface to use (that is, whether the image is HDR or -// not), using: -// -// stbi_is_hdr(char *filename); -// -// =========================================================================== -// -// iPhone PNG support: -// -// We optionally support converting iPhone-formatted PNGs (which store -// premultiplied BGRA) back to RGB, even though they're internally encoded -// differently. To enable this conversion, call -// stbi_convert_iphone_png_to_rgb(1). -// -// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per -// pixel to remove any premultiplied alpha *only* if the image file explicitly -// says there's premultiplied data (currently only happens in iPhone images, -// and only if iPhone convert-to-rgb processing is on). -// -// =========================================================================== -// -// ADDITIONAL CONFIGURATION -// -// - You can suppress implementation of any of the decoders to reduce -// your code footprint by #defining one or more of the following -// symbols before creating the implementation. -// -// STBI_NO_JPEG -// STBI_NO_PNG -// STBI_NO_BMP -// STBI_NO_PSD -// STBI_NO_TGA -// STBI_NO_GIF -// STBI_NO_HDR -// STBI_NO_PIC -// STBI_NO_PNM (.ppm and .pgm) -// -// - You can request *only* certain decoders and suppress all other ones -// (this will be more forward-compatible, as addition of new decoders -// doesn't require you to disable them explicitly): -// -// STBI_ONLY_JPEG -// STBI_ONLY_PNG -// STBI_ONLY_BMP -// STBI_ONLY_PSD -// STBI_ONLY_TGA -// STBI_ONLY_GIF -// STBI_ONLY_HDR -// STBI_ONLY_PIC -// STBI_ONLY_PNM (.ppm and .pgm) -// -// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still -// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB -// -// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater -// than that size (in either width or height) without further processing. -// This is to let programs in the wild set an upper bound to prevent -// denial-of-service attacks on untrusted data, as one could generate a -// valid image of gigantic dimensions and force stb_image to allocate a -// huge block of memory and spend disproportionate time decoding it. By -// default this is set to (1 << 24), which is 16777216, but that's still -// very big. - -#ifndef STBI_NO_STDIO -#include -#endif // STBI_NO_STDIO - -#define STBI_VERSION 1 - -enum { - STBI_default = 0, // only used for desired_channels - - STBI_grey = 1, - STBI_grey_alpha = 2, - STBI_rgb = 3, - STBI_rgb_alpha = 4 -}; - -#include -typedef unsigned char stbi_uc; -typedef unsigned short stbi_us; - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef STBIDEF -#ifdef STB_IMAGE_STATIC -#define STBIDEF static -#else -#define STBIDEF extern -#endif -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// PRIMARY API - works on images of any type -// - -// -// load image by filename, open file, or memory buffer -// - -typedef struct { - int (*read)( - void *user, char *data, - int size); // fill 'data' with 'size' bytes. return number of bytes actually read - void (*skip)(void *user, - int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative - int (*eof)(void *user); // returns nonzero if we are at end of file/data -} stbi_io_callbacks; - -//////////////////////////////////// -// -// 8-bits-per-channel interface -// - -STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, - int *channels_in_file, int desired_channels); -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, - int *channels_in_file, int desired_channels); - -#ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *channels_in_file, - int desired_channels); -STBIDEF void stbi_load_to_target(char const *filename, int *x, int *y, stbi_uc *target, - int *channels_in_file, int desired_channels); -STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *channels_in_file, - int desired_channels); -// for stbi_load_from_file, file pointer is left pointing immediately after image -#endif - -#ifndef STBI_NO_GIF -STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, - int *y, int *z, int *comp, int req_comp); -#endif - -#ifdef STBI_WINDOWS_UTF8 -STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t *input); -#endif - -//////////////////////////////////// -// -// 16-bits-per-channel interface -// - -STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, - int *channels_in_file, int desired_channels); -STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, - int *y, int *channels_in_file, int desired_channels); - -#ifndef STBI_NO_STDIO -STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *channels_in_file, - int desired_channels); -STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, - int desired_channels); -#endif - -//////////////////////////////////// -// -// float-per-channel interface -// -#ifndef STBI_NO_LINEAR -STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, - int *channels_in_file, int desired_channels); -STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, - int *channels_in_file, int desired_channels); - -#ifndef STBI_NO_STDIO -STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *channels_in_file, - int desired_channels); -STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *channels_in_file, - int desired_channels); -#endif -#endif - -#ifndef STBI_NO_HDR -STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); -STBIDEF void stbi_hdr_to_ldr_scale(float scale); -#endif // STBI_NO_HDR - -#ifndef STBI_NO_LINEAR -STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); -STBIDEF void stbi_ldr_to_hdr_scale(float scale); -#endif // STBI_NO_LINEAR - -// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR -STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); -STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); -#ifndef STBI_NO_STDIO -STBIDEF int stbi_is_hdr(char const *filename); -STBIDEF int stbi_is_hdr_from_file(FILE *f); -#endif // STBI_NO_STDIO - -// get a VERY brief reason for failure -// on most compilers (and ALL modern mainstream compilers) this is threadsafe -STBIDEF const char *stbi_failure_reason(void); - -// free the loaded image -- this is just free() -STBIDEF void stbi_image_free(void *retval_from_stbi_load); - -// get image dimensions & components without fully decoding -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, - int *comp); -STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); -STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp); -STBIDEF int stbi_is_16_bit(char const *filename); -STBIDEF int stbi_is_16_bit_from_file(FILE *f); -#endif - -// for image formats that explicitly notate that they have premultiplied alpha, -// we just return the colors as stored in the file. set this flag to force -// unpremultiplication. results are undefined if the unpremultiply overflow. -STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); - -// indicate whether we should process iphone images back to canonical format, -// or just pass them through "as-is" -STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); - -// flip the image vertically, so the first pixel in the output array is the bottom left -STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); - -// as above, but only applies to images loaded on the thread that calls the function -// this function is only available if your compiler supports thread-local variables; -// calling it will fail to link if your compiler doesn't -STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); -STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); -STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); - -// ZLIB client - used by PNG, available for other purposes - -STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, - int *outlen); -STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, - int initial_size, int *outlen, - int parse_header); -STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); -STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); - -STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); -STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, - int ilen); - -#ifdef __cplusplus -} -#endif - -// -// -//// end header file ///////////////////////////////////////////////////// -#endif // STBI_INCLUDE_STB_IMAGE_H - -/* - revision history: - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs - 2.19 (2018-02-11) fix warning - 2.18 (2018-01-30) fix warnings - 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug - 1-bit BMP - *_is_16_bit api - avoid warnings - 2.16 (2017-07-23) all functions have 16-bit variants; - STBI_NO_STDIO works again; - compilation fixes; - fix rounding in unpremultiply; - optimize vertical flip; - disable raw_len validation; - documentation fixes - 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; - warning fixes; disable run-time SSE detection on gcc; - uniform handling of optional "return" values; - thread-safe initialization of zlib tables - 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs - 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now - 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes - 2.11 (2016-04-02) allocate large structures on the stack - remove white matting for transparent PSD - fix reported channel count for PNG & BMP - re-enable SSE2 in non-gcc 64-bit - support RGB-formatted JPEG - read 16-bit PNGs (only as 8-bit) - 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED - 2.09 (2016-01-16) allow comments in PNM files - 16-bit-per-pixel TGA (not bit-per-component) - info() for TGA could break due to .hdr handling - info() for BMP to shares code instead of sloppy parse - can use STBI_REALLOC_SIZED if allocator doesn't support realloc - code cleanup - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) fix compiler warnings - partial animated GIF support - limited 16-bpc PSD support - #ifdef unused functions - bug with < 92 byte PIC,PNM,HDR,TGA - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) extra corruption checking (mmozeiko) - stbi_set_flip_vertically_on_load (nguillemot) - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) - progressive JPEG (stb) - PGM/PPM support (Ken Miller) - STBI_MALLOC,STBI_REALLOC,STBI_FREE - GIF bugfix -- seemingly never worked - STBI_NO_*, STBI_ONLY_* - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) - optimize PNG (ryg) - fix bug in interlaced PNG with user-specified channel count (stb) - 1.46 (2014-08-26) - fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG - 1.45 (2014-08-16) - fix MSVC-ARM internal compiler error by wrapping malloc - 1.44 (2014-08-07) - various warning fixes from Ronny Chevalier - 1.43 (2014-07-15) - fix MSVC-only compiler problem in code changed in 1.42 - 1.42 (2014-07-09) - don't define _CRT_SECURE_NO_WARNINGS (affects user code) - fixes to stbi__cleanup_jpeg path - added STBI_ASSERT to avoid requiring assert.h - 1.41 (2014-06-25) - fix search&replace from 1.36 that messed up comments/error messages - 1.40 (2014-06-22) - fix gcc struct-initialization warning - 1.39 (2014-06-15) - fix to TGA optimization when req_comp != number of components in TGA; - fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) - add support for BMP version 5 (more ignored fields) - 1.38 (2014-06-06) - suppress MSVC warnings on integer casts truncating values - fix accidental rename of 'skip' field of I/O - 1.37 (2014-06-04) - remove duplicate typedef - 1.36 (2014-06-03) - convert to header file single-file library - if de-iphone isn't set, load iphone images color-swapped instead of returning NULL - 1.35 (2014-05-27) - various warnings - fix broken STBI_SIMD path - fix bug where stbi_load_from_file no longer left file pointer in correct place - fix broken non-easy path for 32-bit BMP (possibly never used) - TGA optimization by Arseny Kapoulkine - 1.34 (unknown) - use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case - 1.33 (2011-07-14) - make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements - 1.32 (2011-07-13) - support for "info" function for all supported filetypes (SpartanJ) - 1.31 (2011-06-20) - a few more leak fixes, bug in PNG handling (SpartanJ) - 1.30 (2011-06-11) - added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) - removed deprecated format-specific test/load functions - removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway - error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) - fix inefficiency in decoding 32-bit BMP (David Woo) - 1.29 (2010-08-16) - various warning fixes from Aurelien Pocheville - 1.28 (2010-08-01) - fix bug in GIF palette transparency (SpartanJ) - 1.27 (2010-08-01) - cast-to-stbi_uc to fix warnings - 1.26 (2010-07-24) - fix bug in file buffering for PNG reported by SpartanJ - 1.25 (2010-07-17) - refix trans_data warning (Won Chun) - 1.24 (2010-07-12) - perf improvements reading from files on platforms with lock-heavy fgetc() - minor perf improvements for jpeg - deprecated type-specific functions so we'll get feedback if they're needed - attempt to fix trans_data warning (Won Chun) - 1.23 fixed bug in iPhone support - 1.22 (2010-07-10) - removed image *writing* support - stbi_info support from Jetro Lauha - GIF support from Jean-Marc Lienher - iPhone PNG-extensions from James Brown - warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) - 1.21 fix use of 'stbi_uc' in header (reported by jon blow) - 1.20 added support for Softimage PIC, by Tom Seddon - 1.19 bug in interlaced PNG corruption check (found by ryg) - 1.18 (2008-08-02) - fix a threading bug (local mutable static) - 1.17 support interlaced PNG - 1.16 major bugfix - stbi__convert_format converted one too many pixels - 1.15 initialize some fields for thread safety - 1.14 fix threadsafe conversion bug - header-file-only version (#define STBI_HEADER_FILE_ONLY before including) - 1.13 threadsafe - 1.12 const qualifiers in the API - 1.11 Support installable IDCT, colorspace conversion routines - 1.10 Fixes for 64-bit (don't use "unsigned long") - optimized upsampling by Fabian "ryg" Giesen - 1.09 Fix format-conversion for PSD code (bad global variables!) - 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz - 1.07 attempt to fix C++ warning/errors again - 1.06 attempt to fix C++ warning/errors again - 1.05 fix TGA loading to return correct *comp and use good luminance calc - 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free - 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR - 1.02 support for (subset of) HDR files, float interface for preferred access to them - 1.01 fix bug: possible bug in handling right-side up bmps... not sure - fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all - 1.00 interface to zlib that skips zlib header - 0.99 correct handling of alpha in palette - 0.98 TGA loader by lonesock; dynamically add loaders (untested) - 0.97 jpeg errors on too large a file; also catch another malloc failure - 0.96 fix detection of invalid v value - particleman@mollyrocket forum - 0.95 during header scan, seek to markers in case of padding - 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same - 0.93 handle jpegtran output; verbose errors - 0.92 read 4,8,16,24,32-bit BMP files of several formats - 0.91 output 24-bit Windows 3.0 BMP files - 0.90 fix a few more warnings; bump version number to approach 1.0 - 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd - 0.60 fix compiling as c++ - 0.59 fix warnings: merge Dave Moore's -Wall fixes - 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian - 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available - 0.56 fix bug: zlib uncompressed mode len vs. nlen - 0.55 fix bug: restart_interval not initialized to 0 - 0.54 allow NULL for 'int *comp' - 0.53 fix bug in png 3->4; speedup png decoding - 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments - 0.51 obey req_comp requests, 1-component jpegs return as 1-component, - on 'test' only check type, not whether we support this variant - 0.50 (2006-11-19) - first released version -*/ - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/ diff --git a/StgSharp.Native/k_bufop.c b/StgSharp.Native/sn-src/k_bufop.c similarity index 100% rename from StgSharp.Native/k_bufop.c rename to StgSharp.Native/sn-src/k_bufop.c diff --git a/StgSharp.Native/sn-src/sn_native.c b/StgSharp.Native/sn-src/sn_native.c index 4ee2b33d..8366c78f 100644 --- a/StgSharp.Native/sn-src/sn_native.c +++ b/StgSharp.Native/sn-src/sn_native.c @@ -1,6 +1,9 @@ -#include "StgSharpNative.h" +#ifndef STB_IMAGE_IMPLEMENTATION +#define STB_IMAGE_IMPLEMENTATION +#endif +#include "StgSharpNative.h" #include "gl.h" -#include "../glfw/glfw3.h" +#include "../lib/glfw/glfw3.h" #include #include @@ -32,7 +35,7 @@ SN_API GLFWglproc SN_DECL loadGlfuncDefault(char const *procName) void *ret = glfwGetProcAddress(procName); // printf("%llu\n", (uint64_t)ret); if (ret == NULL) { - strcpy_s(infolog,30, "Failed to load OpenGL api:"); + strcpy_s(infolog, 30, "Failed to load OpenGL api:"); for (size_t i = 0; i < sizeof(procName); i++) { infolog[30 + i] = procName[i]; } @@ -62,8 +65,7 @@ SN_API void SN_DECL loadImageData(char const *location, Image *out, imageLoader } out->pixelPtr = loader(location, &(out->width), &(out->height), &(out->channel), 0); } - -SN_API void SN_DECL unloadImageData(Image *restrict out) +SN_API void SN_DECL unloadImageData(Image *out) { free(out->pixelPtr); } diff --git a/StgSharp.Native/sn-src/stb_image.c b/StgSharp.Native/sn-src/stb_image.c deleted file mode 100644 index 3c2d25a2..00000000 --- a/StgSharp.Native/sn-src/stb_image.c +++ /dev/null @@ -1,8475 +0,0 @@ -#include "stb_image.h" - -#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) || \ - defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) || \ - defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) || \ - defined(STBI_ONLY_ZLIB) -#ifndef STBI_ONLY_JPEG -#define STBI_NO_JPEG -#endif -#ifndef STBI_ONLY_PNG -#define STBI_NO_PNG -#endif -#ifndef STBI_ONLY_BMP -#define STBI_NO_BMP -#endif -#ifndef STBI_ONLY_PSD -#define STBI_NO_PSD -#endif -#ifndef STBI_ONLY_TGA -#define STBI_NO_TGA -#endif -#ifndef STBI_ONLY_GIF -#define STBI_NO_GIF -#endif -#ifndef STBI_ONLY_HDR -#define STBI_NO_HDR -#endif -#ifndef STBI_ONLY_PIC -#define STBI_NO_PIC -#endif -#ifndef STBI_ONLY_PNM -#define STBI_NO_PNM -#endif -#endif - -#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) -#define STBI_NO_ZLIB -#endif - -#include -#include // ptrdiff_t on osx -#include -#include -#include - -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) -#include // ldexp, pow -#endif - -#ifndef STBI_NO_STDIO -#include -#endif - -#ifndef STBI_ASSERT -#include -#define STBI_ASSERT(x) assert(x) -#endif - -#ifdef __cplusplus -#define STBI_EXTERN extern "C" -#else -#define STBI_EXTERN extern -#endif - -#ifndef _MSC_VER -#ifdef __cplusplus -#define stbi_inline inline -#else -#define stbi_inline -#endif -#else -#define stbi_inline __forceinline -#endif - -#ifndef STBI_NO_THREAD_LOCALS -#if defined(__cplusplus) && __cplusplus >= 201103L -#define STBI_THREAD_LOCAL thread_local -#elif defined(__GNUC__) && __GNUC__ < 5 -#define STBI_THREAD_LOCAL __thread -#elif defined(_MSC_VER) -#define STBI_THREAD_LOCAL __declspec(thread) -#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) -#define STBI_THREAD_LOCAL _Thread_local -#endif - -#ifndef STBI_THREAD_LOCAL -#if defined(__GNUC__) -#define STBI_THREAD_LOCAL __thread -#endif -#endif -#endif - -#if defined(_MSC_VER) || defined(__SYMBIAN32__) -typedef unsigned short stbi__uint16; -typedef signed short stbi__int16; -typedef unsigned int stbi__uint32; -typedef signed int stbi__int32; -#else -#include -typedef uint16_t stbi__uint16; -typedef int16_t stbi__int16; -typedef uint32_t stbi__uint32; -typedef int32_t stbi__int32; -#endif - -// should produce compiler error if size is wrong -typedef unsigned char validate_uint32[sizeof(stbi__uint32) == 4 ? 1 : -1]; - -#ifdef _MSC_VER -#define STBI_NOTUSED(v) (void)(v) -#else -#define STBI_NOTUSED(v) (void)sizeof(v) -#endif - -#ifdef _MSC_VER -#define STBI_HAS_LROTL -#endif - -#ifdef STBI_HAS_LROTL -#define stbi_lrot(x, y) _lrotl(x, y) -#else -#define stbi_lrot(x, y) (((x) << (y)) | ((x) >> (-(y) & 31))) -#endif - -#if defined(STBI_MALLOC) && defined(STBI_FREE) && \ - (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) -// ok -#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && \ - !defined(STBI_REALLOC_SIZED) -// ok -#else -#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." -#endif - -#ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p, newsz) realloc(p, newsz) -#define STBI_FREE(p) free(p) -#endif - -#ifndef STBI_REALLOC_SIZED -#define STBI_REALLOC_SIZED(p, oldsz, newsz) STBI_REALLOC(p, newsz) -#endif - -// x86/x64 detection -#if defined(__x86_64__) || defined(_M_X64) -#define STBI__X64_TARGET -#elif defined(__i386) || defined(_M_IX86) -#define STBI__X86_TARGET -#endif - -#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) -// gcc doesn't support sse2 intrinsics unless you compile with -msse2, -// which in turn means it gets to use SSE2 everywhere. This is unfortunate, -// but previous attempts to provide the SSE2 functions with runtime -// detection caused numerous issues. The way architecture extensions are -// exposed in GCC/Clang is, sadly, not really suited for one-file libs. -// New behavior: if compiled with -msse2, we use SSE2 without any -// detection; if not, we don't use it at all. -#define STBI_NO_SIMD -#endif - -#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && \ - !defined(STBI_NO_SIMD) -// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET -// -// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the -// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. -// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not -// simultaneously enabling "-mstackrealign". -// -// See https://github.com/nothings/stb/issues/81 for more information. -// -// So default to no SSE2 on 32-bit MinGW. If you've read this far and added -// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. -#define STBI_NO_SIMD -#endif - -#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) -#define STBI_SSE2 -#include - -#ifdef _MSC_VER - -#if _MSC_VER >= 1400 // not VC6 -#include // __cpuid -static int stbi__cpuid3(void) -{ - int info[4]; - __cpuid(info, 1); - return info[3]; -} -#else -static int stbi__cpuid3(void) -{ - int res; - __asm { - mov eax, 1 - cpuid - mov res, edx - } - return res; -} -#endif - -#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name - -#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) -static int stbi__sse2_available(void) -{ - int info3 = stbi__cpuid3(); - return ((info3 >> 26) & 1) != 0; -} -#endif - -#else // assume GCC-style if not VC++ -#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) - -#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) -static int stbi__sse2_available(void) -{ - // If we're even attempting to compile this on GCC/Clang, that means - // -msse2 is on, which means the compiler is allowed to use SSE2 - // instructions at will, and so are we. - return 1; -} -#endif - -#endif -#endif - -// ARM NEON -#if defined(STBI_NO_SIMD) && defined(STBI_NEON) -#undef STBI_NEON -#endif - -#ifdef STBI_NEON -#include -#ifdef _MSC_VER -#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name -#else -#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) -#endif -#endif - -#ifndef STBI_SIMD_ALIGN -#define STBI_SIMD_ALIGN(type, name) type name -#endif - -#ifndef STBI_MAX_DIMENSIONS -#define STBI_MAX_DIMENSIONS (1 << 24) -#endif - -/////////////////////////////////////////////// -// -// stbi__context struct and start_xxx functions - -// stbi__context structure is our basic context used by all images, so it -// contains all the IO context, plus some basic image information -typedef struct { - stbi__uint32 img_x, img_y; - int img_n, img_out_n; - - stbi_io_callbacks io; - void *io_user_data; - - int read_from_callbacks; - int buflen; - stbi_uc buffer_start[128]; - int callback_already_read; - - stbi_uc *img_buffer, *img_buffer_end; - stbi_uc *img_buffer_original, *img_buffer_original_end; -} stbi__context; - -static void stbi__refill_buffer(stbi__context *s); - -// initialize a memory-decode context -static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) -{ - s->io.read = NULL; - s->read_from_callbacks = 0; - s->callback_already_read = 0; - s->img_buffer = s->img_buffer_original = (stbi_uc *)buffer; - s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *)buffer + len; -} - -// initialize a callback-based context -static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) -{ - s->io = *c; - s->io_user_data = user; - s->buflen = sizeof(s->buffer_start); - s->read_from_callbacks = 1; - s->callback_already_read = 0; - s->img_buffer = s->img_buffer_original = s->buffer_start; - stbi__refill_buffer(s); - s->img_buffer_original_end = s->img_buffer_end; -} - -#ifndef STBI_NO_STDIO - -static int stbi__stdio_read(void *user, char *data, int size) -{ - return (int)fread(data, 1, size, (FILE *)user); -} - -static void stbi__stdio_skip(void *user, int n) -{ - int ch; - fseek((FILE *)user, n, SEEK_CUR); - ch = fgetc((FILE *)user); /* have to read a byte to reset feof()'s flag */ - if (ch != EOF) { - ungetc(ch, (FILE *)user); /* push byte back onto stream if valid. */ - } -} - -static int stbi__stdio_eof(void *user) -{ - return feof((FILE *)user) || ferror((FILE *)user); -} - -static stbi_io_callbacks stbi__stdio_callbacks = { - stbi__stdio_read, - stbi__stdio_skip, - stbi__stdio_eof, -}; - -static void stbi__start_file(stbi__context *s, FILE *f) -{ - stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *)f); -} - -//static void stop_file(stbi__context *s) { } - -#endif // !STBI_NO_STDIO - -static void stbi__rewind(stbi__context *s) -{ - // conceptually rewind SHOULD rewind to the beginning of the stream, - // but we just rewind to the beginning of the initial buffer, because - // we only use it after doing 'test', which only ever looks at at most 92 bytes - s->img_buffer = s->img_buffer_original; - s->img_buffer_end = s->img_buffer_original_end; -} - -enum { STBI_ORDER_RGB, STBI_ORDER_BGR }; - -typedef struct { - int bits_per_channel; - int num_channels; - int channel_order; -} stbi__result_info; - -#ifndef STBI_NO_JPEG -static int stbi__jpeg_test(stbi__context *s); -static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PNG -static int stbi__png_test(stbi__context *s); -static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); -static int stbi__png_is16(stbi__context *s); -#endif - -#ifndef STBI_NO_BMP -static int stbi__bmp_test(stbi__context *s); -static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_TGA -static int stbi__tga_test(stbi__context *s); -static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PSD -static int stbi__psd_test(stbi__context *s); -static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri, int bpc); -static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); -static int stbi__psd_is16(stbi__context *s); -#endif - -#ifndef STBI_NO_HDR -static int stbi__hdr_test(stbi__context *s); -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PIC -static int stbi__pic_test(stbi__context *s); -static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_GIF -static int stbi__gif_test(stbi__context *s); -static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, - int req_comp); -static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PNM -static int stbi__pnm_test(stbi__context *s); -static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri); -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); -static int stbi__pnm_is16(stbi__context *s); -#endif - -static -#ifdef STBI_THREAD_LOCAL - STBI_THREAD_LOCAL -#endif - const char *stbi__g_failure_reason; - -STBIDEF const char *stbi_failure_reason(void) -{ - return stbi__g_failure_reason; -} - -#ifndef STBI_NO_FAILURE_STRINGS -static int stbi__err(const char *str) -{ - stbi__g_failure_reason = str; - return 0; -} -#endif - -static void *stbi__malloc(size_t size) -{ - return STBI_MALLOC(size); -} - -// stb_image uses ints pervasively, including for offset calculations. -// therefore the largest decoded image size we can support with the -// current code, even on 64-bit targets, is INT_MAX. this is not a -// significant limitation for the intended use case. -// -// we do, however, need to make sure our size calculations don't -// overflow. hence a few helper functions for size calculations that -// multiply integers together, making sure that they're non-negative -// and no overflow occurs. - -// return 1 if the sum is valid, 0 on overflow. -// negative terms are considered invalid. -static int stbi__addsizes_valid(int a, int b) -{ - if (b < 0) - return 0; - // now 0 <= b <= INT_MAX, hence also - // 0 <= INT_MAX - b <= INTMAX. - // And "a + b <= INT_MAX" (which might overflow) is the - // same as a <= INT_MAX - b (no overflow) - return a <= INT_MAX - b; -} - -// returns 1 if the product is valid, 0 on overflow. -// negative factors are considered invalid. -static int stbi__mul2sizes_valid(int a, int b) -{ - if (a < 0 || b < 0) - return 0; - if (b == 0) - return 1; // mul-by-0 is always safe - // portable way to check for no overflows in a*b - return a <= INT_MAX / b; -} - -#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || \ - !defined(STBI_NO_HDR) -// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow -static int stbi__mad2sizes_valid(int a, int b, int add) -{ - return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a * b, add); -} -#endif - -// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow -static int stbi__mad3sizes_valid(int a, int b, int c, int add) -{ - return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a * b, c) && - stbi__addsizes_valid(a * b * c, add); -} - -// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) -static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) -{ - return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a * b, c) && - stbi__mul2sizes_valid(a * b * c, d) && stbi__addsizes_valid(a * b * c * d, add); -} -#endif - -#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || \ - !defined(STBI_NO_HDR) -// mallocs with size overflow checking -static void *stbi__malloc_mad2(int a, int b, int add) -{ - if (!stbi__mad2sizes_valid(a, b, add)) - return NULL; - return stbi__malloc(a * b + add); -} -#endif - -static void *stbi__malloc_mad3(int a, int b, int c, int add) -{ - if (!stbi__mad3sizes_valid(a, b, c, add)) - return NULL; - return stbi__malloc(a * b * c + add); -} - -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) -static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) -{ - if (!stbi__mad4sizes_valid(a, b, c, d, add)) - return NULL; - return stbi__malloc(a * b * c * d + add); -} -#endif - -// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. -static int stbi__addints_valid(int a, int b) -{ - if ((a >= 0) != (b >= 0)) - return 1; // a and b have different signs, so no overflow - if (a < 0 && b < 0) - return a >= - INT_MIN - - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. - return a <= INT_MAX - b; -} - -// returns 1 if the product of two signed shorts is valid, 0 on overflow. -static int stbi__mul2shorts_valid(short a, short b) -{ - if (b == 0 || b == -1) - return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow - if ((a >= 0) == (b >= 0)) - return a <= SHRT_MAX / b; // product is positive, so similar to mul2sizes_valid - if (b < 0) - return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN - return a >= SHRT_MIN / b; -} - -// stbi__err - error -// stbi__errpf - error returning pointer to float -// stbi__errpuc - error returning pointer to unsigned char - -#ifdef STBI_NO_FAILURE_STRINGS -#define stbi__err(x, y) 0 -#elif defined(STBI_FAILURE_USERMSG) -#define stbi__err(x, y) stbi__err(y) -#else -#define stbi__err(x, y) stbi__err(x) -#endif - -#define stbi__errpf(x, y) ((float *)(size_t)(stbi__err(x, y) ? NULL : NULL)) -#define stbi__errpuc(x, y) ((unsigned char *)(size_t)(stbi__err(x, y) ? NULL : NULL)) - -STBIDEF void stbi_image_free(void *retval_from_stbi_load) -{ - STBI_FREE(retval_from_stbi_load); -} - -#ifndef STBI_NO_LINEAR -static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); -#endif - -#ifndef STBI_NO_HDR -static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); -#endif - -static int stbi__vertically_flip_on_load_global = 0; - -STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) -{ - stbi__vertically_flip_on_load_global = flag_true_if_should_flip; -} - -#ifndef STBI_THREAD_LOCAL -#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global -#else -static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; - -STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) -{ - stbi__vertically_flip_on_load_local = flag_true_if_should_flip; - stbi__vertically_flip_on_load_set = 1; -} - -#define stbi__vertically_flip_on_load \ - (stbi__vertically_flip_on_load_set ? stbi__vertically_flip_on_load_local : \ - stbi__vertically_flip_on_load_global) -#endif // STBI_THREAD_LOCAL - -static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri, int bpc) -{ - memset(ri, 0, - sizeof(*ri)); // make sure it's initialized if we add new fields - ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed - ri->channel_order = - STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order - ri->num_channels = 0; - - // test the formats with a very explicit header first (at least a FOURCC - // or distinctive magic number first) -#ifndef STBI_NO_PNG - if (stbi__png_test(s)) - return stbi__png_load(s, x, y, comp, req_comp, ri); -#endif -#ifndef STBI_NO_BMP - if (stbi__bmp_test(s)) - return stbi__bmp_load(s, x, y, comp, req_comp, ri); -#endif -#ifndef STBI_NO_GIF - if (stbi__gif_test(s)) - return stbi__gif_load(s, x, y, comp, req_comp, ri); -#endif -#ifndef STBI_NO_PSD - if (stbi__psd_test(s)) - return stbi__psd_load(s, x, y, comp, req_comp, ri, bpc); -#else - STBI_NOTUSED(bpc); -#endif -#ifndef STBI_NO_PIC - if (stbi__pic_test(s)) - return stbi__pic_load(s, x, y, comp, req_comp, ri); -#endif - - // then the formats that can end up attempting to load with just 1 or 2 - // bytes matching expectations; these are prone to false positives, so - // try them later -#ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) - return stbi__jpeg_load(s, x, y, comp, req_comp, ri); -#endif -#ifndef STBI_NO_PNM - if (stbi__pnm_test(s)) - return stbi__pnm_load(s, x, y, comp, req_comp, ri); -#endif - -#ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { - float *hdr = stbi__hdr_load(s, x, y, comp, req_comp, ri); - return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); - } -#endif - -#ifndef STBI_NO_TGA - // test tga last because it's a crappy test! - if (stbi__tga_test(s)) - return stbi__tga_load(s, x, y, comp, req_comp, ri); -#endif - - return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); -} - -static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) -{ - int i; - int img_len = w * h * channels; - stbi_uc *reduced; - - reduced = (stbi_uc *)stbi__malloc(img_len); - if (reduced == NULL) - return stbi__errpuc("outofmem", "Out of memory"); - - for (i = 0; i < img_len; ++i) - reduced[i] = - (stbi_uc)((orig[i] >> 8) & - 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling - - STBI_FREE(orig); - return reduced; -} - -static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) -{ - int i; - int img_len = w * h * channels; - stbi__uint16 *enlarged; - - enlarged = (stbi__uint16 *)stbi__malloc(img_len * 2); - if (enlarged == NULL) - return (stbi__uint16 *)stbi__errpuc("outofmem", "Out of memory"); - - for (i = 0; i < img_len; ++i) - enlarged[i] = - (stbi__uint16)((orig[i] << 8) + - orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff - - STBI_FREE(orig); - return enlarged; -} - -static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) -{ - int row; - size_t bytes_per_row = (size_t)w * bytes_per_pixel; - stbi_uc temp[2048]; - stbi_uc *bytes = (stbi_uc *)image; - - for (row = 0; row < (h >> 1); row++) { - stbi_uc *row0 = bytes + row * bytes_per_row; - stbi_uc *row1 = bytes + (h - row - 1) * bytes_per_row; - // swap row0 with row1 - size_t bytes_left = bytes_per_row; - while (bytes_left) { - size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); - memcpy(temp, row0, bytes_copy); - memcpy(row0, row1, bytes_copy); - memcpy(row1, temp, bytes_copy); - row0 += bytes_copy; - row1 += bytes_copy; - bytes_left -= bytes_copy; - } - } -} - -#ifndef STBI_NO_GIF -static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) -{ - int slice; - int slice_size = w * h * bytes_per_pixel; - - stbi_uc *bytes = (stbi_uc *)image; - for (slice = 0; slice < z; ++slice) { - stbi__vertical_flip(bytes, w, h, bytes_per_pixel); - bytes += slice_size; - } -} -#endif - -static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, - int req_comp) -{ - stbi__result_info ri; - void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); - - if (result == NULL) - return NULL; - - // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. - STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); - - if (ri.bits_per_channel != 8) { - result = stbi__convert_16_to_8((stbi__uint16 *)result, *x, *y, - req_comp == 0 ? *comp : req_comp); - ri.bits_per_channel = 8; - } - - // @TODO: move stbi__convert_format to here - - if (stbi__vertically_flip_on_load) { - int channels = req_comp ? req_comp : *comp; - stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); - } - - return (unsigned char *)result; -} - -static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, - int req_comp) -{ - stbi__result_info ri; - void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); - - if (result == NULL) - return NULL; - - // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. - STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); - - if (ri.bits_per_channel != 16) { - result = stbi__convert_8_to_16((stbi_uc *)result, *x, *y, - req_comp == 0 ? *comp : req_comp); - ri.bits_per_channel = 16; - } - - // @TODO: move stbi__convert_format16 to here - // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision - - if (stbi__vertically_flip_on_load) { - int channels = req_comp ? req_comp : *comp; - stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); - } - - return (stbi__uint16 *)result; -} - -#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) -static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) -{ - if (stbi__vertically_flip_on_load && result != NULL) { - int channels = req_comp ? req_comp : *comp; - stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); - } -} -#endif - -#ifndef STBI_NO_STDIO - -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) -STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, - unsigned long flags, - const char *str, int cbmb, - wchar_t *widestr, int cchwide); -STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte( - unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, - int cbmb, const char *defchar, int *used_default); -#endif - -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) -STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t *input) -{ - return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int)bufferlen, NULL, - NULL); -} -#endif - -static FILE *stbi__fopen(char const *filename, char const *mode) -{ - FILE *f; -#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) - wchar_t wMode[64]; - wchar_t wFilename[1024]; - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, - sizeof(wFilename) / sizeof(*wFilename))) - return 0; - - if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, - sizeof(wMode) / sizeof(*wMode))) - return 0; - -#if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != _wfopen_s(&f, wFilename, wMode)) - f = 0; -#else - f = _wfopen(wFilename, wMode); -#endif - -#elif defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != fopen_s(&f, filename, mode)) - f = 0; -#else - f = fopen(filename, mode); -#endif - return f; -} - -STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - unsigned char *result; - if (!f) - return stbi__errpuc("can't fopen", "Unable to open file"); - result = stbi_load_from_file(f, x, y, comp, req_comp); - fclose(f); - return result; -} - -STBIDEF void stbi_load_to_target(char const *filename, int *x, int *y, stbi_uc *target, int *comp, - int req_comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - unsigned char *result; - if (!f) { - *target = "can't fopen, Unable to open file"; - return; - } - result = stbi_load_from_file(f, x, y, comp, req_comp); - fclose(f); -} - -STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *result; - stbi__context s; - stbi__start_file(&s, f); - result = stbi__load_and_postprocess_8bit(&s, x, y, comp, req_comp); - if (result) { - // need to 'unget' all the characters in the IO buffer - fseek(f, -(int)(s.img_buffer_end - s.img_buffer), SEEK_CUR); - } - return result; -} - -STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi__uint16 *result; - stbi__context s; - stbi__start_file(&s, f); - result = stbi__load_and_postprocess_16bit(&s, x, y, comp, req_comp); - if (result) { - // need to 'unget' all the characters in the IO buffer - fseek(f, -(int)(s.img_buffer_end - s.img_buffer), SEEK_CUR); - } - return result; -} - -STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - stbi__uint16 *result; - if (!f) - return (stbi_us *)stbi__errpuc("can't fopen", "Unable to open file"); - result = stbi_load_from_file_16(f, x, y, comp, req_comp); - fclose(f); - return result; -} - -#endif //!STBI_NO_STDIO - -STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, - int *channels_in_file, int desired_channels) -{ - stbi__context s; - stbi__start_mem(&s, buffer, len); - return stbi__load_and_postprocess_16bit(&s, x, y, channels_in_file, desired_channels); -} - -STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, - int *y, int *channels_in_file, int desired_channels) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); - return stbi__load_and_postprocess_16bit(&s, x, y, channels_in_file, desired_channels); -} - -STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, - int req_comp) -{ - stbi__context s; - stbi__start_mem(&s, buffer, len); - return stbi__load_and_postprocess_8bit(&s, x, y, comp, req_comp); -} - -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, - int *comp, int req_comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); - return stbi__load_and_postprocess_8bit(&s, x, y, comp, req_comp); -} - -#ifndef STBI_NO_GIF -STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, - int *y, int *z, int *comp, int req_comp) -{ - unsigned char *result; - stbi__context s; - stbi__start_mem(&s, buffer, len); - - result = (unsigned char *)stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); - if (stbi__vertically_flip_on_load) { - stbi__vertical_flip_slices(result, *x, *y, *z, *comp); - } - - return result; -} -#endif - -#ifndef STBI_NO_LINEAR -static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; -#ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { - stbi__result_info ri; - float *hdr_data = stbi__hdr_load(s, x, y, comp, req_comp, &ri); - if (hdr_data) - stbi__float_postprocess(hdr_data, x, y, comp, req_comp); - return hdr_data; - } -#endif - data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); - if (data) - return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); -} - -STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, - int req_comp) -{ - stbi__context s; - stbi__start_mem(&s, buffer, len); - return stbi__loadf_main(&s, x, y, comp, req_comp); -} - -STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, - int *comp, int req_comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); - return stbi__loadf_main(&s, x, y, comp, req_comp); -} - -#ifndef STBI_NO_STDIO -STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - float *result; - FILE *f = stbi__fopen(filename, "rb"); - if (!f) - return stbi__errpf("can't fopen", "Unable to open file"); - result = stbi_loadf_from_file(f, x, y, comp, req_comp); - fclose(f); - return result; -} - -STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_file(&s, f); - return stbi__loadf_main(&s, x, y, comp, req_comp); -} -#endif // !STBI_NO_STDIO - -#endif // !STBI_NO_LINEAR - -// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is -// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always -// reports false! - -STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) -{ -#ifndef STBI_NO_HDR - stbi__context s; - stbi__start_mem(&s, buffer, len); - return stbi__hdr_test(&s); -#else - STBI_NOTUSED(buffer); - STBI_NOTUSED(len); - return 0; -#endif -} - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_is_hdr(char const *filename) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result = 0; - if (f) { - result = stbi_is_hdr_from_file(f); - fclose(f); - } - return result; -} - -STBIDEF int stbi_is_hdr_from_file(FILE *f) -{ -#ifndef STBI_NO_HDR - long pos = ftell(f); - int res; - stbi__context s; - stbi__start_file(&s, f); - res = stbi__hdr_test(&s); - fseek(f, pos, SEEK_SET); - return res; -#else - STBI_NOTUSED(f); - return 0; -#endif -} -#endif // !STBI_NO_STDIO - -STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) -{ -#ifndef STBI_NO_HDR - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); - return stbi__hdr_test(&s); -#else - STBI_NOTUSED(clbk); - STBI_NOTUSED(user); - return 0; -#endif -} - -#ifndef STBI_NO_LINEAR -static float stbi__l2h_gamma = 2.2f, stbi__l2h_scale = 1.0f; - -STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) -{ - stbi__l2h_gamma = gamma; -} -STBIDEF void stbi_ldr_to_hdr_scale(float scale) -{ - stbi__l2h_scale = scale; -} -#endif - -static float stbi__h2l_gamma_i = 1.0f / 2.2f, stbi__h2l_scale_i = 1.0f; - -STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) -{ - stbi__h2l_gamma_i = 1 / gamma; -} -STBIDEF void stbi_hdr_to_ldr_scale(float scale) -{ - stbi__h2l_scale_i = 1 / scale; -} - -////////////////////////////////////////////////////////////////////////////// -// -// Common code used by all image loaders -// - -enum { STBI__SCAN_load = 0, STBI__SCAN_type, STBI__SCAN_header }; - -static void stbi__refill_buffer(stbi__context *s) -{ - int n = (s->io.read)(s->io_user_data, (char *)s->buffer_start, s->buflen); - s->callback_already_read += (int)(s->img_buffer - s->img_buffer_original); - if (n == 0) { - // at end of file, treat same as if from memory, but need to handle case - // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file - s->read_from_callbacks = 0; - s->img_buffer = s->buffer_start; - s->img_buffer_end = s->buffer_start + 1; - *s->img_buffer = 0; - } else { - s->img_buffer = s->buffer_start; - s->img_buffer_end = s->buffer_start + n; - } -} - -stbi_inline static stbi_uc stbi__get8(stbi__context *s) -{ - if (s->img_buffer < s->img_buffer_end) - return *s->img_buffer++; - if (s->read_from_callbacks) { - stbi__refill_buffer(s); - return *s->img_buffer++; - } - return 0; -} - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) -// nothing -#else -stbi_inline static int stbi__at_eof(stbi__context *s) -{ - if (s->io.read) { - if (!(s->io.eof)(s->io_user_data)) - return 0; - // if feof() is true, check if buffer = end - // special case: we've only got the special 0 character at the end - if (s->read_from_callbacks == 0) - return 1; - } - - return s->img_buffer >= s->img_buffer_end; -} -#endif - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && \ - defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && \ - defined(STBI_NO_PIC) -// nothing -#else -static void stbi__skip(stbi__context *s, int n) -{ - if (n == 0) - return; // already there! - if (n < 0) { - s->img_buffer = s->img_buffer_end; - return; - } - if (s->io.read) { - int blen = (int)(s->img_buffer_end - s->img_buffer); - if (blen < n) { - s->img_buffer = s->img_buffer_end; - (s->io.skip)(s->io_user_data, n - blen); - return; - } - } - s->img_buffer += n; -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) -// nothing -#else -static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) -{ - if (s->io.read) { - int blen = (int)(s->img_buffer_end - s->img_buffer); - if (blen < n) { - int res, count; - - memcpy(buffer, s->img_buffer, blen); - - count = (s->io.read)(s->io_user_data, (char *)buffer + blen, n - blen); - res = (count == (n - blen)); - s->img_buffer = s->img_buffer_end; - return res; - } - } - - if (s->img_buffer + n <= s->img_buffer_end) { - memcpy(buffer, s->img_buffer, n); - s->img_buffer += n; - return 1; - } else - return 0; -} -#endif - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) -// nothing -#else -static int stbi__get16be(stbi__context *s) -{ - int z = stbi__get8(s); - return (z << 8) + stbi__get8(s); -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) -// nothing -#else -static stbi__uint32 stbi__get32be(stbi__context *s) -{ - stbi__uint32 z = stbi__get16be(s); - return (z << 16) + stbi__get16be(s); -} -#endif - -#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) -// nothing -#else -static int stbi__get16le(stbi__context *s) -{ - int z = stbi__get8(s); - return z + (stbi__get8(s) << 8); -} -#endif - -#ifndef STBI_NO_BMP -static stbi__uint32 stbi__get32le(stbi__context *s) -{ - stbi__uint32 z = stbi__get16le(s); - z += (stbi__uint32)stbi__get16le(s) << 16; - return z; -} -#endif - -#define STBI__BYTECAST(x) ((stbi_uc)((x) & 255)) // truncate int to byte without warnings - -#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && \ - defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && \ - defined(STBI_NO_PIC) && defined(STBI_NO_PNM) -// nothing -#else -////////////////////////////////////////////////////////////////////////////// -// -// generic converter from built-in img_n to req_comp -// individual types do this automatically as much as possible (e.g. jpeg -// does all cases internally since it needs to colorspace convert anyway, -// and it never has alpha, so very few cases ). png can automatically -// interleave an alpha=255 channel, but falls back to this for other cases -// -// assume data buffer is malloced, so malloc a new one and free that one -// only failure mode is malloc failing - -static stbi_uc stbi__compute_y(int r, int g, int b) -{ - return (stbi_uc)(((r * 77) + (g * 150) + (29 * b)) >> 8); -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && \ - defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && \ - defined(STBI_NO_PNM) -// nothing -#else -static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, - unsigned int x, unsigned int y) -{ - int i, j; - unsigned char *good; - - if (req_comp == img_n) - return data; - STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - - good = (unsigned char *)stbi__malloc_mad3(req_comp, x, y, 0); - if (good == NULL) { - STBI_FREE(data); - return stbi__errpuc("outofmem", "Out of memory"); - } - - for (j = 0; j < (int)y; ++j) { - unsigned char *src = data + j * x * img_n; - unsigned char *dest = good + j * x * req_comp; - -#define STBI__COMBO(a, b) ((a) * 8 + (b)) -#define STBI__CASE(a, b) \ - case STBI__COMBO(a, b): \ - for (i = x - 1; i >= 0; --i, src += a, dest += b) - // convert source image with img_n components to one with req_comp components; - // avoid switch per pixel, so use switch per scanline and massive macros - switch (STBI__COMBO(img_n, req_comp)) { - STBI__CASE(1, 2) - { - dest[0] = src[0]; - dest[1] = 255; - } - break; - STBI__CASE(1, 3) - { - dest[0] = dest[1] = dest[2] = src[0]; - } - break; - STBI__CASE(1, 4) - { - dest[0] = dest[1] = dest[2] = src[0]; - dest[3] = 255; - } - break; - STBI__CASE(2, 1) - { - dest[0] = src[0]; - } - break; - STBI__CASE(2, 3) - { - dest[0] = dest[1] = dest[2] = src[0]; - } - break; - STBI__CASE(2, 4) - { - dest[0] = dest[1] = dest[2] = src[0]; - dest[3] = src[1]; - } - break; - STBI__CASE(3, 4) - { - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; - dest[3] = 255; - } - break; - STBI__CASE(3, 1) - { - dest[0] = stbi__compute_y(src[0], src[1], src[2]); - } - break; - STBI__CASE(3, 2) - { - dest[0] = stbi__compute_y(src[0], src[1], src[2]); - dest[1] = 255; - } - break; - STBI__CASE(4, 1) - { - dest[0] = stbi__compute_y(src[0], src[1], src[2]); - } - break; - STBI__CASE(4, 2) - { - dest[0] = stbi__compute_y(src[0], src[1], src[2]); - dest[1] = src[3]; - } - break; - STBI__CASE(4, 3) - { - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; - } - break; - default: - STBI_ASSERT(0); - STBI_FREE(data); - STBI_FREE(good); - return stbi__errpuc("unsupported", "Unsupported format conversion"); - } -#undef STBI__CASE - } - - STBI_FREE(data); - return good; -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) -// nothing -#else -static stbi__uint16 stbi__compute_y_16(int r, int g, int b) -{ - return (stbi__uint16)(((r * 77) + (g * 150) + (29 * b)) >> 8); -} -#endif - -#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) -// nothing -#else -static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, - unsigned int x, unsigned int y) -{ - int i, j; - stbi__uint16 *good; - - if (req_comp == img_n) - return data; - STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - - good = (stbi__uint16 *)stbi__malloc(req_comp * x * y * 2); - if (good == NULL) { - STBI_FREE(data); - return (stbi__uint16 *)stbi__errpuc("outofmem", "Out of memory"); - } - - for (j = 0; j < (int)y; ++j) { - stbi__uint16 *src = data + j * x * img_n; - stbi__uint16 *dest = good + j * x * req_comp; - -#define STBI__COMBO(a, b) ((a) * 8 + (b)) -#define STBI__CASE(a, b) \ - case STBI__COMBO(a, b): \ - for (i = x - 1; i >= 0; --i, src += a, dest += b) - // convert source image with img_n components to one with req_comp components; - // avoid switch per pixel, so use switch per scanline and massive macros - switch (STBI__COMBO(img_n, req_comp)) { - STBI__CASE(1, 2) - { - dest[0] = src[0]; - dest[1] = 0xffff; - } - break; - STBI__CASE(1, 3) - { - dest[0] = dest[1] = dest[2] = src[0]; - } - break; - STBI__CASE(1, 4) - { - dest[0] = dest[1] = dest[2] = src[0]; - dest[3] = 0xffff; - } - break; - STBI__CASE(2, 1) - { - dest[0] = src[0]; - } - break; - STBI__CASE(2, 3) - { - dest[0] = dest[1] = dest[2] = src[0]; - } - break; - STBI__CASE(2, 4) - { - dest[0] = dest[1] = dest[2] = src[0]; - dest[3] = src[1]; - } - break; - STBI__CASE(3, 4) - { - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; - dest[3] = 0xffff; - } - break; - STBI__CASE(3, 1) - { - dest[0] = stbi__compute_y_16(src[0], src[1], src[2]); - } - break; - STBI__CASE(3, 2) - { - dest[0] = stbi__compute_y_16(src[0], src[1], src[2]); - dest[1] = 0xffff; - } - break; - STBI__CASE(4, 1) - { - dest[0] = stbi__compute_y_16(src[0], src[1], src[2]); - } - break; - STBI__CASE(4, 2) - { - dest[0] = stbi__compute_y_16(src[0], src[1], src[2]); - dest[1] = src[3]; - } - break; - STBI__CASE(4, 3) - { - dest[0] = src[0]; - dest[1] = src[1]; - dest[2] = src[2]; - } - break; - default: - STBI_ASSERT(0); - STBI_FREE(data); - STBI_FREE(good); - return (stbi__uint16 *)stbi__errpuc("unsupported", - "Unsupported format conversion"); - } -#undef STBI__CASE - } - - STBI_FREE(data); - return good; -} -#endif - -#ifndef STBI_NO_LINEAR -static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) -{ - int i, k, n; - float *output; - if (!data) - return NULL; - output = (float *)stbi__malloc_mad4(x, y, comp, sizeof(float), 0); - if (output == NULL) { - STBI_FREE(data); - return stbi__errpf("outofmem", "Out of memory"); - } - // compute number of non-alpha components - if (comp & 1) - n = comp; - else - n = comp - 1; - for (i = 0; i < x * y; ++i) { - for (k = 0; k < n; ++k) { - output[i * comp + k] = - (float)(pow(data[i * comp + k] / 255.0f, stbi__l2h_gamma) * - stbi__l2h_scale); - } - } - if (n < comp) { - for (i = 0; i < x * y; ++i) { - output[i * comp + n] = data[i * comp + n] / 255.0f; - } - } - STBI_FREE(data); - return output; -} -#endif - -#ifndef STBI_NO_HDR -#define stbi__float2int(x) ((int)(x)) -static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) -{ - int i, k, n; - stbi_uc *output; - if (!data) - return NULL; - output = (stbi_uc *)stbi__malloc_mad3(x, y, comp, 0); - if (output == NULL) { - STBI_FREE(data); - return stbi__errpuc("outofmem", "Out of memory"); - } - // compute number of non-alpha components - if (comp & 1) - n = comp; - else - n = comp - 1; - for (i = 0; i < x * y; ++i) { - for (k = 0; k < n; ++k) { - float z = (float)pow(data[i * comp + k] * stbi__h2l_scale_i, - stbi__h2l_gamma_i) * - 255 + - 0.5f; - if (z < 0) - z = 0; - if (z > 255) - z = 255; - output[i * comp + k] = (stbi_uc)stbi__float2int(z); - } - if (k < comp) { - float z = data[i * comp + k] * 255 + 0.5f; - if (z < 0) - z = 0; - if (z > 255) - z = 255; - output[i * comp + k] = (stbi_uc)stbi__float2int(z); - } - } - STBI_FREE(data); - return output; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// "baseline" JPEG/JFIF decoder -// -// simple implementation -// - doesn't support delayed output of y-dimension -// - simple interface (only one output format: 8-bit interleaved RGB) -// - doesn't try to recover corrupt jpegs -// - doesn't allow partial loading, loading multiple at once -// - still fast on x86 (copying globals into locals doesn't help x86) -// - allocates lots of intermediate memory (full size of all components) -// - non-interleaved case requires this anyway -// - allows good upsampling (see next) -// high-quality -// - upsampled channels are bilinearly interpolated, even across blocks -// - quality integer IDCT derived from IJG's 'slow' -// performance -// - fast huffman; reasonable integer IDCT -// - some SIMD kernels for common paths on targets with SSE2/NEON -// - uses a lot of intermediate memory, could cache poorly - -#ifndef STBI_NO_JPEG - -// huffman decoding acceleration -#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache - -typedef struct { - stbi_uc fast[1 << FAST_BITS]; - // weirdly, repacking this into AoS is a 10% speed loss, instead of a win - stbi__uint16 code[256]; - stbi_uc values[256]; - stbi_uc size[257]; - unsigned int maxcode[18]; - int delta[17]; // old 'firstsymbol' - old 'firstcode' -} stbi__huffman; - -typedef struct { - stbi__context *s; - stbi__huffman huff_dc[4]; - stbi__huffman huff_ac[4]; - stbi__uint16 dequant[4][64]; - stbi__int16 fast_ac[4][1 << FAST_BITS]; - - // sizes for components, interleaved MCUs - int img_h_max, img_v_max; - int img_mcu_x, img_mcu_y; - int img_mcu_w, img_mcu_h; - - // definition of jpeg image component - struct { - int id; - int h, v; - int tq; - int hd, ha; - int dc_pred; - - int x, y, w2, h2; - stbi_uc *data; - void *raw_data, *raw_coeff; - stbi_uc *linebuf; - short *coeff; // progressive only - int coeff_w, coeff_h; // number of 8x8 coefficient blocks - } img_comp[4]; - - stbi__uint32 code_buffer; // jpeg entropy-coded buffer - int code_bits; // number of valid bits - unsigned char marker; // marker seen while filling entropy buffer - int nomore; // flag if we saw a marker so must stop - - int progressive; - int spec_start; - int spec_end; - int succ_high; - int succ_low; - int eob_run; - int jfif; - int app14_color_transform; // Adobe APP14 tag - int rgb; - - int scan_n, order[4]; - int restart_interval, todo; - - // kernels - void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); - void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, - const stbi_uc *pcr, int count, int step); - stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, - int hs); -} stbi__jpeg; - -static int stbi__build_huffman(stbi__huffman *h, int *count) -{ - int i, j, k = 0; - unsigned int code; - // build size list for each symbol (from JPEG spec) - for (i = 0; i < 16; ++i) { - for (j = 0; j < count[i]; ++j) { - h->size[k++] = (stbi_uc)(i + 1); - if (k >= 257) - return stbi__err("bad size list", "Corrupt JPEG"); - } - } - h->size[k] = 0; - - // compute actual symbols (from jpeg spec) - code = 0; - k = 0; - for (j = 1; j <= 16; ++j) { - // compute delta to add to code to compute symbol id - h->delta[j] = k - code; - if (h->size[k] == j) { - while (h->size[k] == j) - h->code[k++] = (stbi__uint16)(code++); - if (code - 1 >= (1u << j)) - return stbi__err("bad code lengths", "Corrupt JPEG"); - } - // compute largest code + 1 for this size, preshifted as needed later - h->maxcode[j] = code << (16 - j); - code <<= 1; - } - h->maxcode[j] = 0xffffffff; - - // build non-spec acceleration table; 255 is flag for not-accelerated - memset(h->fast, 255, 1 << FAST_BITS); - for (i = 0; i < k; ++i) { - int s = h->size[i]; - if (s <= FAST_BITS) { - int c = h->code[i] << (FAST_BITS - s); - int m = 1 << (FAST_BITS - s); - for (j = 0; j < m; ++j) { - h->fast[c + j] = (stbi_uc)i; - } - } - } - return 1; -} - -// build a table that decodes both magnitude and value of small ACs in -// one go. -static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) -{ - int i; - for (i = 0; i < (1 << FAST_BITS); ++i) { - stbi_uc fast = h->fast[i]; - fast_ac[i] = 0; - if (fast < 255) { - int rs = h->values[fast]; - int run = (rs >> 4) & 15; - int magbits = rs & 15; - int len = h->size[fast]; - - if (magbits && len + magbits <= FAST_BITS) { - // magnitude code followed by receive_extend code - int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> - (FAST_BITS - magbits); - int m = 1 << (magbits - 1); - if (k < m) - k += (~0U << magbits) + 1; - // if the result is small enough, we can fit it in fast_ac table - if (k >= -128 && k <= 127) - fast_ac[i] = (stbi__int16)((k * 256) + (run * 16) + - (len + magbits)); - } - } - } -} - -static void stbi__grow_buffer_unsafe(stbi__jpeg *j) -{ - do { - unsigned int b = j->nomore ? 0 : stbi__get8(j->s); - if (b == 0xff) { - int c = stbi__get8(j->s); - while (c == 0xff) - c = stbi__get8(j->s); // consume fill bytes - if (c != 0) { - j->marker = (unsigned char)c; - j->nomore = 1; - return; - } - } - j->code_buffer |= b << (24 - j->code_bits); - j->code_bits += 8; - } while (j->code_bits <= 24); -} - -// (1 << n) - 1 -static const stbi__uint32 stbi__bmask[17] = { 0, 1, 3, 7, 15, 31, 63, 127, 255, - 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535 }; - -// decode a jpeg huffman value from the bitstream -stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) -{ - unsigned int temp; - int c, k; - - if (j->code_bits < 16) - stbi__grow_buffer_unsafe(j); - - // look at the top FAST_BITS and determine what symbol ID it is, - // if the code is <= FAST_BITS - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS) - 1); - k = h->fast[c]; - if (k < 255) { - int s = h->size[k]; - if (s > j->code_bits) - return -1; - j->code_buffer <<= s; - j->code_bits -= s; - return h->values[k]; - } - - // naive test is to shift the code_buffer down so k bits are - // valid, then test against maxcode. To speed this up, we've - // preshifted maxcode left so that it has (16-k) 0s at the - // end; in other words, regardless of the number of bits, it - // wants to be compared against something shifted to have 16; - // that way we don't need to shift inside the loop. - temp = j->code_buffer >> 16; - for (k = FAST_BITS + 1;; ++k) - if (temp < h->maxcode[k]) - break; - if (k == 17) { - // error! code not found - j->code_bits -= 16; - return -1; - } - - if (k > j->code_bits) - return -1; - - // convert the huffman code to the symbol id - c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; - if (c < 0 || c >= 256) // symbol id out of bounds! - return -1; - STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == - h->code[c]); - - // convert the id to a symbol - j->code_bits -= k; - j->code_buffer <<= k; - return h->values[c]; -} - -// bias[n] = (-1<code_bits < n) - stbi__grow_buffer_unsafe(j); - if (j->code_bits < n) - return 0; // ran out of bits from stream, return 0s intead of continuing - - sgn = j->code_buffer >> - 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) - k = stbi_lrot(j->code_buffer, n); - j->code_buffer = k & ~stbi__bmask[n]; - k &= stbi__bmask[n]; - j->code_bits -= n; - return k + (stbi__jbias[n] & (sgn - 1)); -} - -// get some unsigned bits -stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) -{ - unsigned int k; - if (j->code_bits < n) - stbi__grow_buffer_unsafe(j); - if (j->code_bits < n) - return 0; // ran out of bits from stream, return 0s intead of continuing - k = stbi_lrot(j->code_buffer, n); - j->code_buffer = k & ~stbi__bmask[n]; - k &= stbi__bmask[n]; - j->code_bits -= n; - return k; -} - -stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) -{ - unsigned int k; - if (j->code_bits < 1) - stbi__grow_buffer_unsafe(j); - if (j->code_bits < 1) - return 0; // ran out of bits from stream, return 0s intead of continuing - k = j->code_buffer; - j->code_buffer <<= 1; - --j->code_bits; - return k & 0x80000000; -} - -// given a value that's at position X in the zigzag stream, -// where does it appear in the 8x8 matrix coded as row-major? -static const stbi_uc stbi__jpeg_dezigzag[64 + 15] = { - 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, - 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63, - // let corrupt input sample past end - 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63 -}; - -// decode one 64-entry block-- -static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, - stbi__huffman *hac, stbi__int16 *fac, int b, - stbi__uint16 *dequant) -{ - int diff, dc, k; - int t; - - if (j->code_bits < 16) - stbi__grow_buffer_unsafe(j); - t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0 || t > 15) - return stbi__err("bad huffman code", "Corrupt JPEG"); - - // 0 all the ac values now so we can do it 32-bits at a time - memset(data, 0, 64 * sizeof(data[0])); - - diff = t ? stbi__extend_receive(j, t) : 0; - if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) - return stbi__err("bad delta", "Corrupt JPEG"); - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - if (!stbi__mul2shorts_valid(dc, dequant[0])) - return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - data[0] = (short)(dc * dequant[0]); - - // decode AC components, see JPEG spec - k = 1; - do { - unsigned int zig; - int c, r, s; - if (j->code_bits < 16) - stbi__grow_buffer_unsafe(j); - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS) - 1); - r = fac[c]; - if (r) { // fast-AC path - k += (r >> 4) & 15; // run - s = r & 15; // combined length - if (s > j->code_bits) - return stbi__err("bad huffman code", - "Combined length longer than code bits available"); - j->code_buffer <<= s; - j->code_bits -= s; - // decode into unzigzag'd location - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short)((r >> 8) * dequant[zig]); - } else { - int rs = stbi__jpeg_huff_decode(j, hac); - if (rs < 0) - return stbi__err("bad huffman code", "Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (rs != 0xf0) - break; // end block - k += 16; - } else { - k += r; - // decode into unzigzag'd location - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short)(stbi__extend_receive(j, s) * dequant[zig]); - } - } - } while (k < 64); - return 1; -} - -static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) -{ - int diff, dc; - int t; - if (j->spec_end != 0) - return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - - if (j->code_bits < 16) - stbi__grow_buffer_unsafe(j); - - if (j->succ_high == 0) { - // first scan for DC coefficient, must be first - memset(data, 0, - 64 * sizeof(data[0])); // 0 all the ac values now - t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0 || t > 15) - return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - diff = t ? stbi__extend_receive(j, t) : 0; - - if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) - return stbi__err("bad delta", "Corrupt JPEG"); - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) - return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - data[0] = (short)(dc * (1 << j->succ_low)); - } else { - // refinement scan for DC coefficient - if (stbi__jpeg_get_bit(j)) - data[0] += (short)(1 << j->succ_low); - } - return 1; -} - -// @OPTIMIZE: store non-zigzagged during the decode passes, -// and only de-zigzag when dequantizing -static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, - stbi__int16 *fac) -{ - int k; - if (j->spec_start == 0) - return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - - if (j->succ_high == 0) { - int shift = j->succ_low; - - if (j->eob_run) { - --j->eob_run; - return 1; - } - - k = j->spec_start; - do { - unsigned int zig; - int c, r, s; - if (j->code_bits < 16) - stbi__grow_buffer_unsafe(j); - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS) - 1); - r = fac[c]; - if (r) { // fast-AC path - k += (r >> 4) & 15; // run - s = r & 15; // combined length - if (s > j->code_bits) - return stbi__err( - "bad huffman code", - "Combined length longer than code bits available"); - j->code_buffer <<= s; - j->code_bits -= s; - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short)((r >> 8) * (1 << shift)); - } else { - int rs = stbi__jpeg_huff_decode(j, hac); - if (rs < 0) - return stbi__err("bad huffman code", "Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (r < 15) { - j->eob_run = (1 << r); - if (r) - j->eob_run += stbi__jpeg_get_bits(j, r); - --j->eob_run; - break; - } - k += 16; - } else { - k += r; - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = - (short)(stbi__extend_receive(j, s) * (1 << shift)); - } - } - } while (k <= j->spec_end); - } else { - // refinement scan for these AC coefficients - - short bit = (short)(1 << j->succ_low); - - if (j->eob_run) { - --j->eob_run; - for (k = j->spec_start; k <= j->spec_end; ++k) { - short *p = &data[stbi__jpeg_dezigzag[k]]; - if (*p != 0) - if (stbi__jpeg_get_bit(j)) - if ((*p & bit) == 0) { - if (*p > 0) - *p += bit; - else - *p -= bit; - } - } - } else { - k = j->spec_start; - do { - int r, s; - int rs = stbi__jpeg_huff_decode( - j, - hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh - if (rs < 0) - return stbi__err("bad huffman code", "Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (r < 15) { - j->eob_run = (1 << r) - 1; - if (r) - j->eob_run += stbi__jpeg_get_bits(j, r); - r = 64; // force end of block - } else { - // r=15 s=0 should write 16 0s, so we just do - // a run of 15 0s and then write s (which is 0), - // so we don't have to do anything special here - } - } else { - if (s != 1) - return stbi__err("bad huffman code", - "Corrupt JPEG"); - // sign bit - if (stbi__jpeg_get_bit(j)) - s = bit; - else - s = -bit; - } - - // advance by r - while (k <= j->spec_end) { - short *p = &data[stbi__jpeg_dezigzag[k++]]; - if (*p != 0) { - if (stbi__jpeg_get_bit(j)) - if ((*p & bit) == 0) { - if (*p > 0) - *p += bit; - else - *p -= bit; - } - } else { - if (r == 0) { - *p = (short)s; - break; - } - --r; - } - } - } while (k <= j->spec_end); - } - } - return 1; -} - -// take a -128..127 value and stbi__clamp it and convert to 0..255 -stbi_inline static stbi_uc stbi__clamp(int x) -{ - // trick to use a single test to catch both cases - if ((unsigned int)x > 255) { - if (x < 0) - return 0; - if (x > 255) - return 255; - } - return (stbi_uc)x; -} - -#define stbi__f2f(x) ((int)(((x) * 4096 + 0.5))) -#define stbi__fsh(x) ((x) * 4096) - -// derived from jidctint -- DCT_ISLOW -#define STBI__IDCT_1D(s0, s1, s2, s3, s4, s5, s6, s7) \ - int t0, t1, t2, t3, p1, p2, p3, p4, p5, x0, x1, x2, x3; \ - p2 = s2; \ - p3 = s6; \ - p1 = (p2 + p3) * stbi__f2f(0.5411961f); \ - t2 = p1 + p3 * stbi__f2f(-1.847759065f); \ - t3 = p1 + p2 * stbi__f2f(0.765366865f); \ - p2 = s0; \ - p3 = s4; \ - t0 = stbi__fsh(p2 + p3); \ - t1 = stbi__fsh(p2 - p3); \ - x0 = t0 + t3; \ - x3 = t0 - t3; \ - x1 = t1 + t2; \ - x2 = t1 - t2; \ - t0 = s7; \ - t1 = s5; \ - t2 = s3; \ - t3 = s1; \ - p3 = t0 + t2; \ - p4 = t1 + t3; \ - p1 = t0 + t3; \ - p2 = t1 + t2; \ - p5 = (p3 + p4) * stbi__f2f(1.175875602f); \ - t0 = t0 * stbi__f2f(0.298631336f); \ - t1 = t1 * stbi__f2f(2.053119869f); \ - t2 = t2 * stbi__f2f(3.072711026f); \ - t3 = t3 * stbi__f2f(1.501321110f); \ - p1 = p5 + p1 * stbi__f2f(-0.899976223f); \ - p2 = p5 + p2 * stbi__f2f(-2.562915447f); \ - p3 = p3 * stbi__f2f(-1.961570560f); \ - p4 = p4 * stbi__f2f(-0.390180644f); \ - t3 += p1 + p4; \ - t2 += p2 + p3; \ - t1 += p2 + p4; \ - t0 += p1 + p3; - -static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) -{ - int i, val[64], *v = val; - stbi_uc *o; - short *d = data; - - // columns - for (i = 0; i < 8; ++i, ++d, ++v) { - // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing - if (d[8] == 0 && d[16] == 0 && d[24] == 0 && d[32] == 0 && d[40] == 0 && - d[48] == 0 && d[56] == 0) { - // no shortcut 0 seconds - // (1|2|3|4|5|6|7)==0 0 seconds - // all separate -0.047 seconds - // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds - int dcterm = d[0] * 4; - v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; - } else { - STBI__IDCT_1D(d[0], d[8], d[16], d[24], d[32], d[40], d[48], d[56]) - // constants scaled things up by 1<<12; let's bring them back - // down, but keep 2 extra bits of precision - x0 += 512; - x1 += 512; - x2 += 512; - x3 += 512; - v[0] = (x0 + t3) >> 10; - v[56] = (x0 - t3) >> 10; - v[8] = (x1 + t2) >> 10; - v[48] = (x1 - t2) >> 10; - v[16] = (x2 + t1) >> 10; - v[40] = (x2 - t1) >> 10; - v[24] = (x3 + t0) >> 10; - v[32] = (x3 - t0) >> 10; - } - } - - for (i = 0, v = val, o = out; i < 8; ++i, v += 8, o += out_stride) { - // no fast case since the first 1D IDCT spread components out - STBI__IDCT_1D(v[0], v[1], v[2], v[3], v[4], v[5], v[6], v[7]) - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - // so we want to round that, which means adding 0.5 * 1<<17, - // aka 65536. Also, we'll end up with -128 to 127 that we want - // to encode as 0..255 by adding 128, so we'll add that before the shift - x0 += 65536 + (128 << 17); - x1 += 65536 + (128 << 17); - x2 += 65536 + (128 << 17); - x3 += 65536 + (128 << 17); - // tried computing the shifts into temps, or'ing the temps to see - // if any were out of range, but that was slower - o[0] = stbi__clamp((x0 + t3) >> 17); - o[7] = stbi__clamp((x0 - t3) >> 17); - o[1] = stbi__clamp((x1 + t2) >> 17); - o[6] = stbi__clamp((x1 - t2) >> 17); - o[2] = stbi__clamp((x2 + t1) >> 17); - o[5] = stbi__clamp((x2 - t1) >> 17); - o[3] = stbi__clamp((x3 + t0) >> 17); - o[4] = stbi__clamp((x3 - t0) >> 17); - } -} - -#ifdef STBI_SSE2 -// sse2 integer IDCT. not the fastest possible implementation but it -// produces bit-identical results to the generic C version so it's -// fully "transparent". -static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) -{ - // This is constructed to match our regular (generic) integer IDCT exactly. - __m128i row0, row1, row2, row3, row4, row5, row6, row7; - __m128i tmp; - - // dot product constant: even elems=x, odd elems=y -#define dct_const(x, y) _mm_setr_epi16((x), (y), (x), (y), (x), (y), (x), (y)) - -// out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) -// out(1) = c1[even]*x + c1[odd]*y -#define dct_rot(out0, out1, x, y, c0, c1) \ - __m128i c0##lo = _mm_unpacklo_epi16((x), (y)); \ - __m128i c0##hi = _mm_unpackhi_epi16((x), (y)); \ - __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ - __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ - __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ - __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) - - // out = in << 12 (in 16-bit, out 32-bit) -#define dct_widen(out, in) \ - __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ - __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) - - // wide add -#define dct_wadd(out, a, b) \ - __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ - __m128i out##_h = _mm_add_epi32(a##_h, b##_h) - - // wide sub -#define dct_wsub(out, a, b) \ - __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ - __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) - - // butterfly a/b, add bias, then shift by "s" and pack -#define dct_bfly32o(out0, out1, a, b, bias, s) \ - { \ - __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ - __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ - dct_wadd(sum, abiased, b); \ - dct_wsub(dif, abiased, b); \ - out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ - out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ - } - - // 8-bit interleave step (for transposes) -#define dct_interleave8(a, b) \ - tmp = a; \ - a = _mm_unpacklo_epi8(a, b); \ - b = _mm_unpackhi_epi8(tmp, b) - - // 16-bit interleave step (for transposes) -#define dct_interleave16(a, b) \ - tmp = a; \ - a = _mm_unpacklo_epi16(a, b); \ - b = _mm_unpackhi_epi16(tmp, b) - -#define dct_pass(bias, shift) \ - { \ - /* even part */ \ - dct_rot(t2e, t3e, row2, row6, rot0_0, rot0_1); \ - __m128i sum04 = _mm_add_epi16(row0, row4); \ - __m128i dif04 = _mm_sub_epi16(row0, row4); \ - dct_widen(t0e, sum04); \ - dct_widen(t1e, dif04); \ - dct_wadd(x0, t0e, t3e); \ - dct_wsub(x3, t0e, t3e); \ - dct_wadd(x1, t1e, t2e); \ - dct_wsub(x2, t1e, t2e); \ - /* odd part */ \ - dct_rot(y0o, y2o, row7, row3, rot2_0, rot2_1); \ - dct_rot(y1o, y3o, row5, row1, rot3_0, rot3_1); \ - __m128i sum17 = _mm_add_epi16(row1, row7); \ - __m128i sum35 = _mm_add_epi16(row3, row5); \ - dct_rot(y4o, y5o, sum17, sum35, rot1_0, rot1_1); \ - dct_wadd(x4, y0o, y4o); \ - dct_wadd(x5, y1o, y5o); \ - dct_wadd(x6, y2o, y5o); \ - dct_wadd(x7, y3o, y4o); \ - dct_bfly32o(row0, row7, x0, x7, bias, shift); \ - dct_bfly32o(row1, row6, x1, x6, bias, shift); \ - dct_bfly32o(row2, row5, x2, x5, bias, shift); \ - dct_bfly32o(row3, row4, x3, x4, bias, shift); \ - } - - __m128i rot0_0 = - dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); - __m128i rot0_1 = - dct_const(stbi__f2f(0.5411961f) + stbi__f2f(0.765366865f), stbi__f2f(0.5411961f)); - __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), - stbi__f2f(1.175875602f)); - __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), - stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); - __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f(0.298631336f), - stbi__f2f(-1.961570560f)); - __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), - stbi__f2f(-1.961570560f) + stbi__f2f(3.072711026f)); - __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f(2.053119869f), - stbi__f2f(-0.390180644f)); - __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), - stbi__f2f(-0.390180644f) + stbi__f2f(1.501321110f)); - - // rounding biases in column/row passes, see stbi__idct_block for explanation. - __m128i bias_0 = _mm_set1_epi32(512); - __m128i bias_1 = _mm_set1_epi32(65536 + (128 << 17)); - - // load - row0 = _mm_load_si128((const __m128i *)(data + 0 * 8)); - row1 = _mm_load_si128((const __m128i *)(data + 1 * 8)); - row2 = _mm_load_si128((const __m128i *)(data + 2 * 8)); - row3 = _mm_load_si128((const __m128i *)(data + 3 * 8)); - row4 = _mm_load_si128((const __m128i *)(data + 4 * 8)); - row5 = _mm_load_si128((const __m128i *)(data + 5 * 8)); - row6 = _mm_load_si128((const __m128i *)(data + 6 * 8)); - row7 = _mm_load_si128((const __m128i *)(data + 7 * 8)); - - // column pass - dct_pass(bias_0, 10); - - { - // 16bit 8x8 transpose pass 1 - dct_interleave16(row0, row4); - dct_interleave16(row1, row5); - dct_interleave16(row2, row6); - dct_interleave16(row3, row7); - - // transpose pass 2 - dct_interleave16(row0, row2); - dct_interleave16(row1, row3); - dct_interleave16(row4, row6); - dct_interleave16(row5, row7); - - // transpose pass 3 - dct_interleave16(row0, row1); - dct_interleave16(row2, row3); - dct_interleave16(row4, row5); - dct_interleave16(row6, row7); - } - - // row pass - dct_pass(bias_1, 17); - - { - // pack - __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 - __m128i p1 = _mm_packus_epi16(row2, row3); - __m128i p2 = _mm_packus_epi16(row4, row5); - __m128i p3 = _mm_packus_epi16(row6, row7); - - // 8bit 8x8 transpose pass 1 - dct_interleave8(p0, p2); // a0e0a1e1... - dct_interleave8(p1, p3); // c0g0c1g1... - - // transpose pass 2 - dct_interleave8(p0, p1); // a0c0e0g0... - dct_interleave8(p2, p3); // b0d0f0h0... - - // transpose pass 3 - dct_interleave8(p0, p2); // a0b0c0d0... - dct_interleave8(p1, p3); // a4b4c4d4... - - // store - _mm_storel_epi64((__m128i *)out, p0); - out += out_stride; - _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p0, 0x4e)); - out += out_stride; - _mm_storel_epi64((__m128i *)out, p2); - out += out_stride; - _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p2, 0x4e)); - out += out_stride; - _mm_storel_epi64((__m128i *)out, p1); - out += out_stride; - _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p1, 0x4e)); - out += out_stride; - _mm_storel_epi64((__m128i *)out, p3); - out += out_stride; - _mm_storel_epi64((__m128i *)out, _mm_shuffle_epi32(p3, 0x4e)); - } - -#undef dct_const -#undef dct_rot -#undef dct_widen -#undef dct_wadd -#undef dct_wsub -#undef dct_bfly32o -#undef dct_interleave8 -#undef dct_interleave16 -#undef dct_pass -} - -#endif // STBI_SSE2 - -#ifdef STBI_NEON - -// NEON integer IDCT. should produce bit-identical -// results to the generic C version. -static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) -{ - int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; - - int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); - int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); - int16x4_t rot0_2 = vdup_n_s16(stbi__f2f(0.765366865f)); - int16x4_t rot1_0 = vdup_n_s16(stbi__f2f(1.175875602f)); - int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); - int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); - int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); - int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); - int16x4_t rot3_0 = vdup_n_s16(stbi__f2f(0.298631336f)); - int16x4_t rot3_1 = vdup_n_s16(stbi__f2f(2.053119869f)); - int16x4_t rot3_2 = vdup_n_s16(stbi__f2f(3.072711026f)); - int16x4_t rot3_3 = vdup_n_s16(stbi__f2f(1.501321110f)); - -#define dct_long_mul(out, inq, coeff) \ - int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ - int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) - -#define dct_long_mac(out, acc, inq, coeff) \ - int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ - int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) - -#define dct_widen(out, inq) \ - int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ - int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) - - // wide add -#define dct_wadd(out, a, b) \ - int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ - int32x4_t out##_h = vaddq_s32(a##_h, b##_h) - -// wide sub -#define dct_wsub(out, a, b) \ - int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ - int32x4_t out##_h = vsubq_s32(a##_h, b##_h) - -// butterfly a/b, then shift using "shiftop" by "s" and pack -#define dct_bfly32o(out0, out1, a, b, shiftop, s) \ - { \ - dct_wadd(sum, a, b); \ - dct_wsub(dif, a, b); \ - out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ - out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ - } - -#define dct_pass(shiftop, shift) \ - { \ - /* even part */ \ - int16x8_t sum26 = vaddq_s16(row2, row6); \ - dct_long_mul(p1e, sum26, rot0_0); \ - dct_long_mac(t2e, p1e, row6, rot0_1); \ - dct_long_mac(t3e, p1e, row2, rot0_2); \ - int16x8_t sum04 = vaddq_s16(row0, row4); \ - int16x8_t dif04 = vsubq_s16(row0, row4); \ - dct_widen(t0e, sum04); \ - dct_widen(t1e, dif04); \ - dct_wadd(x0, t0e, t3e); \ - dct_wsub(x3, t0e, t3e); \ - dct_wadd(x1, t1e, t2e); \ - dct_wsub(x2, t1e, t2e); \ - /* odd part */ \ - int16x8_t sum15 = vaddq_s16(row1, row5); \ - int16x8_t sum17 = vaddq_s16(row1, row7); \ - int16x8_t sum35 = vaddq_s16(row3, row5); \ - int16x8_t sum37 = vaddq_s16(row3, row7); \ - int16x8_t sumodd = vaddq_s16(sum17, sum35); \ - dct_long_mul(p5o, sumodd, rot1_0); \ - dct_long_mac(p1o, p5o, sum17, rot1_1); \ - dct_long_mac(p2o, p5o, sum35, rot1_2); \ - dct_long_mul(p3o, sum37, rot2_0); \ - dct_long_mul(p4o, sum15, rot2_1); \ - dct_wadd(sump13o, p1o, p3o); \ - dct_wadd(sump24o, p2o, p4o); \ - dct_wadd(sump23o, p2o, p3o); \ - dct_wadd(sump14o, p1o, p4o); \ - dct_long_mac(x4, sump13o, row7, rot3_0); \ - dct_long_mac(x5, sump24o, row5, rot3_1); \ - dct_long_mac(x6, sump23o, row3, rot3_2); \ - dct_long_mac(x7, sump14o, row1, rot3_3); \ - dct_bfly32o(row0, row7, x0, x7, shiftop, shift); \ - dct_bfly32o(row1, row6, x1, x6, shiftop, shift); \ - dct_bfly32o(row2, row5, x2, x5, shiftop, shift); \ - dct_bfly32o(row3, row4, x3, x4, shiftop, shift); \ - } - - // load - row0 = vld1q_s16(data + 0 * 8); - row1 = vld1q_s16(data + 1 * 8); - row2 = vld1q_s16(data + 2 * 8); - row3 = vld1q_s16(data + 3 * 8); - row4 = vld1q_s16(data + 4 * 8); - row5 = vld1q_s16(data + 5 * 8); - row6 = vld1q_s16(data + 6 * 8); - row7 = vld1q_s16(data + 7 * 8); - - // add DC bias - row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); - - // column pass - dct_pass(vrshrn_n_s32, 10); - - // 16bit 8x8 transpose - { - // these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. - // whether compilers actually get this is another story, sadly. -#define dct_trn16(x, y) \ - { \ - int16x8x2_t t = vtrnq_s16(x, y); \ - x = t.val[0]; \ - y = t.val[1]; \ - } -#define dct_trn32(x, y) \ - { \ - int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); \ - x = vreinterpretq_s16_s32(t.val[0]); \ - y = vreinterpretq_s16_s32(t.val[1]); \ - } -#define dct_trn64(x, y) \ - { \ - int16x8_t x0 = x; \ - int16x8_t y0 = y; \ - x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); \ - y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); \ - } - - // pass 1 - dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 - dct_trn16(row2, row3); - dct_trn16(row4, row5); - dct_trn16(row6, row7); - - // pass 2 - dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 - dct_trn32(row1, row3); - dct_trn32(row4, row6); - dct_trn32(row5, row7); - - // pass 3 - dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 - dct_trn64(row1, row5); - dct_trn64(row2, row6); - dct_trn64(row3, row7); - -#undef dct_trn16 -#undef dct_trn32 -#undef dct_trn64 - } - - // row pass - // vrshrn_n_s32 only supports shifts up to 16, we need - // 17. so do a non-rounding shift of 16 first then follow - // up with a rounding shift by 1. - dct_pass(vshrn_n_s32, 16); - - { - // pack and round - uint8x8_t p0 = vqrshrun_n_s16(row0, 1); - uint8x8_t p1 = vqrshrun_n_s16(row1, 1); - uint8x8_t p2 = vqrshrun_n_s16(row2, 1); - uint8x8_t p3 = vqrshrun_n_s16(row3, 1); - uint8x8_t p4 = vqrshrun_n_s16(row4, 1); - uint8x8_t p5 = vqrshrun_n_s16(row5, 1); - uint8x8_t p6 = vqrshrun_n_s16(row6, 1); - uint8x8_t p7 = vqrshrun_n_s16(row7, 1); - - // again, these can translate into one instruction, but often don't. -#define dct_trn8_8(x, y) \ - { \ - uint8x8x2_t t = vtrn_u8(x, y); \ - x = t.val[0]; \ - y = t.val[1]; \ - } -#define dct_trn8_16(x, y) \ - { \ - uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); \ - x = vreinterpret_u8_u16(t.val[0]); \ - y = vreinterpret_u8_u16(t.val[1]); \ - } -#define dct_trn8_32(x, y) \ - { \ - uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); \ - x = vreinterpret_u8_u32(t.val[0]); \ - y = vreinterpret_u8_u32(t.val[1]); \ - } - - // sadly can't use interleaved stores here since we only write - // 8 bytes to each scan line! - - // 8x8 8-bit transpose pass 1 - dct_trn8_8(p0, p1); - dct_trn8_8(p2, p3); - dct_trn8_8(p4, p5); - dct_trn8_8(p6, p7); - - // pass 2 - dct_trn8_16(p0, p2); - dct_trn8_16(p1, p3); - dct_trn8_16(p4, p6); - dct_trn8_16(p5, p7); - - // pass 3 - dct_trn8_32(p0, p4); - dct_trn8_32(p1, p5); - dct_trn8_32(p2, p6); - dct_trn8_32(p3, p7); - - // store - vst1_u8(out, p0); - out += out_stride; - vst1_u8(out, p1); - out += out_stride; - vst1_u8(out, p2); - out += out_stride; - vst1_u8(out, p3); - out += out_stride; - vst1_u8(out, p4); - out += out_stride; - vst1_u8(out, p5); - out += out_stride; - vst1_u8(out, p6); - out += out_stride; - vst1_u8(out, p7); - -#undef dct_trn8_8 -#undef dct_trn8_16 -#undef dct_trn8_32 - } - -#undef dct_long_mul -#undef dct_long_mac -#undef dct_widen -#undef dct_wadd -#undef dct_wsub -#undef dct_bfly32o -#undef dct_pass -} - -#endif // STBI_NEON - -#define STBI__MARKER_none 0xff -// if there's a pending marker from the entropy stream, return that -// otherwise, fetch from the stream and get a marker. if there's no -// marker, return 0xff, which is never a valid marker value -static stbi_uc stbi__get_marker(stbi__jpeg *j) -{ - stbi_uc x; - if (j->marker != STBI__MARKER_none) { - x = j->marker; - j->marker = STBI__MARKER_none; - return x; - } - x = stbi__get8(j->s); - if (x != 0xff) - return STBI__MARKER_none; - while (x == 0xff) - x = stbi__get8(j->s); // consume repeated 0xff fill bytes - return x; -} - -// in each scan, we'll have scan_n components, and the order -// of the components is specified by order[] -#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) - -// after a restart interval, stbi__jpeg_reset the entropy decoder and -// the dc prediction -static void stbi__jpeg_reset(stbi__jpeg *j) -{ - j->code_bits = 0; - j->code_buffer = 0; - j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = - j->img_comp[3].dc_pred = 0; - j->marker = STBI__MARKER_none; - j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; - j->eob_run = 0; - // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, - // since we don't even allow 1<<30 pixels -} - -static int stbi__parse_entropy_coded_data(stbi__jpeg *z) -{ - stbi__jpeg_reset(z); - if (!z->progressive) { - if (z->scan_n == 1) { - int i, j; - STBI_SIMD_ALIGN(short, data[64]); - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x + 7) >> 3; - int h = (z->img_comp[n].y + 7) >> 3; - for (j = 0; j < h; ++j) { - for (i = 0; i < w; ++i) { - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block( - z, data, z->huff_dc + z->img_comp[n].hd, - z->huff_ac + ha, z->fast_ac[ha], n, - z->dequant[z->img_comp[n].tq])) - return 0; - z->idct_block_kernel(z->img_comp[n].data + - z->img_comp[n].w2 * j * 8 + - i * 8, - z->img_comp[n].w2, data); - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) - stbi__grow_buffer_unsafe(z); - // if it's NOT a restart, then just bail, so we get corrupt data - // rather than no data - if (!STBI__RESTART(z->marker)) - return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } else { // interleaved - int i, j, k, x, y; - STBI_SIMD_ALIGN(short, data[64]); - for (j = 0; j < z->img_mcu_y; ++j) { - for (i = 0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k = 0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y = 0; y < z->img_comp[n].v; ++y) { - for (x = 0; x < z->img_comp[n].h; ++x) { - int x2 = - (i * z->img_comp[n].h + x) * - 8; - int y2 = - (j * z->img_comp[n].v + y) * - 8; - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block( - z, data, - z->huff_dc + - z->img_comp[n] - .hd, - z->huff_ac + ha, - z->fast_ac[ha], n, - z->dequant[z->img_comp[n] - .tq])) - return 0; - z->idct_block_kernel( - z->img_comp[n].data + - z->img_comp[n].w2 * - y2 + - x2, - z->img_comp[n].w2, data); - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) - stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) - return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } - } else { - if (z->scan_n == 1) { - int i, j; - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x + 7) >> 3; - int h = (z->img_comp[n].y + 7) >> 3; - for (j = 0; j < h; ++j) { - for (i = 0; i < w; ++i) { - short *data = z->img_comp[n].coeff + - 64 * (i + j * z->img_comp[n].coeff_w); - if (z->spec_start == 0) { - if (!stbi__jpeg_decode_block_prog_dc( - z, data, &z->huff_dc[z->img_comp[n].hd], - n)) - return 0; - } else { - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block_prog_ac( - z, data, &z->huff_ac[ha], - z->fast_ac[ha])) - return 0; - } - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) - stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) - return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } else { // interleaved - int i, j, k, x, y; - for (j = 0; j < z->img_mcu_y; ++j) { - for (i = 0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k = 0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y = 0; y < z->img_comp[n].v; ++y) { - for (x = 0; x < z->img_comp[n].h; ++x) { - int x2 = (i * z->img_comp[n].h + x); - int y2 = (j * z->img_comp[n].v + y); - short *data = - z->img_comp[n].coeff + - 64 * (x2 + - y2 * z->img_comp[n] - .coeff_w); - if (!stbi__jpeg_decode_block_prog_dc( - z, data, - &z->huff_dc[z->img_comp[n] - .hd], - n)) - return 0; - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) - stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) - return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } - } -} - -static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) -{ - int i; - for (i = 0; i < 64; ++i) - data[i] *= dequant[i]; -} - -static void stbi__jpeg_finish(stbi__jpeg *z) -{ - if (z->progressive) { - // dequantize and idct the data - int i, j, n; - for (n = 0; n < z->s->img_n; ++n) { - int w = (z->img_comp[n].x + 7) >> 3; - int h = (z->img_comp[n].y + 7) >> 3; - for (j = 0; j < h; ++j) { - for (i = 0; i < w; ++i) { - short *data = z->img_comp[n].coeff + - 64 * (i + j * z->img_comp[n].coeff_w); - stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); - z->idct_block_kernel(z->img_comp[n].data + - z->img_comp[n].w2 * j * 8 + - i * 8, - z->img_comp[n].w2, data); - } - } - } - } -} - -static int stbi__process_marker(stbi__jpeg *z, int m) -{ - int L; - switch (m) { - case STBI__MARKER_none: // no marker found - return stbi__err("expected marker", "Corrupt JPEG"); - - case 0xDD: // DRI - specify restart interval - if (stbi__get16be(z->s) != 4) - return stbi__err("bad DRI len", "Corrupt JPEG"); - z->restart_interval = stbi__get16be(z->s); - return 1; - - case 0xDB: // DQT - define quantization table - L = stbi__get16be(z->s) - 2; - while (L > 0) { - int q = stbi__get8(z->s); - int p = q >> 4, sixteen = (p != 0); - int t = q & 15, i; - if (p != 0 && p != 1) - return stbi__err("bad DQT type", "Corrupt JPEG"); - if (t > 3) - return stbi__err("bad DQT table", "Corrupt JPEG"); - - for (i = 0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = - (stbi__uint16)(sixteen ? stbi__get16be(z->s) : - stbi__get8(z->s)); - L -= (sixteen ? 129 : 65); - } - return L == 0; - - case 0xC4: // DHT - define huffman table - L = stbi__get16be(z->s) - 2; - while (L > 0) { - stbi_uc *v; - int sizes[16], i, n = 0; - int q = stbi__get8(z->s); - int tc = q >> 4; - int th = q & 15; - if (tc > 1 || th > 3) - return stbi__err("bad DHT header", "Corrupt JPEG"); - for (i = 0; i < 16; ++i) { - sizes[i] = stbi__get8(z->s); - n += sizes[i]; - } - if (n > 256) - return stbi__err( - "bad DHT header", - "Corrupt JPEG"); // Loop over i < n would write past end of values! - L -= 17; - if (tc == 0) { - if (!stbi__build_huffman(z->huff_dc + th, sizes)) - return 0; - v = z->huff_dc[th].values; - } else { - if (!stbi__build_huffman(z->huff_ac + th, sizes)) - return 0; - v = z->huff_ac[th].values; - } - for (i = 0; i < n; ++i) - v[i] = stbi__get8(z->s); - if (tc != 0) - stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); - L -= n; - } - return L == 0; - } - - // check for comment block or APP blocks - if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - L = stbi__get16be(z->s); - if (L < 2) { - if (m == 0xFE) - return stbi__err("bad COM len", "Corrupt JPEG"); - else - return stbi__err("bad APP len", "Corrupt JPEG"); - } - L -= 2; - - if (m == 0xE0 && L >= 5) { // JFIF APP0 segment - static const unsigned char tag[5] = { 'J', 'F', 'I', 'F', '\0' }; - int ok = 1; - int i; - for (i = 0; i < 5; ++i) - if (stbi__get8(z->s) != tag[i]) - ok = 0; - L -= 5; - if (ok) - z->jfif = 1; - } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment - static const unsigned char tag[6] = { 'A', 'd', 'o', 'b', 'e', '\0' }; - int ok = 1; - int i; - for (i = 0; i < 6; ++i) - if (stbi__get8(z->s) != tag[i]) - ok = 0; - L -= 6; - if (ok) { - stbi__get8(z->s); // version - stbi__get16be(z->s); // flags0 - stbi__get16be(z->s); // flags1 - z->app14_color_transform = stbi__get8(z->s); // color transform - L -= 6; - } - } - - stbi__skip(z->s, L); - return 1; - } - - return stbi__err("unknown marker", "Corrupt JPEG"); -} - -// after we see SOS -static int stbi__process_scan_header(stbi__jpeg *z) -{ - int i; - int Ls = stbi__get16be(z->s); - z->scan_n = stbi__get8(z->s); - if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int)z->s->img_n) - return stbi__err("bad SOS component count", "Corrupt JPEG"); - if (Ls != 6 + 2 * z->scan_n) - return stbi__err("bad SOS len", "Corrupt JPEG"); - for (i = 0; i < z->scan_n; ++i) { - int id = stbi__get8(z->s), which; - int q = stbi__get8(z->s); - for (which = 0; which < z->s->img_n; ++which) - if (z->img_comp[which].id == id) - break; - if (which == z->s->img_n) - return 0; // no match - z->img_comp[which].hd = q >> 4; - if (z->img_comp[which].hd > 3) - return stbi__err("bad DC huff", "Corrupt JPEG"); - z->img_comp[which].ha = q & 15; - if (z->img_comp[which].ha > 3) - return stbi__err("bad AC huff", "Corrupt JPEG"); - z->order[i] = which; - } - - { - int aa; - z->spec_start = stbi__get8(z->s); - z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 - aa = stbi__get8(z->s); - z->succ_high = (aa >> 4); - z->succ_low = (aa & 15); - if (z->progressive) { - if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || - z->succ_high > 13 || z->succ_low > 13) - return stbi__err("bad SOS", "Corrupt JPEG"); - } else { - if (z->spec_start != 0) - return stbi__err("bad SOS", "Corrupt JPEG"); - if (z->succ_high != 0 || z->succ_low != 0) - return stbi__err("bad SOS", "Corrupt JPEG"); - z->spec_end = 63; - } - } - - return 1; -} - -static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) -{ - int i; - for (i = 0; i < ncomp; ++i) { - if (z->img_comp[i].raw_data) { - STBI_FREE(z->img_comp[i].raw_data); - z->img_comp[i].raw_data = NULL; - z->img_comp[i].data = NULL; - } - if (z->img_comp[i].raw_coeff) { - STBI_FREE(z->img_comp[i].raw_coeff); - z->img_comp[i].raw_coeff = 0; - z->img_comp[i].coeff = 0; - } - if (z->img_comp[i].linebuf) { - STBI_FREE(z->img_comp[i].linebuf); - z->img_comp[i].linebuf = NULL; - } - } - return why; -} - -static int stbi__process_frame_header(stbi__jpeg *z, int scan) -{ - stbi__context *s = z->s; - int Lf, p, i, q, h_max = 1, v_max = 1, c; - Lf = stbi__get16be(s); - if (Lf < 11) - return stbi__err("bad SOF len", "Corrupt JPEG"); // JPEG - p = stbi__get8(s); - if (p != 8) - return stbi__err("only 8-bit", - "JPEG format not supported: 8-bit only"); // JPEG baseline - s->img_y = stbi__get16be(s); - if (s->img_y == 0) - return stbi__err( - "no header height", - "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG - s->img_x = stbi__get16be(s); - if (s->img_x == 0) - return stbi__err("0 width", "Corrupt JPEG"); // JPEG requires - if (s->img_y > STBI_MAX_DIMENSIONS) - return stbi__err("too large", "Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) - return stbi__err("too large", "Very large image (corrupt?)"); - c = stbi__get8(s); - if (c != 3 && c != 1 && c != 4) - return stbi__err("bad component count", "Corrupt JPEG"); - s->img_n = c; - for (i = 0; i < c; ++i) { - z->img_comp[i].data = NULL; - z->img_comp[i].linebuf = NULL; - } - - if (Lf != 8 + 3 * s->img_n) - return stbi__err("bad SOF len", "Corrupt JPEG"); - - z->rgb = 0; - for (i = 0; i < s->img_n; ++i) { - static const unsigned char rgb[3] = { 'R', 'G', 'B' }; - z->img_comp[i].id = stbi__get8(s); - if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) - ++z->rgb; - q = stbi__get8(s); - z->img_comp[i].h = (q >> 4); - if (!z->img_comp[i].h || z->img_comp[i].h > 4) - return stbi__err("bad H", "Corrupt JPEG"); - z->img_comp[i].v = q & 15; - if (!z->img_comp[i].v || z->img_comp[i].v > 4) - return stbi__err("bad V", "Corrupt JPEG"); - z->img_comp[i].tq = stbi__get8(s); - if (z->img_comp[i].tq > 3) - return stbi__err("bad TQ", "Corrupt JPEG"); - } - - if (scan != STBI__SCAN_load) - return 1; - - if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) - return stbi__err("too large", "Image too large to decode"); - - for (i = 0; i < s->img_n; ++i) { - if (z->img_comp[i].h > h_max) - h_max = z->img_comp[i].h; - if (z->img_comp[i].v > v_max) - v_max = z->img_comp[i].v; - } - - // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios - // and I've never seen a non-corrupted JPEG file actually use them - for (i = 0; i < s->img_n; ++i) { - if (h_max % z->img_comp[i].h != 0) - return stbi__err("bad H", "Corrupt JPEG"); - if (v_max % z->img_comp[i].v != 0) - return stbi__err("bad V", "Corrupt JPEG"); - } - - // compute interleaved mcu info - z->img_h_max = h_max; - z->img_v_max = v_max; - z->img_mcu_w = h_max * 8; - z->img_mcu_h = v_max * 8; - // these sizes can't be more than 17 bits - z->img_mcu_x = (s->img_x + z->img_mcu_w - 1) / z->img_mcu_w; - z->img_mcu_y = (s->img_y + z->img_mcu_h - 1) / z->img_mcu_h; - - for (i = 0; i < s->img_n; ++i) { - // number of effective pixels (e.g. for non-interleaved MCU) - z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max - 1) / h_max; - z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max - 1) / v_max; - // to simplify generation, we'll allocate enough memory to decode - // the bogus oversized data from using interleaved MCUs and their - // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't - // discard the extra data until colorspace conversion - // - // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) - // so these muls can't overflow with 32-bit ints (which we require) - z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; - z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; - z->img_comp[i].coeff = 0; - z->img_comp[i].raw_coeff = 0; - z->img_comp[i].linebuf = NULL; - z->img_comp[i].raw_data = - stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); - if (z->img_comp[i].raw_data == NULL) - return stbi__free_jpeg_components(z, i + 1, - stbi__err("outofmem", "Out of memory")); - // align blocks for idct using mmx/sse - z->img_comp[i].data = (stbi_uc *)(((size_t)z->img_comp[i].raw_data + 15) & ~15); - if (z->progressive) { - // w2, h2 are multiples of 8 (see above) - z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; - z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; - z->img_comp[i].raw_coeff = stbi__malloc_mad3( - z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); - if (z->img_comp[i].raw_coeff == NULL) - return stbi__free_jpeg_components( - z, i + 1, stbi__err("outofmem", "Out of memory")); - z->img_comp[i].coeff = - (short *)(((size_t)z->img_comp[i].raw_coeff + 15) & ~15); - } - } - - return 1; -} - -// use comparisons since in some cases we handle more than one case (e.g. SOF) -#define stbi__DNL(x) ((x) == 0xdc) -#define stbi__SOI(x) ((x) == 0xd8) -#define stbi__EOI(x) ((x) == 0xd9) -#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) -#define stbi__SOS(x) ((x) == 0xda) - -#define stbi__SOF_progressive(x) ((x) == 0xc2) - -static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) -{ - int m; - z->jfif = 0; - z->app14_color_transform = -1; // valid values are 0,1,2 - z->marker = STBI__MARKER_none; // initialize cached marker to empty - m = stbi__get_marker(z); - if (!stbi__SOI(m)) - return stbi__err("no SOI", "Corrupt JPEG"); - if (scan == STBI__SCAN_type) - return 1; - m = stbi__get_marker(z); - while (!stbi__SOF(m)) { - if (!stbi__process_marker(z, m)) - return 0; - m = stbi__get_marker(z); - while (m == STBI__MARKER_none) { - // some files have extra padding after their blocks, so ok, we'll scan - if (stbi__at_eof(z->s)) - return stbi__err("no SOF", "Corrupt JPEG"); - m = stbi__get_marker(z); - } - } - z->progressive = stbi__SOF_progressive(m); - if (!stbi__process_frame_header(z, scan)) - return 0; - return 1; -} - -static int stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) -{ - // some JPEGs have junk at end, skip over it but if we find what looks - // like a valid marker, resume there - while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - while (x == 255) { // might be a marker - if (stbi__at_eof(j->s)) - return STBI__MARKER_none; - x = stbi__get8(j->s); - if (x != 0x00 && x != 0xff) { - // not a stuffed zero or lead-in to another marker, looks - // like an actual marker, return it - return x; - } - // stuffed zero has x=0 now which ends the loop, meaning we go - // back to regular scan loop. - // repeated 0xff keeps trying to read the next byte of the marker. - } - } - return STBI__MARKER_none; -} - -// decode image to YCbCr format -static int stbi__decode_jpeg_image(stbi__jpeg *j) -{ - int m; - for (m = 0; m < 4; m++) { - j->img_comp[m].raw_data = NULL; - j->img_comp[m].raw_coeff = NULL; - } - j->restart_interval = 0; - if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) - return 0; - m = stbi__get_marker(j); - while (!stbi__EOI(m)) { - if (stbi__SOS(m)) { - if (!stbi__process_scan_header(j)) - return 0; - if (!stbi__parse_entropy_coded_data(j)) - return 0; - if (j->marker == STBI__MARKER_none) { - j->marker = stbi__skip_jpeg_junk_at_end(j); - // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 - } - m = stbi__get_marker(j); - if (STBI__RESTART(m)) - m = stbi__get_marker(j); - } else if (stbi__DNL(m)) { - int Ld = stbi__get16be(j->s); - stbi__uint32 NL = stbi__get16be(j->s); - if (Ld != 4) - return stbi__err("bad DNL len", "Corrupt JPEG"); - if (NL != j->s->img_y) - return stbi__err("bad DNL height", "Corrupt JPEG"); - m = stbi__get_marker(j); - } else { - if (!stbi__process_marker(j, m)) - return 1; - m = stbi__get_marker(j); - } - } - if (j->progressive) - stbi__jpeg_finish(j); - return 1; -} - -// static jfif-centered resampling (across block boundaries) - -typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, int w, int hs); - -#define stbi__div4(x) ((stbi_uc)((x) >> 2)) - -static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - STBI_NOTUSED(out); - STBI_NOTUSED(in_far); - STBI_NOTUSED(w); - STBI_NOTUSED(hs); - return in_near; -} - -static stbi_uc *stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, - int hs) -{ - // need to generate two samples vertically for every one in input - int i; - STBI_NOTUSED(hs); - for (i = 0; i < w; ++i) - out[i] = stbi__div4(3 * in_near[i] + in_far[i] + 2); - return out; -} - -static stbi_uc *stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, - int hs) -{ - // need to generate two samples horizontally for every one in input - int i; - stbi_uc *input = in_near; - - if (w == 1) { - // if only one sample, can't do any interpolation - out[0] = out[1] = input[0]; - return out; - } - - out[0] = input[0]; - out[1] = stbi__div4(input[0] * 3 + input[1] + 2); - for (i = 1; i < w - 1; ++i) { - int n = 3 * input[i] + 2; - out[i * 2 + 0] = stbi__div4(n + input[i - 1]); - out[i * 2 + 1] = stbi__div4(n + input[i + 1]); - } - out[i * 2 + 0] = stbi__div4(input[w - 2] * 3 + input[w - 1] + 2); - out[i * 2 + 1] = input[w - 1]; - - STBI_NOTUSED(in_far); - STBI_NOTUSED(hs); - - return out; -} - -#define stbi__div16(x) ((stbi_uc)((x) >> 4)) - -static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, - int hs) -{ - // need to generate 2x2 samples for every one in input - int i, t0, t1; - if (w == 1) { - out[0] = out[1] = stbi__div4(3 * in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3 * in_near[0] + in_far[0]; - out[0] = stbi__div4(t1 + 2); - for (i = 1; i < w; ++i) { - t0 = t1; - t1 = 3 * in_near[i] + in_far[i]; - out[i * 2 - 1] = stbi__div16(3 * t0 + t1 + 8); - out[i * 2] = stbi__div16(3 * t1 + t0 + 8); - } - out[w * 2 - 1] = stbi__div4(t1 + 2); - - STBI_NOTUSED(hs); - - return out; -} - -#if defined(STBI_SSE2) || defined(STBI_NEON) -static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, - int hs) -{ - // need to generate 2x2 samples for every one in input - int i = 0, t0, t1; - - if (w == 1) { - out[0] = out[1] = stbi__div4(3 * in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3 * in_near[0] + in_far[0]; - // process groups of 8 pixels for as long as we can. - // note we can't handle the last pixel in a row in this loop - // because we need to handle the filter boundary conditions. - for (; i < ((w - 1) & ~7); i += 8) { -#if defined(STBI_SSE2) - // load and perform the vertical filtering pass - // this uses 3*x + y = 4*x + (y - x) - __m128i zero = _mm_setzero_si128(); - __m128i farb = _mm_loadl_epi64((__m128i *)(in_far + i)); - __m128i nearb = _mm_loadl_epi64((__m128i *)(in_near + i)); - __m128i farw = _mm_unpacklo_epi8(farb, zero); - __m128i nearw = _mm_unpacklo_epi8(nearb, zero); - __m128i diff = _mm_sub_epi16(farw, nearw); - __m128i nears = _mm_slli_epi16(nearw, 2); - __m128i curr = _mm_add_epi16(nears, diff); // current row - - // horizontal filter works the same based on shifted vers of current - // row. "prev" is current row shifted right by 1 pixel; we need to - // insert the previous pixel value (from t1). - // "next" is current row shifted left by 1 pixel, with first pixel - // of next block of 8 pixels added in. - __m128i prv0 = _mm_slli_si128(curr, 2); - __m128i nxt0 = _mm_srli_si128(curr, 2); - __m128i prev = _mm_insert_epi16(prv0, t1, 0); - __m128i next = _mm_insert_epi16(nxt0, 3 * in_near[i + 8] + in_far[i + 8], 7); - - // horizontal filter, polyphase implementation since it's convenient: - // even pixels = 3*cur + prev = cur*4 + (prev - cur) - // odd pixels = 3*cur + next = cur*4 + (next - cur) - // note the shared term. - __m128i bias = _mm_set1_epi16(8); - __m128i curs = _mm_slli_epi16(curr, 2); - __m128i prvd = _mm_sub_epi16(prev, curr); - __m128i nxtd = _mm_sub_epi16(next, curr); - __m128i curb = _mm_add_epi16(curs, bias); - __m128i even = _mm_add_epi16(prvd, curb); - __m128i odd = _mm_add_epi16(nxtd, curb); - - // interleave even and odd pixels, then undo scaling. - __m128i int0 = _mm_unpacklo_epi16(even, odd); - __m128i int1 = _mm_unpackhi_epi16(even, odd); - __m128i de0 = _mm_srli_epi16(int0, 4); - __m128i de1 = _mm_srli_epi16(int1, 4); - - // pack and write output - __m128i outv = _mm_packus_epi16(de0, de1); - _mm_storeu_si128((__m128i *)(out + i * 2), outv); -#elif defined(STBI_NEON) - // load and perform the vertical filtering pass - // this uses 3*x + y = 4*x + (y - x) - uint8x8_t farb = vld1_u8(in_far + i); - uint8x8_t nearb = vld1_u8(in_near + i); - int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); - int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); - int16x8_t curr = vaddq_s16(nears, diff); // current row - - // horizontal filter works the same based on shifted vers of current - // row. "prev" is current row shifted right by 1 pixel; we need to - // insert the previous pixel value (from t1). - // "next" is current row shifted left by 1 pixel, with first pixel - // of next block of 8 pixels added in. - int16x8_t prv0 = vextq_s16(curr, curr, 7); - int16x8_t nxt0 = vextq_s16(curr, curr, 1); - int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); - int16x8_t next = vsetq_lane_s16(3 * in_near[i + 8] + in_far[i + 8], nxt0, 7); - - // horizontal filter, polyphase implementation since it's convenient: - // even pixels = 3*cur + prev = cur*4 + (prev - cur) - // odd pixels = 3*cur + next = cur*4 + (next - cur) - // note the shared term. - int16x8_t curs = vshlq_n_s16(curr, 2); - int16x8_t prvd = vsubq_s16(prev, curr); - int16x8_t nxtd = vsubq_s16(next, curr); - int16x8_t even = vaddq_s16(curs, prvd); - int16x8_t odd = vaddq_s16(curs, nxtd); - - // undo scaling and round, then store with even/odd phases interleaved - uint8x8x2_t o; - o.val[0] = vqrshrun_n_s16(even, 4); - o.val[1] = vqrshrun_n_s16(odd, 4); - vst2_u8(out + i * 2, o); -#endif - - // "previous" value for next iter - t1 = 3 * in_near[i + 7] + in_far[i + 7]; - } - - t0 = t1; - t1 = 3 * in_near[i] + in_far[i]; - out[i * 2] = stbi__div16(3 * t1 + t0 + 8); - - for (++i; i < w; ++i) { - t0 = t1; - t1 = 3 * in_near[i] + in_far[i]; - out[i * 2 - 1] = stbi__div16(3 * t0 + t1 + 8); - out[i * 2] = stbi__div16(3 * t1 + t0 + 8); - } - out[w * 2 - 1] = stbi__div4(t1 + 2); - - STBI_NOTUSED(hs); - - return out; -} -#endif - -static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, - int hs) -{ - // resample with nearest-neighbor - int i, j; - STBI_NOTUSED(in_far); - for (i = 0; i < w; ++i) - for (j = 0; j < hs; ++j) - out[i * hs + j] = in_near[i]; - return out; -} - -// this is a reduced-precision calculation of YCbCr-to-RGB introduced -// to make sure the code produces the same results in both SIMD and scalar -#define stbi__float2fixed(x) (((int)((x) * 4096.0f + 0.5f)) << 8) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, - const stbi_uc *pcr, int count, int step) -{ - int i; - for (i = 0; i < count; ++i) { - int y_fixed = (y[i] << 20) + (1 << 19); // rounding - int r, g, b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr * stbi__float2fixed(1.40200f); - g = y_fixed + (cr * -stbi__float2fixed(0.71414f)) + - ((cb * -stbi__float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb * stbi__float2fixed(1.77200f); - r >>= 20; - g >>= 20; - b >>= 20; - if ((unsigned)r > 255) { - if (r < 0) - r = 0; - else - r = 255; - } - if ((unsigned)g > 255) { - if (g < 0) - g = 0; - else - g = 255; - } - if ((unsigned)b > 255) { - if (b < 0) - b = 0; - else - b = 255; - } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} - -#if defined(STBI_SSE2) || defined(STBI_NEON) -static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, - stbi_uc const *pcr, int count, int step) -{ - int i = 0; - -#ifdef STBI_SSE2 - // step == 3 is pretty ugly on the final interleave, and i'm not convinced - // it's useful in practice (you wouldn't use it for textures, for example). - // so just accelerate step == 4 case. - if (step == 4) { - // this is a fairly straightforward implementation and not super-optimized. - __m128i signflip = _mm_set1_epi8(-0x80); - __m128i cr_const0 = _mm_set1_epi16((short)(1.40200f * 4096.0f + 0.5f)); - __m128i cr_const1 = _mm_set1_epi16(-(short)(0.71414f * 4096.0f + 0.5f)); - __m128i cb_const0 = _mm_set1_epi16(-(short)(0.34414f * 4096.0f + 0.5f)); - __m128i cb_const1 = _mm_set1_epi16((short)(1.77200f * 4096.0f + 0.5f)); - __m128i y_bias = _mm_set1_epi8((char)(unsigned char)128); - __m128i xw = _mm_set1_epi16(255); // alpha channel - - for (; i + 7 < count; i += 8) { - // load - __m128i y_bytes = _mm_loadl_epi64((__m128i *)(y + i)); - __m128i cr_bytes = _mm_loadl_epi64((__m128i *)(pcr + i)); - __m128i cb_bytes = _mm_loadl_epi64((__m128i *)(pcb + i)); - __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 - __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 - - // unpack to short (and left-shift cr, cb by 8) - __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); - __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); - __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); - - // color transform - __m128i yws = _mm_srli_epi16(yw, 4); - __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); - __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); - __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); - __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); - __m128i rws = _mm_add_epi16(cr0, yws); - __m128i gwt = _mm_add_epi16(cb0, yws); - __m128i bws = _mm_add_epi16(yws, cb1); - __m128i gws = _mm_add_epi16(gwt, cr1); - - // descale - __m128i rw = _mm_srai_epi16(rws, 4); - __m128i bw = _mm_srai_epi16(bws, 4); - __m128i gw = _mm_srai_epi16(gws, 4); - - // back to byte, set up for transpose - __m128i brb = _mm_packus_epi16(rw, bw); - __m128i gxb = _mm_packus_epi16(gw, xw); - - // transpose to interleave channels - __m128i t0 = _mm_unpacklo_epi8(brb, gxb); - __m128i t1 = _mm_unpackhi_epi8(brb, gxb); - __m128i o0 = _mm_unpacklo_epi16(t0, t1); - __m128i o1 = _mm_unpackhi_epi16(t0, t1); - - // store - _mm_storeu_si128((__m128i *)(out + 0), o0); - _mm_storeu_si128((__m128i *)(out + 16), o1); - out += 32; - } - } -#endif - -#ifdef STBI_NEON - // in this version, step=3 support would be easy to add. but is there demand? - if (step == 4) { - // this is a fairly straightforward implementation and not super-optimized. - uint8x8_t signflip = vdup_n_u8(0x80); - int16x8_t cr_const0 = vdupq_n_s16((short)(1.40200f * 4096.0f + 0.5f)); - int16x8_t cr_const1 = vdupq_n_s16(-(short)(0.71414f * 4096.0f + 0.5f)); - int16x8_t cb_const0 = vdupq_n_s16(-(short)(0.34414f * 4096.0f + 0.5f)); - int16x8_t cb_const1 = vdupq_n_s16((short)(1.77200f * 4096.0f + 0.5f)); - - for (; i + 7 < count; i += 8) { - // load - uint8x8_t y_bytes = vld1_u8(y + i); - uint8x8_t cr_bytes = vld1_u8(pcr + i); - uint8x8_t cb_bytes = vld1_u8(pcb + i); - int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); - int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); - - // expand to s16 - int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); - int16x8_t crw = vshll_n_s8(cr_biased, 7); - int16x8_t cbw = vshll_n_s8(cb_biased, 7); - - // color transform - int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); - int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); - int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); - int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); - int16x8_t rws = vaddq_s16(yws, cr0); - int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); - int16x8_t bws = vaddq_s16(yws, cb1); - - // undo scaling, round, convert to byte - uint8x8x4_t o; - o.val[0] = vqrshrun_n_s16(rws, 4); - o.val[1] = vqrshrun_n_s16(gws, 4); - o.val[2] = vqrshrun_n_s16(bws, 4); - o.val[3] = vdup_n_u8(255); - - // store, interleaving r/g/b/a - vst4_u8(out, o); - out += 8 * 4; - } - } -#endif - - for (; i < count; ++i) { - int y_fixed = (y[i] << 20) + (1 << 19); // rounding - int r, g, b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr * stbi__float2fixed(1.40200f); - g = y_fixed + cr * -stbi__float2fixed(0.71414f) + - ((cb * -stbi__float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb * stbi__float2fixed(1.77200f); - r >>= 20; - g >>= 20; - b >>= 20; - if ((unsigned)r > 255) { - if (r < 0) - r = 0; - else - r = 255; - } - if ((unsigned)g > 255) { - if (g < 0) - g = 0; - else - g = 255; - } - if ((unsigned)b > 255) { - if (b < 0) - b = 0; - else - b = 255; - } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#endif - -// set up the kernels -static void stbi__setup_jpeg(stbi__jpeg *j) -{ - j->idct_block_kernel = stbi__idct_block; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; - -#ifdef STBI_SSE2 - if (stbi__sse2_available()) { - j->idct_block_kernel = stbi__idct_simd; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; - } -#endif - -#ifdef STBI_NEON - j->idct_block_kernel = stbi__idct_simd; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; -#endif -} - -// clean up the temporary component buffers -static void stbi__cleanup_jpeg(stbi__jpeg *j) -{ - stbi__free_jpeg_components(j, j->s->img_n, 0); -} - -typedef struct { - resample_row_func resample; - stbi_uc *line0, *line1; - int hs, vs; // expansion factor in each axis - int w_lores; // horizontal pixels pre-expansion - int ystep; // how far through vertical expansion we are - int ypos; // which pre-expansion row we're on -} stbi__resample; - -// fast 0..255 * 0..255 => 0..255 rounded multiplication -static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) -{ - unsigned int t = x * y + 128; - return (stbi_uc)((t + (t >> 8)) >> 8); -} - -static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) -{ - int n, decode_n, is_rgb; - z->s->img_n = 0; // make stbi__cleanup_jpeg safe - - // validate req_comp - if (req_comp < 0 || req_comp > 4) - return stbi__errpuc("bad req_comp", "Internal error"); - - // load a jpeg image from whichever source, but leave in YCbCr format - if (!stbi__decode_jpeg_image(z)) { - stbi__cleanup_jpeg(z); - return NULL; - } - - // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; - - is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); - - if (z->s->img_n == 3 && n < 3 && !is_rgb) - decode_n = 1; - else - decode_n = z->s->img_n; - - // nothing to do if no components requested; check this now to avoid - // accessing uninitialized coutput[0] later - if (decode_n <= 0) { - stbi__cleanup_jpeg(z); - return NULL; - } - - // resample and color-convert - { - int k; - unsigned int i, j; - stbi_uc *output; - stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; - - stbi__resample res_comp[4]; - - for (k = 0; k < decode_n; ++k) { - stbi__resample *r = &res_comp[k]; - - // allocate line buffer big enough for upsampling off the edges - // with upsample factor of 4 - z->img_comp[k].linebuf = (stbi_uc *)stbi__malloc(z->s->img_x + 3); - if (!z->img_comp[k].linebuf) { - stbi__cleanup_jpeg(z); - return stbi__errpuc("outofmem", "Out of memory"); - } - - r->hs = z->img_h_max / z->img_comp[k].h; - r->vs = z->img_v_max / z->img_comp[k].v; - r->ystep = r->vs >> 1; - r->w_lores = (z->s->img_x + r->hs - 1) / r->hs; - r->ypos = 0; - r->line0 = r->line1 = z->img_comp[k].data; - - if (r->hs == 1 && r->vs == 1) - r->resample = resample_row_1; - else if (r->hs == 1 && r->vs == 2) - r->resample = stbi__resample_row_v_2; - else if (r->hs == 2 && r->vs == 1) - r->resample = stbi__resample_row_h_2; - else if (r->hs == 2 && r->vs == 2) - r->resample = z->resample_row_hv_2_kernel; - else - r->resample = stbi__resample_row_generic; - } - - // can't error after this so, this is safe - output = (stbi_uc *)stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); - if (!output) { - stbi__cleanup_jpeg(z); - return stbi__errpuc("outofmem", "Out of memory"); - } - - // now go ahead and resample - for (j = 0; j < z->s->img_y; ++j) { - stbi_uc *out = output + n * z->s->img_x * j; - for (k = 0; k < decode_n; ++k) { - stbi__resample *r = &res_comp[k]; - int y_bot = r->ystep >= (r->vs >> 1); - coutput[k] = r->resample(z->img_comp[k].linebuf, - y_bot ? r->line1 : r->line0, - y_bot ? r->line0 : r->line1, r->w_lores, - r->hs); - if (++r->ystep >= r->vs) { - r->ystep = 0; - r->line0 = r->line1; - if (++r->ypos < z->img_comp[k].y) - r->line1 += z->img_comp[k].w2; - } - } - if (n >= 3) { - stbi_uc *y = coutput[0]; - if (z->s->img_n == 3) { - if (is_rgb) { - for (i = 0; i < z->s->img_x; ++i) { - out[0] = y[i]; - out[1] = coutput[1][i]; - out[2] = coutput[2][i]; - out[3] = 255; - out += n; - } - } else { - z->YCbCr_to_RGB_kernel(out, y, coutput[1], - coutput[2], z->s->img_x, n); - } - } else if (z->s->img_n == 4) { - if (z->app14_color_transform == 0) { // CMYK - for (i = 0; i < z->s->img_x; ++i) { - stbi_uc m = coutput[3][i]; - out[0] = stbi__blinn_8x8(coutput[0][i], m); - out[1] = stbi__blinn_8x8(coutput[1][i], m); - out[2] = stbi__blinn_8x8(coutput[2][i], m); - out[3] = 255; - out += n; - } - } else if (z->app14_color_transform == 2) { // YCCK - z->YCbCr_to_RGB_kernel(out, y, coutput[1], - coutput[2], z->s->img_x, n); - for (i = 0; i < z->s->img_x; ++i) { - stbi_uc m = coutput[3][i]; - out[0] = stbi__blinn_8x8(255 - out[0], m); - out[1] = stbi__blinn_8x8(255 - out[1], m); - out[2] = stbi__blinn_8x8(255 - out[2], m); - out += n; - } - } else { // YCbCr + alpha? Ignore the fourth channel for now - z->YCbCr_to_RGB_kernel(out, y, coutput[1], - coutput[2], z->s->img_x, n); - } - } else - for (i = 0; i < z->s->img_x; ++i) { - out[0] = out[1] = out[2] = y[i]; - out[3] = 255; // not used if n==3 - out += n; - } - } else { - if (is_rgb) { - if (n == 1) - for (i = 0; i < z->s->img_x; ++i) - *out++ = stbi__compute_y(coutput[0][i], - coutput[1][i], - coutput[2][i]); - else { - for (i = 0; i < z->s->img_x; ++i, out += 2) { - out[0] = stbi__compute_y(coutput[0][i], - coutput[1][i], - coutput[2][i]); - out[1] = 255; - } - } - } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { - for (i = 0; i < z->s->img_x; ++i) { - stbi_uc m = coutput[3][i]; - stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); - stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); - stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); - out[0] = stbi__compute_y(r, g, b); - out[1] = 255; - out += n; - } - } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { - for (i = 0; i < z->s->img_x; ++i) { - out[0] = stbi__blinn_8x8(255 - coutput[0][i], - coutput[3][i]); - out[1] = 255; - out += n; - } - } else { - stbi_uc *y = coutput[0]; - if (n == 1) - for (i = 0; i < z->s->img_x; ++i) - out[i] = y[i]; - else - for (i = 0; i < z->s->img_x; ++i) { - *out++ = y[i]; - *out++ = 255; - } - } - } - } - stbi__cleanup_jpeg(z); - *out_x = z->s->img_x; - *out_y = z->s->img_y; - if (comp) - *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output - return output; - } -} - -static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - unsigned char *result; - stbi__jpeg *j = (stbi__jpeg *)stbi__malloc(sizeof(stbi__jpeg)); - if (!j) - return stbi__errpuc("outofmem", "Out of memory"); - memset(j, 0, sizeof(stbi__jpeg)); - STBI_NOTUSED(ri); - j->s = s; - stbi__setup_jpeg(j); - result = load_jpeg_image(j, x, y, comp, req_comp); - STBI_FREE(j); - return result; -} - -static int stbi__jpeg_test(stbi__context *s) -{ - int r; - stbi__jpeg *j = (stbi__jpeg *)stbi__malloc(sizeof(stbi__jpeg)); - if (!j) - return stbi__err("outofmem", "Out of memory"); - memset(j, 0, sizeof(stbi__jpeg)); - j->s = s; - stbi__setup_jpeg(j); - r = stbi__decode_jpeg_header(j, STBI__SCAN_type); - stbi__rewind(s); - STBI_FREE(j); - return r; -} - -static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) -{ - if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { - stbi__rewind(j->s); - return 0; - } - if (x) - *x = j->s->img_x; - if (y) - *y = j->s->img_y; - if (comp) - *comp = j->s->img_n >= 3 ? 3 : 1; - return 1; -} - -static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) -{ - int result; - stbi__jpeg *j = (stbi__jpeg *)(stbi__malloc(sizeof(stbi__jpeg))); - if (!j) - return stbi__err("outofmem", "Out of memory"); - memset(j, 0, sizeof(stbi__jpeg)); - j->s = s; - result = stbi__jpeg_info_raw(j, x, y, comp); - STBI_FREE(j); - return result; -} -#endif - -// public domain zlib decode v0.2 Sean Barrett 2006-11-18 -// simple implementation -// - all input must be provided in an upfront buffer -// - all output is written to a single output buffer (can malloc/realloc) -// performance -// - fast huffman - -#ifndef STBI_NO_ZLIB - -// fast-way is faster to check than jpeg huffman, but slow way is slower -#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables -#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) -#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet - -// zlib-style huffman encoding -// (jpegs packs from left, zlib from right, so can't share code) -typedef struct { - stbi__uint16 fast[1 << STBI__ZFAST_BITS]; - stbi__uint16 firstcode[16]; - int maxcode[17]; - stbi__uint16 firstsymbol[16]; - stbi_uc size[STBI__ZNSYMS]; - stbi__uint16 value[STBI__ZNSYMS]; -} stbi__zhuffman; - -stbi_inline static int stbi__bitreverse16(int n) -{ - n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); - n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); - n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); - n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); - return n; -} - -stbi_inline static int stbi__bit_reverse(int v, int bits) -{ - STBI_ASSERT(bits <= 16); - // to bit reverse n bits, reverse 16 and shift - // e.g. 11 bits, bit reverse and shift away 5 - return stbi__bitreverse16(v) >> (16 - bits); -} - -static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) -{ - int i, k = 0; - int code, next_code[16], sizes[17]; - - // DEFLATE spec for generating codes - memset(sizes, 0, sizeof(sizes)); - memset(z->fast, 0, sizeof(z->fast)); - for (i = 0; i < num; ++i) - ++sizes[sizelist[i]]; - sizes[0] = 0; - for (i = 1; i < 16; ++i) - if (sizes[i] > (1 << i)) - return stbi__err("bad sizes", "Corrupt PNG"); - code = 0; - for (i = 1; i < 16; ++i) { - next_code[i] = code; - z->firstcode[i] = (stbi__uint16)code; - z->firstsymbol[i] = (stbi__uint16)k; - code = (code + sizes[i]); - if (sizes[i]) - if (code - 1 >= (1 << i)) - return stbi__err("bad codelengths", "Corrupt PNG"); - z->maxcode[i] = code << (16 - i); // preshift for inner loop - code <<= 1; - k += sizes[i]; - } - z->maxcode[16] = 0x10000; // sentinel - for (i = 0; i < num; ++i) { - int s = sizelist[i]; - if (s) { - int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; - stbi__uint16 fastv = (stbi__uint16)((s << 9) | i); - z->size[c] = (stbi_uc)s; - z->value[c] = (stbi__uint16)i; - if (s <= STBI__ZFAST_BITS) { - int j = stbi__bit_reverse(next_code[s], s); - while (j < (1 << STBI__ZFAST_BITS)) { - z->fast[j] = fastv; - j += (1 << s); - } - } - ++next_code[s]; - } - } - return 1; -} - -// zlib-from-memory implementation for PNG reading -// because PNG allows splitting the zlib stream arbitrarily, -// and it's annoying structurally to have PNG call ZLIB call PNG, -// we require PNG read all the IDATs and combine them into a single -// memory buffer - -typedef struct { - stbi_uc *zbuffer, *zbuffer_end; - int num_bits; - stbi__uint32 code_buffer; - - char *zout; - char *zout_start; - char *zout_end; - int z_expandable; - - stbi__zhuffman z_length, z_distance; -} stbi__zbuf; - -stbi_inline static int stbi__zeof(stbi__zbuf *z) -{ - return (z->zbuffer >= z->zbuffer_end); -} - -stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) -{ - return stbi__zeof(z) ? 0 : *z->zbuffer++; -} - -static void stbi__fill_bits(stbi__zbuf *z) -{ - do { - if (z->code_buffer >= (1U << z->num_bits)) { - z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ - return; - } - z->code_buffer |= (unsigned int)stbi__zget8(z) << z->num_bits; - z->num_bits += 8; - } while (z->num_bits <= 24); -} - -stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) -{ - unsigned int k; - if (z->num_bits < n) - stbi__fill_bits(z); - k = z->code_buffer & ((1 << n) - 1); - z->code_buffer >>= n; - z->num_bits -= n; - return k; -} - -static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) -{ - int b, s, k; - // not resolved by fast table, so compute it the slow way - // use jpeg approach, which requires MSbits at top - k = stbi__bit_reverse(a->code_buffer, 16); - for (s = STBI__ZFAST_BITS + 1;; ++s) - if (k < z->maxcode[s]) - break; - if (s >= 16) - return -1; // invalid code! - // code size is s, so: - b = (k >> (16 - s)) - z->firstcode[s] + z->firstsymbol[s]; - if (b >= STBI__ZNSYMS) - return -1; // some data was corrupt somewhere! - if (z->size[b] != s) - return -1; // was originally an assert, but report failure instead. - a->code_buffer >>= s; - a->num_bits -= s; - return z->value[b]; -} - -stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) -{ - int b, s; - if (a->num_bits < 16) { - if (stbi__zeof(a)) { - return -1; /* report error for unexpected end of data. */ - } - stbi__fill_bits(a); - } - b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; - if (b) { - s = b >> 9; - a->code_buffer >>= s; - a->num_bits -= s; - return b & 511; - } - return stbi__zhuffman_decode_slowpath(a, z); -} - -static int stbi__zexpand(stbi__zbuf *z, char *zout, - int n) // need to make room for n bytes -{ - char *q; - unsigned int cur, limit, old_limit; - z->zout = zout; - if (!z->z_expandable) - return stbi__err("output buffer limit", "Corrupt PNG"); - cur = (unsigned int)(z->zout - z->zout_start); - limit = old_limit = (unsigned)(z->zout_end - z->zout_start); - if (UINT_MAX - cur < (unsigned)n) - return stbi__err("outofmem", "Out of memory"); - while (cur + n > limit) { - if (limit > UINT_MAX / 2) - return stbi__err("outofmem", "Out of memory"); - limit *= 2; - } - q = (char *)STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); - STBI_NOTUSED(old_limit); - if (q == NULL) - return stbi__err("outofmem", "Out of memory"); - z->zout_start = q; - z->zout = q + cur; - z->zout_end = q + limit; - return 1; -} - -static const int stbi__zlength_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, - 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, - 99, 115, 131, 163, 195, 227, 258, 0, 0 }; - -static const int stbi__zlength_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 }; - -static const int stbi__zdist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, - 17, 25, 33, 49, 65, 97, 129, 193, - 257, 385, 513, 769, 1025, 1537, 2049, 3073, - 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 }; - -static const int stbi__zdist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, - 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 }; - -static int stbi__parse_huffman_block(stbi__zbuf *a) -{ - char *zout = a->zout; - for (;;) { - int z = stbi__zhuffman_decode(a, &a->z_length); - if (z < 256) { - if (z < 0) - return stbi__err("bad huffman code", - "Corrupt PNG"); // error in huffman codes - if (zout >= a->zout_end) { - if (!stbi__zexpand(a, zout, 1)) - return 0; - zout = a->zout; - } - *zout++ = (char)z; - } else { - stbi_uc *p; - int len, dist; - if (z == 256) { - a->zout = zout; - return 1; - } - if (z >= 286) - return stbi__err( - "bad huffman code", - "Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data - z -= 257; - len = stbi__zlength_base[z]; - if (stbi__zlength_extra[z]) - len += stbi__zreceive(a, stbi__zlength_extra[z]); - z = stbi__zhuffman_decode(a, &a->z_distance); - if (z < 0 || z >= 30) - return stbi__err( - "bad huffman code", - "Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data - dist = stbi__zdist_base[z]; - if (stbi__zdist_extra[z]) - dist += stbi__zreceive(a, stbi__zdist_extra[z]); - if (zout - a->zout_start < dist) - return stbi__err("bad dist", "Corrupt PNG"); - if (zout + len > a->zout_end) { - if (!stbi__zexpand(a, zout, len)) - return 0; - zout = a->zout; - } - p = (stbi_uc *)(zout - dist); - if (dist == 1) { // run of one byte; common in images. - stbi_uc v = *p; - if (len) { - do - *zout++ = v; - while (--len); - } - } else { - if (len) { - do - *zout++ = *p++; - while (--len); - } - } - } - } -} - -static int stbi__compute_huffman_codes(stbi__zbuf *a) -{ - static const stbi_uc length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, - 11, 4, 12, 3, 13, 2, 14, 1, 15 }; - stbi__zhuffman z_codelength; - stbi_uc lencodes[286 + 32 + 137]; //padding for maximum single op - stbi_uc codelength_sizes[19]; - int i, n; - - int hlit = stbi__zreceive(a, 5) + 257; - int hdist = stbi__zreceive(a, 5) + 1; - int hclen = stbi__zreceive(a, 4) + 4; - int ntot = hlit + hdist; - - memset(codelength_sizes, 0, sizeof(codelength_sizes)); - for (i = 0; i < hclen; ++i) { - int s = stbi__zreceive(a, 3); - codelength_sizes[length_dezigzag[i]] = (stbi_uc)s; - } - if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) - return 0; - - n = 0; - while (n < ntot) { - int c = stbi__zhuffman_decode(a, &z_codelength); - if (c < 0 || c >= 19) - return stbi__err("bad codelengths", "Corrupt PNG"); - if (c < 16) - lencodes[n++] = (stbi_uc)c; - else { - stbi_uc fill = 0; - if (c == 16) { - c = stbi__zreceive(a, 2) + 3; - if (n == 0) - return stbi__err("bad codelengths", "Corrupt PNG"); - fill = lencodes[n - 1]; - } else if (c == 17) { - c = stbi__zreceive(a, 3) + 3; - } else if (c == 18) { - c = stbi__zreceive(a, 7) + 11; - } else { - return stbi__err("bad codelengths", "Corrupt PNG"); - } - if (ntot - n < c) - return stbi__err("bad codelengths", "Corrupt PNG"); - memset(lencodes + n, fill, c); - n += c; - } - } - if (n != ntot) - return stbi__err("bad codelengths", "Corrupt PNG"); - if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) - return 0; - if (!stbi__zbuild_huffman(&a->z_distance, lencodes + hlit, hdist)) - return 0; - return 1; -} - -static int stbi__parse_uncompressed_block(stbi__zbuf *a) -{ - stbi_uc header[4]; - int len, nlen, k; - if (a->num_bits & 7) - stbi__zreceive(a, a->num_bits & 7); // discard - // drain the bit-packed data into header - k = 0; - while (a->num_bits > 0) { - header[k++] = (stbi_uc)(a->code_buffer & 255); // suppress MSVC run-time check - a->code_buffer >>= 8; - a->num_bits -= 8; - } - if (a->num_bits < 0) - return stbi__err("zlib corrupt", "Corrupt PNG"); - // now fill header the normal way - while (k < 4) - header[k++] = stbi__zget8(a); - len = header[1] * 256 + header[0]; - nlen = header[3] * 256 + header[2]; - if (nlen != (len ^ 0xffff)) - return stbi__err("zlib corrupt", "Corrupt PNG"); - if (a->zbuffer + len > a->zbuffer_end) - return stbi__err("read past buffer", "Corrupt PNG"); - if (a->zout + len > a->zout_end) - if (!stbi__zexpand(a, a->zout, len)) - return 0; - memcpy(a->zout, a->zbuffer, len); - a->zbuffer += len; - a->zout += len; - return 1; -} - -static int stbi__parse_zlib_header(stbi__zbuf *a) -{ - int cmf = stbi__zget8(a); - int cm = cmf & 15; - /* int cinfo = cmf >> 4; */ - int flg = stbi__zget8(a); - if (stbi__zeof(a)) - return stbi__err("bad zlib header", "Corrupt PNG"); // zlib spec - if ((cmf * 256 + flg) % 31 != 0) - return stbi__err("bad zlib header", "Corrupt PNG"); // zlib spec - if (flg & 32) - return stbi__err("no preset dict", - "Corrupt PNG"); // preset dictionary not allowed in png - if (cm != 8) - return stbi__err("bad compression", - "Corrupt PNG"); // DEFLATE required for png - // window = 1 << (8 + cinfo)... but who cares, we fully buffer output - return 1; -} - -static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = { - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, - 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8 -}; -static const stbi_uc stbi__zdefault_distance[32] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 -}; -/* -Init algorithm: -{ - int i; // use <= to match clearly with spec - for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; - for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; - for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; - for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; - - for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; -} -*/ - -static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) -{ - int final, type; - if (parse_header) - if (!stbi__parse_zlib_header(a)) - return 0; - a->num_bits = 0; - a->code_buffer = 0; - do { - final = stbi__zreceive(a, 1); - type = stbi__zreceive(a, 2); - if (type == 0) { - if (!stbi__parse_uncompressed_block(a)) - return 0; - } else if (type == 3) { - return 0; - } else { - if (type == 1) { - // use fixed code lengths - if (!stbi__zbuild_huffman(&a->z_length, stbi__zdefault_length, - STBI__ZNSYMS)) - return 0; - if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, - 32)) - return 0; - } else { - if (!stbi__compute_huffman_codes(a)) - return 0; - } - if (!stbi__parse_huffman_block(a)) - return 0; - } - } while (!final); - return 1; -} - -static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) -{ - a->zout_start = obuf; - a->zout = obuf; - a->zout_end = obuf + olen; - a->z_expandable = exp; - - return stbi__parse_zlib(a, parse_header); -} - -STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, - int *outlen) -{ - stbi__zbuf a; - char *p = (char *)stbi__malloc(initial_size); - if (p == NULL) - return NULL; - a.zbuffer = (stbi_uc *)buffer; - a.zbuffer_end = (stbi_uc *)buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { - if (outlen) - *outlen = (int)(a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) -{ - return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); -} - -STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, - int initial_size, int *outlen, - int parse_header) -{ - stbi__zbuf a; - char *p = (char *)stbi__malloc(initial_size); - if (p == NULL) - return NULL; - a.zbuffer = (stbi_uc *)buffer; - a.zbuffer_end = (stbi_uc *)buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { - if (outlen) - *outlen = (int)(a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) -{ - stbi__zbuf a; - a.zbuffer = (stbi_uc *)ibuffer; - a.zbuffer_end = (stbi_uc *)ibuffer + ilen; - if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) - return (int)(a.zout - a.zout_start); - else - return -1; -} - -STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) -{ - stbi__zbuf a; - char *p = (char *)stbi__malloc(16384); - if (p == NULL) - return NULL; - a.zbuffer = (stbi_uc *)buffer; - a.zbuffer_end = (stbi_uc *)buffer + len; - if (stbi__do_zlib(&a, p, 16384, 1, 0)) { - if (outlen) - *outlen = (int)(a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) -{ - stbi__zbuf a; - a.zbuffer = (stbi_uc *)ibuffer; - a.zbuffer_end = (stbi_uc *)ibuffer + ilen; - if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) - return (int)(a.zout - a.zout_start); - else - return -1; -} -#endif - -// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 -// simple implementation -// - only 8-bit samples -// - no CRC checking -// - allocates lots of intermediate memory -// - avoids problem of streaming data between subsystems -// - avoids explicit window management -// performance -// - uses stb_zlib, a PD zlib implementation with fast huffman decoding - -#ifndef STBI_NO_PNG -typedef struct { - stbi__uint32 length; - stbi__uint32 type; -} stbi__pngchunk; - -static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) -{ - stbi__pngchunk c; - c.length = stbi__get32be(s); - c.type = stbi__get32be(s); - return c; -} - -static int stbi__check_png_header(stbi__context *s) -{ - static const stbi_uc png_sig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; - int i; - for (i = 0; i < 8; ++i) - if (stbi__get8(s) != png_sig[i]) - return stbi__err("bad png sig", "Not a PNG"); - return 1; -} - -typedef struct { - stbi__context *s; - stbi_uc *idata, *expanded, *out; - int depth; -} stbi__png; - -enum { - STBI__F_none = 0, - STBI__F_sub = 1, - STBI__F_up = 2, - STBI__F_avg = 3, - STBI__F_paeth = 4, - // synthetic filters used for first scanline to avoid needing a dummy row of 0s - STBI__F_avg_first, - STBI__F_paeth_first -}; - -static stbi_uc first_row_filter[5] = { STBI__F_none, STBI__F_sub, STBI__F_none, STBI__F_avg_first, - STBI__F_paeth_first }; - -static int stbi__paeth(int a, int b, int c) -{ - int p = a + b - c; - int pa = abs(p - a); - int pb = abs(p - b); - int pc = abs(p - c); - if (pa <= pb && pa <= pc) - return a; - if (pb <= pc) - return b; - return c; -} - -static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0, 0, 0, 0x01 }; - -// create the png data from post-deflated data -static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, - stbi__uint32 x, stbi__uint32 y, int depth, int color) -{ - int bytes = (depth == 16 ? 2 : 1); - stbi__context *s = a->s; - stbi__uint32 i, j, stride = x * out_n * bytes; - stbi__uint32 img_len, img_width_bytes; - int k; - int img_n = s->img_n; // copy it into a local for later - - int output_bytes = out_n * bytes; - int filter_bytes = img_n * bytes; - int width = x; - - STBI_ASSERT(out_n == s->img_n || out_n == s->img_n + 1); - a->out = (stbi_uc *)stbi__malloc_mad3(x, y, output_bytes, - 0); // extra bytes to write off the end into - if (!a->out) - return stbi__err("outofmem", "Out of memory"); - - if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) - return stbi__err("too large", "Corrupt PNG"); - img_width_bytes = (((img_n * x * depth) + 7) >> 3); - img_len = (img_width_bytes + 1) * y; - - // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, - // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), - // so just check for raw_len < img_len always. - if (raw_len < img_len) - return stbi__err("not enough pixels", "Corrupt PNG"); - - for (j = 0; j < y; ++j) { - stbi_uc *cur = a->out + stride * j; - stbi_uc *prior; - int filter = *raw++; - - if (filter > 4) - return stbi__err("invalid filter", "Corrupt PNG"); - - if (depth < 8) { - if (img_width_bytes > x) - return stbi__err("invalid width", "Corrupt PNG"); - cur += x * out_n - - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place - filter_bytes = 1; - width = img_width_bytes; - } - prior = cur - - stride; // bugfix: need to compute this after 'cur +=' computation above - - // if first row, use special filter that doesn't sample previous row - if (j == 0) - filter = first_row_filter[filter]; - - // handle first byte explicitly - for (k = 0; k < filter_bytes; ++k) { - switch (filter) { - case STBI__F_none: - cur[k] = raw[k]; - break; - case STBI__F_sub: - cur[k] = raw[k]; - break; - case STBI__F_up: - cur[k] = STBI__BYTECAST(raw[k] + prior[k]); - break; - case STBI__F_avg: - cur[k] = STBI__BYTECAST(raw[k] + (prior[k] >> 1)); - break; - case STBI__F_paeth: - cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0, prior[k], 0)); - break; - case STBI__F_avg_first: - cur[k] = raw[k]; - break; - case STBI__F_paeth_first: - cur[k] = raw[k]; - break; - } - } - - if (depth == 8) { - if (img_n != out_n) - cur[img_n] = 255; // first pixel - raw += img_n; - cur += out_n; - prior += out_n; - } else if (depth == 16) { - if (img_n != out_n) { - cur[filter_bytes] = 255; // first pixel top byte - cur[filter_bytes + 1] = 255; // first pixel bottom byte - } - raw += filter_bytes; - cur += output_bytes; - prior += output_bytes; - } else { - raw += 1; - cur += 1; - prior += 1; - } - - // this is a little gross, so that we don't switch per-pixel or per-component - if (depth < 8 || img_n == out_n) { - int nk = (width - 1) * filter_bytes; -#define STBI__CASE(f) \ - case f: \ - for (k = 0; k < nk; ++k) - switch (filter) { - // "none" filter turns into a memcpy here; make that explicit. - case STBI__F_none: - memcpy(cur, raw, nk); - break; - STBI__CASE(STBI__F_sub) - { - cur[k] = STBI__BYTECAST(raw[k] + cur[k - filter_bytes]); - } - break; - STBI__CASE(STBI__F_up) - { - cur[k] = STBI__BYTECAST(raw[k] + prior[k]); - } - break; - STBI__CASE(STBI__F_avg) - { - cur[k] = STBI__BYTECAST( - raw[k] + ((prior[k] + cur[k - filter_bytes]) >> 1)); - } - break; - STBI__CASE(STBI__F_paeth) - { - cur[k] = STBI__BYTECAST( - raw[k] + stbi__paeth(cur[k - filter_bytes], - prior[k], - prior[k - filter_bytes])); - } - break; - STBI__CASE(STBI__F_avg_first) - { - cur[k] = STBI__BYTECAST(raw[k] + - (cur[k - filter_bytes] >> 1)); - } - break; - STBI__CASE(STBI__F_paeth_first) - { - cur[k] = STBI__BYTECAST( - raw[k] + stbi__paeth(cur[k - filter_bytes], 0, 0)); - } - break; - } -#undef STBI__CASE - raw += nk; - } else { - STBI_ASSERT(img_n + 1 == out_n); -#define STBI__CASE(f) \ - case f: \ - for (i = x - 1; i >= 1; --i, cur[filter_bytes] = 255, raw += filter_bytes, \ - cur += output_bytes, prior += output_bytes) \ - for (k = 0; k < filter_bytes; ++k) - switch (filter) { - STBI__CASE(STBI__F_none) - { - cur[k] = raw[k]; - } - break; - STBI__CASE(STBI__F_sub) - { - cur[k] = STBI__BYTECAST(raw[k] + cur[k - output_bytes]); - } - break; - STBI__CASE(STBI__F_up) - { - cur[k] = STBI__BYTECAST(raw[k] + prior[k]); - } - break; - STBI__CASE(STBI__F_avg) - { - cur[k] = STBI__BYTECAST( - raw[k] + ((prior[k] + cur[k - output_bytes]) >> 1)); - } - break; - STBI__CASE(STBI__F_paeth) - { - cur[k] = STBI__BYTECAST( - raw[k] + stbi__paeth(cur[k - output_bytes], - prior[k], - prior[k - output_bytes])); - } - break; - STBI__CASE(STBI__F_avg_first) - { - cur[k] = STBI__BYTECAST(raw[k] + - (cur[k - output_bytes] >> 1)); - } - break; - STBI__CASE(STBI__F_paeth_first) - { - cur[k] = STBI__BYTECAST( - raw[k] + stbi__paeth(cur[k - output_bytes], 0, 0)); - } - break; - } -#undef STBI__CASE - - // the loop above sets the high byte of the pixels' alpha, but for - // 16 bit png files we also need the low byte set. we'll do that here. - if (depth == 16) { - cur = a->out + - stride * j; // start at the beginning of the row again - for (i = 0; i < x; ++i, cur += output_bytes) { - cur[filter_bytes + 1] = 255; - } - } - } - } - - // we make a separate pass to expand bits to pixels; for performance, - // this could run two scanlines behind the above code, so it won't - // intefere with filtering but will still be in the cache. - if (depth < 8) { - for (j = 0; j < y; ++j) { - stbi_uc *cur = a->out + stride * j; - stbi_uc *in = a->out + stride * j + x * out_n - img_width_bytes; - // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit - // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop - stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : - 1; // scale grayscale values to 0..255 range - - // note that the final byte might overshoot and write more data than desired. - // we can allocate enough data that this never writes out of memory, but it - // could also overwrite the next scanline. can it overwrite non-empty data - // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. - // so we need to explicitly clamp the final ones - - if (depth == 4) { - for (k = x * img_n; k >= 2; k -= 2, ++in) { - *cur++ = scale * ((*in >> 4)); - *cur++ = scale * ((*in) & 0x0f); - } - if (k > 0) - *cur++ = scale * ((*in >> 4)); - } else if (depth == 2) { - for (k = x * img_n; k >= 4; k -= 4, ++in) { - *cur++ = scale * ((*in >> 6)); - *cur++ = scale * ((*in >> 4) & 0x03); - *cur++ = scale * ((*in >> 2) & 0x03); - *cur++ = scale * ((*in) & 0x03); - } - if (k > 0) - *cur++ = scale * ((*in >> 6)); - if (k > 1) - *cur++ = scale * ((*in >> 4) & 0x03); - if (k > 2) - *cur++ = scale * ((*in >> 2) & 0x03); - } else if (depth == 1) { - for (k = x * img_n; k >= 8; k -= 8, ++in) { - *cur++ = scale * ((*in >> 7)); - *cur++ = scale * ((*in >> 6) & 0x01); - *cur++ = scale * ((*in >> 5) & 0x01); - *cur++ = scale * ((*in >> 4) & 0x01); - *cur++ = scale * ((*in >> 3) & 0x01); - *cur++ = scale * ((*in >> 2) & 0x01); - *cur++ = scale * ((*in >> 1) & 0x01); - *cur++ = scale * ((*in) & 0x01); - } - if (k > 0) - *cur++ = scale * ((*in >> 7)); - if (k > 1) - *cur++ = scale * ((*in >> 6) & 0x01); - if (k > 2) - *cur++ = scale * ((*in >> 5) & 0x01); - if (k > 3) - *cur++ = scale * ((*in >> 4) & 0x01); - if (k > 4) - *cur++ = scale * ((*in >> 3) & 0x01); - if (k > 5) - *cur++ = scale * ((*in >> 2) & 0x01); - if (k > 6) - *cur++ = scale * ((*in >> 1) & 0x01); - } - if (img_n != out_n) { - int q; - // insert alpha = 255 - cur = a->out + stride * j; - if (img_n == 1) { - for (q = x - 1; q >= 0; --q) { - cur[q * 2 + 1] = 255; - cur[q * 2 + 0] = cur[q]; - } - } else { - STBI_ASSERT(img_n == 3); - for (q = x - 1; q >= 0; --q) { - cur[q * 4 + 3] = 255; - cur[q * 4 + 2] = cur[q * 3 + 2]; - cur[q * 4 + 1] = cur[q * 3 + 1]; - cur[q * 4 + 0] = cur[q * 3 + 0]; - } - } - } - } - } else if (depth == 16) { - // force the image data from big-endian to platform-native. - // this is done in a separate pass due to the decoding relying - // on the data being untouched, but could probably be done - // per-line during decode if care is taken. - stbi_uc *cur = a->out; - stbi__uint16 *cur16 = (stbi__uint16 *)cur; - - for (i = 0; i < x * y * out_n; ++i, cur16++, cur += 2) { - *cur16 = (cur[0] << 8) | cur[1]; - } - } - - return 1; -} - -static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, - int out_n, int depth, int color, int interlaced) -{ - int bytes = (depth == 16 ? 2 : 1); - int out_bytes = out_n * bytes; - stbi_uc *final; - int p; - if (!interlaced) - return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, - a->s->img_y, depth, color); - - // de-interlacing - final = (stbi_uc *)stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); - if (!final) - return stbi__err("outofmem", "Out of memory"); - for (p = 0; p < 7; ++p) { - int xorig[] = { 0, 4, 0, 2, 0, 1, 0 }; - int yorig[] = { 0, 0, 4, 0, 2, 0, 1 }; - int xspc[] = { 8, 8, 4, 4, 2, 2, 1 }; - int yspc[] = { 8, 8, 8, 4, 4, 2, 2 }; - int i, j, x, y; - // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 - x = (a->s->img_x - xorig[p] + xspc[p] - 1) / xspc[p]; - y = (a->s->img_y - yorig[p] + yspc[p] - 1) / yspc[p]; - if (x && y) { - stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; - if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, - depth, color)) { - STBI_FREE(final); - return 0; - } - for (j = 0; j < y; ++j) { - for (i = 0; i < x; ++i) { - int out_y = j * yspc[p] + yorig[p]; - int out_x = i * xspc[p] + xorig[p]; - memcpy(final + out_y * a->s->img_x * out_bytes + - out_x * out_bytes, - a->out + (j * x + i) * out_bytes, out_bytes); - } - } - STBI_FREE(a->out); - image_data += img_len; - image_data_len -= img_len; - } - } - a->out = final; - - return 1; -} - -static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - // compute color-based transparency, assuming we've - // already got 255 as the alpha value in the output - STBI_ASSERT(out_n == 2 || out_n == 4); - - if (out_n == 2) { - for (i = 0; i < pixel_count; ++i) { - p[1] = (p[0] == tc[0] ? 0 : 255); - p += 2; - } - } else { - for (i = 0; i < pixel_count; ++i) { - if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) - p[3] = 0; - p += 4; - } - } - return 1; -} - -static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi__uint16 *p = (stbi__uint16 *)z->out; - - // compute color-based transparency, assuming we've - // already got 65535 as the alpha value in the output - STBI_ASSERT(out_n == 2 || out_n == 4); - - if (out_n == 2) { - for (i = 0; i < pixel_count; ++i) { - p[1] = (p[0] == tc[0] ? 0 : 65535); - p += 2; - } - } else { - for (i = 0; i < pixel_count; ++i) { - if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) - p[3] = 0; - p += 4; - } - } - return 1; -} - -static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) -{ - stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; - stbi_uc *p, *temp_out, *orig = a->out; - - p = (stbi_uc *)stbi__malloc_mad2(pixel_count, pal_img_n, 0); - if (p == NULL) - return stbi__err("outofmem", "Out of memory"); - - // between here and free(out) below, exitting would leak - temp_out = p; - - if (pal_img_n == 3) { - for (i = 0; i < pixel_count; ++i) { - int n = orig[i] * 4; - p[0] = palette[n]; - p[1] = palette[n + 1]; - p[2] = palette[n + 2]; - p += 3; - } - } else { - for (i = 0; i < pixel_count; ++i) { - int n = orig[i] * 4; - p[0] = palette[n]; - p[1] = palette[n + 1]; - p[2] = palette[n + 2]; - p[3] = palette[n + 3]; - p += 4; - } - } - STBI_FREE(a->out); - a->out = temp_out; - - STBI_NOTUSED(len); - - return 1; -} - -static int stbi__unpremultiply_on_load_global = 0; -static int stbi__de_iphone_flag_global = 0; - -STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) -{ - stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; -} - -STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) -{ - stbi__de_iphone_flag_global = flag_true_if_should_convert; -} - -#ifndef STBI_THREAD_LOCAL -#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global -#define stbi__de_iphone_flag stbi__de_iphone_flag_global -#else -static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; -static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; - -STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) -{ - stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; - stbi__unpremultiply_on_load_set = 1; -} - -STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) -{ - stbi__de_iphone_flag_local = flag_true_if_should_convert; - stbi__de_iphone_flag_set = 1; -} - -#define stbi__unpremultiply_on_load \ - (stbi__unpremultiply_on_load_set ? stbi__unpremultiply_on_load_local : \ - stbi__unpremultiply_on_load_global) -#define stbi__de_iphone_flag \ - (stbi__de_iphone_flag_set ? stbi__de_iphone_flag_local : stbi__de_iphone_flag_global) -#endif // STBI_THREAD_LOCAL - -static void stbi__de_iphone(stbi__png *z) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - if (s->img_out_n == 3) { // convert bgr to rgb - for (i = 0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 3; - } - } else { - STBI_ASSERT(s->img_out_n == 4); - if (stbi__unpremultiply_on_load) { - // convert bgr to rgb and unpremultiply - for (i = 0; i < pixel_count; ++i) { - stbi_uc a = p[3]; - stbi_uc t = p[0]; - if (a) { - stbi_uc half = a / 2; - p[0] = (p[2] * 255 + half) / a; - p[1] = (p[1] * 255 + half) / a; - p[2] = (t * 255 + half) / a; - } else { - p[0] = p[2]; - p[2] = t; - } - p += 4; - } - } else { - // convert bgr to rgb - for (i = 0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 4; - } - } - } -} - -#define STBI__PNG_TYPE(a, b, c, d) \ - (((unsigned)(a) << 24) + ((unsigned)(b) << 16) + ((unsigned)(c) << 8) + (unsigned)(d)) - -static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) -{ - stbi_uc palette[1024], pal_img_n = 0; - stbi_uc has_trans = 0, tc[3] = { 0 }; - stbi__uint16 tc16[3]; - stbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0; - int first = 1, k, interlace = 0, color = 0, is_iphone = 0; - stbi__context *s = z->s; - - z->expanded = NULL; - z->idata = NULL; - z->out = NULL; - - if (!stbi__check_png_header(s)) - return 0; - - if (scan == STBI__SCAN_type) - return 1; - - for (;;) { - stbi__pngchunk c = stbi__get_chunk_header(s); - switch (c.type) { - case STBI__PNG_TYPE('C', 'g', 'B', 'I'): - is_iphone = 1; - stbi__skip(s, c.length); - break; - case STBI__PNG_TYPE('I', 'H', 'D', 'R'): { - int comp, filter; - if (!first) - return stbi__err("multiple IHDR", "Corrupt PNG"); - first = 0; - if (c.length != 13) - return stbi__err("bad IHDR len", "Corrupt PNG"); - s->img_x = stbi__get32be(s); - s->img_y = stbi__get32be(s); - if (s->img_y > STBI_MAX_DIMENSIONS) - return stbi__err("too large", "Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) - return stbi__err("too large", "Very large image (corrupt?)"); - z->depth = stbi__get8(s); - if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && - z->depth != 16) - return stbi__err("1/2/4/8/16-bit only", - "PNG not supported: 1/2/4/8/16-bit only"); - color = stbi__get8(s); - if (color > 6) - return stbi__err("bad ctype", "Corrupt PNG"); - if (color == 3 && z->depth == 16) - return stbi__err("bad ctype", "Corrupt PNG"); - if (color == 3) - pal_img_n = 3; - else if (color & 1) - return stbi__err("bad ctype", "Corrupt PNG"); - comp = stbi__get8(s); - if (comp) - return stbi__err("bad comp method", "Corrupt PNG"); - filter = stbi__get8(s); - if (filter) - return stbi__err("bad filter method", "Corrupt PNG"); - interlace = stbi__get8(s); - if (interlace > 1) - return stbi__err("bad interlace method", "Corrupt PNG"); - if (!s->img_x || !s->img_y) - return stbi__err("0-pixel image", "Corrupt PNG"); - if (!pal_img_n) { - s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); - if ((1 << 30) / s->img_x / s->img_n < s->img_y) - return stbi__err("too large", "Image too large to decode"); - } else { - // if paletted, then pal_n is our final components, and - // img_n is # components to decompress/filter. - s->img_n = 1; - if ((1 << 30) / s->img_x / 4 < s->img_y) - return stbi__err("too large", "Corrupt PNG"); - } - // even with SCAN_header, have to scan to see if we have a tRNS - break; - } - - case STBI__PNG_TYPE('P', 'L', 'T', 'E'): { - if (first) - return stbi__err("first not IHDR", "Corrupt PNG"); - if (c.length > 256 * 3) - return stbi__err("invalid PLTE", "Corrupt PNG"); - pal_len = c.length / 3; - if (pal_len * 3 != c.length) - return stbi__err("invalid PLTE", "Corrupt PNG"); - for (i = 0; i < pal_len; ++i) { - palette[i * 4 + 0] = stbi__get8(s); - palette[i * 4 + 1] = stbi__get8(s); - palette[i * 4 + 2] = stbi__get8(s); - palette[i * 4 + 3] = 255; - } - break; - } - - case STBI__PNG_TYPE('t', 'R', 'N', 'S'): { - if (first) - return stbi__err("first not IHDR", "Corrupt PNG"); - if (z->idata) - return stbi__err("tRNS after IDAT", "Corrupt PNG"); - if (pal_img_n) { - if (scan == STBI__SCAN_header) { - s->img_n = 4; - return 1; - } - if (pal_len == 0) - return stbi__err("tRNS before PLTE", "Corrupt PNG"); - if (c.length > pal_len) - return stbi__err("bad tRNS len", "Corrupt PNG"); - pal_img_n = 4; - for (i = 0; i < c.length; ++i) - palette[i * 4 + 3] = stbi__get8(s); - } else { - if (!(s->img_n & 1)) - return stbi__err("tRNS with alpha", "Corrupt PNG"); - if (c.length != (stbi__uint32)s->img_n * 2) - return stbi__err("bad tRNS len", "Corrupt PNG"); - has_trans = 1; - // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. - if (scan == STBI__SCAN_header) { - ++s->img_n; - return 1; - } - if (z->depth == 16) { - for (k = 0; k < s->img_n; ++k) - tc16[k] = (stbi__uint16)stbi__get16be( - s); // copy the values as-is - } else { - for (k = 0; k < s->img_n; ++k) - tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * - stbi__depth_scale_table - [z->depth]; // non 8-bit images will be larger - } - } - break; - } - - case STBI__PNG_TYPE('I', 'D', 'A', 'T'): { - if (first) - return stbi__err("first not IHDR", "Corrupt PNG"); - if (pal_img_n && !pal_len) - return stbi__err("no PLTE", "Corrupt PNG"); - if (scan == STBI__SCAN_header) { - // header scan definitely stops at first IDAT - if (pal_img_n) - s->img_n = pal_img_n; - return 1; - } - if (c.length > (1u << 30)) - return stbi__err("IDAT size limit", - "IDAT section larger than 2^30 bytes"); - if ((int)(ioff + c.length) < (int)ioff) - return 0; - if (ioff + c.length > idata_limit) { - stbi__uint32 idata_limit_old = idata_limit; - stbi_uc *p; - if (idata_limit == 0) - idata_limit = c.length > 4096 ? c.length : 4096; - while (ioff + c.length > idata_limit) - idata_limit *= 2; - STBI_NOTUSED(idata_limit_old); - p = (stbi_uc *)STBI_REALLOC_SIZED(z->idata, idata_limit_old, - idata_limit); - if (p == NULL) - return stbi__err("outofmem", "Out of memory"); - z->idata = p; - } - if (!stbi__getn(s, z->idata + ioff, c.length)) - return stbi__err("outofdata", "Corrupt PNG"); - ioff += c.length; - break; - } - - case STBI__PNG_TYPE('I', 'E', 'N', 'D'): { - stbi__uint32 raw_len, bpl; - if (first) - return stbi__err("first not IHDR", "Corrupt PNG"); - if (scan != STBI__SCAN_load) - return 1; - if (z->idata == NULL) - return stbi__err("no IDAT", "Corrupt PNG"); - // initial guess for decoded data size to avoid unnecessary reallocs - bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component - raw_len = bpl * s->img_y * s->img_n /* pixels */ + - s->img_y /* filter mode per row */; - z->expanded = (stbi_uc *)stbi_zlib_decode_malloc_guesssize_headerflag( - (char *)z->idata, ioff, raw_len, (int *)&raw_len, !is_iphone); - if (z->expanded == NULL) - return 0; // zlib should set error - STBI_FREE(z->idata); - z->idata = NULL; - if ((req_comp == s->img_n + 1 && req_comp != 3 && !pal_img_n) || has_trans) - s->img_out_n = s->img_n + 1; - else - s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, - color, interlace)) - return 0; - if (has_trans) { - if (z->depth == 16) { - if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) - return 0; - } else { - if (!stbi__compute_transparency(z, tc, s->img_out_n)) - return 0; - } - } - if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) - stbi__de_iphone(z); - if (pal_img_n) { - // pal_img_n == 3 or 4 - s->img_n = pal_img_n; // record the actual colors we had - s->img_out_n = pal_img_n; - if (req_comp >= 3) - s->img_out_n = req_comp; - if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) - return 0; - } else if (has_trans) { - // non-paletted image with tRNS -> source image has (constant) alpha - ++s->img_n; - } - STBI_FREE(z->expanded); - z->expanded = NULL; - // end of PNG chunk, read and skip CRC - stbi__get32be(s); - return 1; - } - - default: - // if critical, fail - if (first) - return stbi__err("first not IHDR", "Corrupt PNG"); - if ((c.type & (1 << 29)) == 0) { -#ifndef STBI_NO_FAILURE_STRINGS - // not threadsafe - static char invalid_chunk[] = "XXXX PNG chunk not known"; - invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); - invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); - invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); - invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); -#endif - return stbi__err(invalid_chunk, - "PNG not supported: unknown PNG chunk type"); - } - stbi__skip(s, c.length); - break; - } - // end of PNG chunk, read and skip CRC - stbi__get32be(s); - } -} - -static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) -{ - void *result = NULL; - if (req_comp < 0 || req_comp > 4) - return stbi__errpuc("bad req_comp", "Internal error"); - if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - if (p->depth <= 8) - ri->bits_per_channel = 8; - else if (p->depth == 16) - ri->bits_per_channel = 16; - else - return stbi__errpuc("bad bits_per_channel", - "PNG not supported: unsupported color depth"); - result = p->out; - p->out = NULL; - if (req_comp && req_comp != p->s->img_out_n) { - if (ri->bits_per_channel == 8) - result = stbi__convert_format((unsigned char *)result, - p->s->img_out_n, req_comp, - p->s->img_x, p->s->img_y); - else - result = stbi__convert_format16((stbi__uint16 *)result, - p->s->img_out_n, req_comp, - p->s->img_x, p->s->img_y); - p->s->img_out_n = req_comp; - if (result == NULL) - return result; - } - *x = p->s->img_x; - *y = p->s->img_y; - if (n) - *n = p->s->img_n; - } - STBI_FREE(p->out); - p->out = NULL; - STBI_FREE(p->expanded); - p->expanded = NULL; - STBI_FREE(p->idata); - p->idata = NULL; - - return result; -} - -static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - stbi__png p; - p.s = s; - return stbi__do_png(&p, x, y, comp, req_comp, ri); -} - -static int stbi__png_test(stbi__context *s) -{ - int r; - r = stbi__check_png_header(s); - stbi__rewind(s); - return r; -} - -static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) -{ - if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { - stbi__rewind(p->s); - return 0; - } - if (x) - *x = p->s->img_x; - if (y) - *y = p->s->img_y; - if (comp) - *comp = p->s->img_n; - return 1; -} - -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__png p; - p.s = s; - return stbi__png_info_raw(&p, x, y, comp); -} - -static int stbi__png_is16(stbi__context *s) -{ - stbi__png p; - p.s = s; - if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) - return 0; - if (p.depth != 16) { - stbi__rewind(p.s); - return 0; - } - return 1; -} -#endif - -// Microsoft/Windows BMP image - -#ifndef STBI_NO_BMP -static int stbi__bmp_test_raw(stbi__context *s) -{ - int r; - int sz; - if (stbi__get8(s) != 'B') - return 0; - if (stbi__get8(s) != 'M') - return 0; - stbi__get32le(s); // discard filesize - stbi__get16le(s); // discard reserved - stbi__get16le(s); // discard reserved - stbi__get32le(s); // discard data offset - sz = stbi__get32le(s); - r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); - return r; -} - -static int stbi__bmp_test(stbi__context *s) -{ - int r = stbi__bmp_test_raw(s); - stbi__rewind(s); - return r; -} - -// returns 0..31 for the highest set bit -static int stbi__high_bit(unsigned int z) -{ - int n = 0; - if (z == 0) - return -1; - if (z >= 0x10000) { - n += 16; - z >>= 16; - } - if (z >= 0x00100) { - n += 8; - z >>= 8; - } - if (z >= 0x00010) { - n += 4; - z >>= 4; - } - if (z >= 0x00004) { - n += 2; - z >>= 2; - } - if (z >= 0x00002) { - n += 1; /* >>= 1;*/ - } - return n; -} - -static int stbi__bitcount(unsigned int a) -{ - a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 - a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits - a = (a + (a >> 8)); // max 16 per 8 bits - a = (a + (a >> 16)); // max 32 per 8 bits - return a & 0xff; -} - -// extract an arbitrarily-aligned N-bit value (N=bits) -// from v, and then make it 8-bits long and fractionally -// extend it to full full range. -static int stbi__shiftsigned(unsigned int v, int shift, int bits) -{ - static unsigned int mul_table[9] = { - 0, - 0xff /*0b11111111*/, - 0x55 /*0b01010101*/, - 0x49 /*0b01001001*/, - 0x11 /*0b00010001*/, - 0x21 /*0b00100001*/, - 0x41 /*0b01000001*/, - 0x81 /*0b10000001*/, - 0x01 /*0b00000001*/, - }; - static unsigned int shift_table[9] = { - 0, 0, 0, 1, 0, 2, 4, 6, 0, - }; - if (shift < 0) - v <<= -shift; - else - v >>= shift; - STBI_ASSERT(v < 256); - v >>= (8 - bits); - STBI_ASSERT(bits >= 0 && bits <= 8); - return (int)((unsigned)v * mul_table[bits]) >> shift_table[bits]; -} - -typedef struct { - int bpp, offset, hsz; - unsigned int mr, mg, mb, ma, all_a; - int extra_read; -} stbi__bmp_data; - -static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) -{ - // BI_BITFIELDS specifies masks explicitly, don't override - if (compress == 3) - return 1; - - if (compress == 0) { - if (info->bpp == 16) { - info->mr = 31u << 10; - info->mg = 31u << 5; - info->mb = 31u << 0; - } else if (info->bpp == 32) { - info->mr = 0xffu << 16; - info->mg = 0xffu << 8; - info->mb = 0xffu << 0; - info->ma = 0xffu << 24; - info->all_a = - 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 - } else { - // otherwise, use defaults, which is all-0 - info->mr = info->mg = info->mb = info->ma = 0; - } - return 1; - } - return 0; // error -} - -static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) -{ - int hsz; - if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') - return stbi__errpuc("not BMP", "Corrupt BMP"); - stbi__get32le(s); // discard filesize - stbi__get16le(s); // discard reserved - stbi__get16le(s); // discard reserved - info->offset = stbi__get32le(s); - info->hsz = hsz = stbi__get32le(s); - info->mr = info->mg = info->mb = info->ma = 0; - info->extra_read = 14; - - if (info->offset < 0) - return stbi__errpuc("bad BMP", "bad BMP"); - - if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) - return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); - if (hsz == 12) { - s->img_x = stbi__get16le(s); - s->img_y = stbi__get16le(s); - } else { - s->img_x = stbi__get32le(s); - s->img_y = stbi__get32le(s); - } - if (stbi__get16le(s) != 1) - return stbi__errpuc("bad BMP", "bad BMP"); - info->bpp = stbi__get16le(s); - if (hsz != 12) { - int compress = stbi__get32le(s); - if (compress == 1 || compress == 2) - return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); - if (compress >= 4) - return stbi__errpuc( - "BMP JPEG/PNG", - "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes - if (compress == 3 && info->bpp != 16 && info->bpp != 32) - return stbi__errpuc("bad BMP", - "bad BMP"); // bitfields requires 16 or 32 bits/pixel - stbi__get32le(s); // discard sizeof - stbi__get32le(s); // discard hres - stbi__get32le(s); // discard vres - stbi__get32le(s); // discard colorsused - stbi__get32le(s); // discard max important - if (hsz == 40 || hsz == 56) { - if (hsz == 56) { - stbi__get32le(s); - stbi__get32le(s); - stbi__get32le(s); - stbi__get32le(s); - } - if (info->bpp == 16 || info->bpp == 32) { - if (compress == 0) { - stbi__bmp_set_mask_defaults(info, compress); - } else if (compress == 3) { - info->mr = stbi__get32le(s); - info->mg = stbi__get32le(s); - info->mb = stbi__get32le(s); - info->extra_read += 12; - // not documented, but generated by photoshop and handled by mspaint - if (info->mr == info->mg && info->mg == info->mb) { - // ?!?!? - return stbi__errpuc("bad BMP", "bad BMP"); - } - } else - return stbi__errpuc("bad BMP", "bad BMP"); - } - } else { - // V4/V5 header - int i; - if (hsz != 108 && hsz != 124) - return stbi__errpuc("bad BMP", "bad BMP"); - info->mr = stbi__get32le(s); - info->mg = stbi__get32le(s); - info->mb = stbi__get32le(s); - info->ma = stbi__get32le(s); - if (compress != - 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs - stbi__bmp_set_mask_defaults(info, compress); - stbi__get32le(s); // discard color space - for (i = 0; i < 12; ++i) - stbi__get32le(s); // discard color space parameters - if (hsz == 124) { - stbi__get32le(s); // discard rendering intent - stbi__get32le(s); // discard offset of profile data - stbi__get32le(s); // discard size of profile data - stbi__get32le(s); // discard reserved - } - } - } - return (void *)1; -} - -static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - stbi_uc *out; - unsigned int mr = 0, mg = 0, mb = 0, ma = 0, all_a; - stbi_uc pal[256][4]; - int psize = 0, i, j, width; - int flip_vertically, pad, target; - stbi__bmp_data info; - STBI_NOTUSED(ri); - - info.all_a = 255; - if (stbi__bmp_parse_header(s, &info) == NULL) - return NULL; // error code already set - - flip_vertically = ((int)s->img_y) > 0; - s->img_y = abs((int)s->img_y); - - if (s->img_y > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - - mr = info.mr; - mg = info.mg; - mb = info.mb; - ma = info.ma; - all_a = info.all_a; - - if (info.hsz == 12) { - if (info.bpp < 24) - psize = (info.offset - info.extra_read - 24) / 3; - } else { - if (info.bpp < 16) - psize = (info.offset - info.extra_read - info.hsz) >> 2; - } - if (psize == 0) { - // accept some number of extra bytes after the header, but if the offset points either to before - // the header ends or implies a large amount of extra data, reject the file as malformed - int bytes_read_so_far = - s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); - int header_limit = 1024; // max we actually read is below 256 bytes currently. - int extra_data_limit = - 256 * - 4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. - if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { - return stbi__errpuc("bad header", "Corrupt BMP"); - } - // we established that bytes_read_so_far is positive and sensible. - // the first half of this test rejects offsets that are either too small positives, or - // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn - // ensures the number computed in the second half of the test can't overflow. - if (info.offset < bytes_read_so_far || - info.offset - bytes_read_so_far > extra_data_limit) { - return stbi__errpuc("bad offset", "Corrupt BMP"); - } else { - stbi__skip(s, info.offset - bytes_read_so_far); - } - } - - if (info.bpp == 24 && ma == 0xff000000) - s->img_n = 3; - else - s->img_n = ma ? 4 : 3; - if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 - target = req_comp; - else - target = s->img_n; // if they want monochrome, we'll post-convert - - // sanity-check size - if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) - return stbi__errpuc("too large", "Corrupt BMP"); - - out = (stbi_uc *)stbi__malloc_mad3(target, s->img_x, s->img_y, 0); - if (!out) - return stbi__errpuc("outofmem", "Out of memory"); - if (info.bpp < 16) { - int z = 0; - if (psize == 0 || psize > 256) { - STBI_FREE(out); - return stbi__errpuc("invalid", "Corrupt BMP"); - } - for (i = 0; i < psize; ++i) { - pal[i][2] = stbi__get8(s); - pal[i][1] = stbi__get8(s); - pal[i][0] = stbi__get8(s); - if (info.hsz != 12) - stbi__get8(s); - pal[i][3] = 255; - } - stbi__skip(s, info.offset - info.extra_read - info.hsz - - psize * (info.hsz == 12 ? 3 : 4)); - if (info.bpp == 1) - width = (s->img_x + 7) >> 3; - else if (info.bpp == 4) - width = (s->img_x + 1) >> 1; - else if (info.bpp == 8) - width = s->img_x; - else { - STBI_FREE(out); - return stbi__errpuc("bad bpp", "Corrupt BMP"); - } - pad = (-width) & 3; - if (info.bpp == 1) { - for (j = 0; j < (int)s->img_y; ++j) { - int bit_offset = 7, v = stbi__get8(s); - for (i = 0; i < (int)s->img_x; ++i) { - int color = (v >> bit_offset) & 0x1; - out[z++] = pal[color][0]; - out[z++] = pal[color][1]; - out[z++] = pal[color][2]; - if (target == 4) - out[z++] = 255; - if (i + 1 == (int)s->img_x) - break; - if ((--bit_offset) < 0) { - bit_offset = 7; - v = stbi__get8(s); - } - } - stbi__skip(s, pad); - } - } else { - for (j = 0; j < (int)s->img_y; ++j) { - for (i = 0; i < (int)s->img_x; i += 2) { - int v = stbi__get8(s), v2 = 0; - if (info.bpp == 4) { - v2 = v & 15; - v >>= 4; - } - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) - out[z++] = 255; - if (i + 1 == (int)s->img_x) - break; - v = (info.bpp == 8) ? stbi__get8(s) : v2; - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) - out[z++] = 255; - } - stbi__skip(s, pad); - } - } - } else { - int rshift = 0, gshift = 0, bshift = 0, ashift = 0, rcount = 0, gcount = 0, - bcount = 0, acount = 0; - int z = 0; - int easy = 0; - stbi__skip(s, info.offset - info.extra_read - info.hsz); - if (info.bpp == 24) - width = 3 * s->img_x; - else if (info.bpp == 16) - width = 2 * s->img_x; - else /* bpp = 32 and pad = 0 */ - width = 0; - pad = (-width) & 3; - if (info.bpp == 24) { - easy = 1; - } else if (info.bpp == 32) { - if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) - easy = 2; - } - if (!easy) { - if (!mr || !mg || !mb) { - STBI_FREE(out); - return stbi__errpuc("bad masks", "Corrupt BMP"); - } - // right shift amt to put high bit in position #7 - rshift = stbi__high_bit(mr) - 7; - rcount = stbi__bitcount(mr); - gshift = stbi__high_bit(mg) - 7; - gcount = stbi__bitcount(mg); - bshift = stbi__high_bit(mb) - 7; - bcount = stbi__bitcount(mb); - ashift = stbi__high_bit(ma) - 7; - acount = stbi__bitcount(ma); - if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { - STBI_FREE(out); - return stbi__errpuc("bad masks", "Corrupt BMP"); - } - } - for (j = 0; j < (int)s->img_y; ++j) { - if (easy) { - for (i = 0; i < (int)s->img_x; ++i) { - unsigned char a; - out[z + 2] = stbi__get8(s); - out[z + 1] = stbi__get8(s); - out[z + 0] = stbi__get8(s); - z += 3; - a = (easy == 2 ? stbi__get8(s) : 255); - all_a |= a; - if (target == 4) - out[z++] = a; - } - } else { - int bpp = info.bpp; - for (i = 0; i < (int)s->img_x; ++i) { - stbi__uint32 v = (bpp == 16 ? - (stbi__uint32)stbi__get16le(s) : - stbi__get32le(s)); - unsigned int a; - out[z++] = STBI__BYTECAST( - stbi__shiftsigned(v & mr, rshift, rcount)); - out[z++] = STBI__BYTECAST( - stbi__shiftsigned(v & mg, gshift, gcount)); - out[z++] = STBI__BYTECAST( - stbi__shiftsigned(v & mb, bshift, bcount)); - a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); - all_a |= a; - if (target == 4) - out[z++] = STBI__BYTECAST(a); - } - } - stbi__skip(s, pad); - } - } - - // if alpha channel is all 0s, replace with all 255s - if (target == 4 && all_a == 0) - for (i = 4 * s->img_x * s->img_y - 1; i >= 0; i -= 4) - out[i] = 255; - - if (flip_vertically) { - stbi_uc t; - for (j = 0; j < (int)s->img_y >> 1; ++j) { - stbi_uc *p1 = out + j * s->img_x * target; - stbi_uc *p2 = out + (s->img_y - 1 - j) * s->img_x * target; - for (i = 0; i < (int)s->img_x * target; ++i) { - t = p1[i]; - p1[i] = p2[i]; - p2[i] = t; - } - } - } - - if (req_comp && req_comp != target) { - out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); - if (out == NULL) - return out; // stbi__convert_format frees input on failure - } - - *x = s->img_x; - *y = s->img_y; - if (comp) - *comp = s->img_n; - return out; -} -#endif - -// Targa Truevision - TGA -// by Jonathan Dummer -#ifndef STBI_NO_TGA -// returns STBI_rgb or whatever, 0 on error -static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int *is_rgb16) -{ - // only RGB or RGBA (incl. 16bit) or grey allowed - if (is_rgb16) - *is_rgb16 = 0; - switch (bits_per_pixel) { - case 8: - return STBI_grey; - case 16: - if (is_grey) - return STBI_grey_alpha; - // fallthrough - case 15: - if (is_rgb16) - *is_rgb16 = 1; - return STBI_rgb; - case 24: // fallthrough - case 32: - return bits_per_pixel / 8; - default: - return 0; - } -} - -static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) -{ - int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; - int sz, tga_colormap_type; - stbi__get8(s); // discard Offset - tga_colormap_type = stbi__get8(s); // colormap type - if (tga_colormap_type > 1) { - stbi__rewind(s); - return 0; // only RGB or indexed allowed - } - tga_image_type = stbi__get8(s); // image type - if (tga_colormap_type == 1) { // colormapped (paletted) image - if (tga_image_type != 1 && tga_image_type != 9) { - stbi__rewind(s); - return 0; - } - stbi__skip(s, - 4); // skip index of first colormap entry and number of entries - sz = stbi__get8(s); // check bits per palette color entry - if ((sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32)) { - stbi__rewind(s); - return 0; - } - stbi__skip(s, 4); // skip image x and y origin - tga_colormap_bpp = sz; - } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE - if ((tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && - (tga_image_type != 11)) { - stbi__rewind(s); - return 0; // only RGB or grey allowed, +/- RLE - } - stbi__skip(s, - 9); // skip colormap specification and image x/y origin - tga_colormap_bpp = 0; - } - tga_w = stbi__get16le(s); - if (tga_w < 1) { - stbi__rewind(s); - return 0; // test width - } - tga_h = stbi__get16le(s); - if (tga_h < 1) { - stbi__rewind(s); - return 0; // test height - } - tga_bits_per_pixel = stbi__get8(s); // bits per pixel - stbi__get8(s); // ignore alpha bits - if (tga_colormap_bpp != 0) { - if ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { - // when using a colormap, tga_bits_per_pixel is the size of the indexes - // I don't think anything but 8 or 16bit indexes makes sense - stbi__rewind(s); - return 0; - } - tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); - } else { - tga_comp = stbi__tga_get_comp( - tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); - } - if (!tga_comp) { - stbi__rewind(s); - return 0; - } - if (x) - *x = tga_w; - if (y) - *y = tga_h; - if (comp) - *comp = tga_comp; - return 1; // seems to have passed everything -} - -static int stbi__tga_test(stbi__context *s) -{ - int res = 0; - int sz, tga_color_type; - stbi__get8(s); // discard Offset - tga_color_type = stbi__get8(s); // color type - if (tga_color_type > 1) - goto errorEnd; // only RGB or indexed allowed - sz = stbi__get8(s); // image type - if (tga_color_type == 1) { // colormapped (paletted) image - if (sz != 1 && sz != 9) - goto errorEnd; // colortype 1 demands image type 1 or 9 - stbi__skip(s, - 4); // skip index of first colormap entry and number of entries - sz = stbi__get8(s); // check bits per palette color entry - if ((sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32)) - goto errorEnd; - stbi__skip(s, 4); // skip image x and y origin - } else { // "normal" image w/o colormap - if ((sz != 2) && (sz != 3) && (sz != 10) && (sz != 11)) - goto errorEnd; // only RGB or grey allowed, +/- RLE - stbi__skip(s, - 9); // skip colormap specification and image x/y origin - } - if (stbi__get16le(s) < 1) - goto errorEnd; // test width - if (stbi__get16le(s) < 1) - goto errorEnd; // test height - sz = stbi__get8(s); // bits per pixel - if ((tga_color_type == 1) && (sz != 8) && (sz != 16)) - goto errorEnd; // for colormapped images, bpp is size of an index - if ((sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32)) - goto errorEnd; - - res = 1; // if we got this far, everything's good and we can return 1 instead of 0 - -errorEnd: - stbi__rewind(s); - return res; -} - -// read 16bit value and convert to 24bit RGB -static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc *out) -{ - stbi__uint16 px = (stbi__uint16)stbi__get16le(s); - stbi__uint16 fiveBitMask = 31; - // we have 3 channels with 5bits each - int r = (px >> 10) & fiveBitMask; - int g = (px >> 5) & fiveBitMask; - int b = px & fiveBitMask; - // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later - out[0] = (stbi_uc)((r * 255) / 31); - out[1] = (stbi_uc)((g * 255) / 31); - out[2] = (stbi_uc)((b * 255) / 31); - - // some people claim that the most significant bit might be used for alpha - // (possibly if an alpha-bit is set in the "image descriptor byte") - // but that only made 16bit test images completely translucent.. - // so let's treat all 15 and 16bit TGAs as RGB with no alpha. -} - -static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - // read in the TGA header stuff - int tga_offset = stbi__get8(s); - int tga_indexed = stbi__get8(s); - int tga_image_type = stbi__get8(s); - int tga_is_RLE = 0; - int tga_palette_start = stbi__get16le(s); - int tga_palette_len = stbi__get16le(s); - int tga_palette_bits = stbi__get8(s); - int tga_x_origin = stbi__get16le(s); - int tga_y_origin = stbi__get16le(s); - int tga_width = stbi__get16le(s); - int tga_height = stbi__get16le(s); - int tga_bits_per_pixel = stbi__get8(s); - int tga_comp, tga_rgb16 = 0; - int tga_inverted = stbi__get8(s); - // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) - // image data - unsigned char *tga_data; - unsigned char *tga_palette = NULL; - int i, j; - unsigned char raw_data[4] = { 0 }; - int RLE_count = 0; - int RLE_repeating = 0; - int read_next_pixel = 1; - STBI_NOTUSED(ri); - STBI_NOTUSED(tga_x_origin); // @TODO - STBI_NOTUSED(tga_y_origin); // @TODO - - if (tga_height > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - if (tga_width > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - - // do a tiny bit of precessing - if (tga_image_type >= 8) { - tga_image_type -= 8; - tga_is_RLE = 1; - } - tga_inverted = 1 - ((tga_inverted >> 5) & 1); - - // If I'm paletted, then I'll use the number of bits from the palette - if (tga_indexed) - tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); - else - tga_comp = - stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); - - if (!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency - return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); - - // tga info - *x = tga_width; - *y = tga_height; - if (comp) - *comp = tga_comp; - - if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) - return stbi__errpuc("too large", "Corrupt TGA"); - - tga_data = (unsigned char *)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); - if (!tga_data) - return stbi__errpuc("outofmem", "Out of memory"); - - // skip to the data's starting position (offset usually = 0) - stbi__skip(s, tga_offset); - - if (!tga_indexed && !tga_is_RLE && !tga_rgb16) { - for (i = 0; i < tga_height; ++i) { - int row = tga_inverted ? tga_height - i - 1 : i; - stbi_uc *tga_row = tga_data + row * tga_width * tga_comp; - stbi__getn(s, tga_row, tga_width * tga_comp); - } - } else { - // do I need to load a palette? - if (tga_indexed) { - if (tga_palette_len == 0) { /* you have to have at least one entry! */ - STBI_FREE(tga_data); - return stbi__errpuc("bad palette", "Corrupt TGA"); - } - - // any data to skip? (offset usually = 0) - stbi__skip(s, tga_palette_start); - // load the palette - tga_palette = - (unsigned char *)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); - if (!tga_palette) { - STBI_FREE(tga_data); - return stbi__errpuc("outofmem", "Out of memory"); - } - if (tga_rgb16) { - stbi_uc *pal_entry = tga_palette; - STBI_ASSERT(tga_comp == STBI_rgb); - for (i = 0; i < tga_palette_len; ++i) { - stbi__tga_read_rgb16(s, pal_entry); - pal_entry += tga_comp; - } - } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { - STBI_FREE(tga_data); - STBI_FREE(tga_palette); - return stbi__errpuc("bad palette", "Corrupt TGA"); - } - } - // load the data - for (i = 0; i < tga_width * tga_height; ++i) { - // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? - if (tga_is_RLE) { - if (RLE_count == 0) { - // yep, get the next byte as a RLE command - int RLE_cmd = stbi__get8(s); - RLE_count = 1 + (RLE_cmd & 127); - RLE_repeating = RLE_cmd >> 7; - read_next_pixel = 1; - } else if (!RLE_repeating) { - read_next_pixel = 1; - } - } else { - read_next_pixel = 1; - } - // OK, if I need to read a pixel, do it now - if (read_next_pixel) { - // load however much data we did have - if (tga_indexed) { - // read in index, then perform the lookup - int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : - stbi__get16le(s); - if (pal_idx >= tga_palette_len) { - // invalid index - pal_idx = 0; - } - pal_idx *= tga_comp; - for (j = 0; j < tga_comp; ++j) { - raw_data[j] = tga_palette[pal_idx + j]; - } - } else if (tga_rgb16) { - STBI_ASSERT(tga_comp == STBI_rgb); - stbi__tga_read_rgb16(s, raw_data); - } else { - // read in the data raw - for (j = 0; j < tga_comp; ++j) { - raw_data[j] = stbi__get8(s); - } - } - // clear the reading flag for the next pixel - read_next_pixel = 0; - } // end of reading a pixel - - // copy data - for (j = 0; j < tga_comp; ++j) - tga_data[i * tga_comp + j] = raw_data[j]; - - // in case we're in RLE mode, keep counting down - --RLE_count; - } - // do I need to invert the image? - if (tga_inverted) { - for (j = 0; j * 2 < tga_height; ++j) { - int index1 = j * tga_width * tga_comp; - int index2 = (tga_height - 1 - j) * tga_width * tga_comp; - for (i = tga_width * tga_comp; i > 0; --i) { - unsigned char temp = tga_data[index1]; - tga_data[index1] = tga_data[index2]; - tga_data[index2] = temp; - ++index1; - ++index2; - } - } - } - // clear my palette, if I had one - if (tga_palette != NULL) { - STBI_FREE(tga_palette); - } - } - - // swap RGB - if the source data was RGB16, it already is in the right order - if (tga_comp >= 3 && !tga_rgb16) { - unsigned char *tga_pixel = tga_data; - for (i = 0; i < tga_width * tga_height; ++i) { - unsigned char temp = tga_pixel[0]; - tga_pixel[0] = tga_pixel[2]; - tga_pixel[2] = temp; - tga_pixel += tga_comp; - } - } - - // convert to target component count - if (req_comp && req_comp != tga_comp) - tga_data = - stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); - - // the things I do to get rid of an error message, and yet keep - // Microsoft's C compilers happy... [8^( - tga_palette_start = tga_palette_len = tga_palette_bits = tga_x_origin = tga_y_origin = 0; - STBI_NOTUSED(tga_palette_start); - // OK, done - return tga_data; -} -#endif - -// ************************************************************************************************* -// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB - -#ifndef STBI_NO_PSD -static int stbi__psd_test(stbi__context *s) -{ - int r = (stbi__get32be(s) == 0x38425053); - stbi__rewind(s); - return r; -} - -static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) -{ - int count, nleft, len; - - count = 0; - while ((nleft = pixelCount - count) > 0) { - len = stbi__get8(s); - if (len == 128) { - // No-op. - } else if (len < 128) { - // Copy next len+1 bytes literally. - len++; - if (len > nleft) - return 0; // corrupt data - count += len; - while (len) { - *p = stbi__get8(s); - p += 4; - len--; - } - } else if (len > 128) { - stbi_uc val; - // Next -len+1 bytes in the dest are replicated from next source byte. - // (Interpret len as a negative 8-bit int.) - len = 257 - len; - if (len > nleft) - return 0; // corrupt data - val = stbi__get8(s); - count += len; - while (len) { - *p = val; - p += 4; - len--; - } - } - } - - return 1; -} - -static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri, int bpc) -{ - int pixelCount; - int channelCount, compression; - int channel, i; - int bitdepth; - int w, h; - stbi_uc *out; - STBI_NOTUSED(ri); - - // Check identifier - if (stbi__get32be(s) != 0x38425053) // "8BPS" - return stbi__errpuc("not PSD", "Corrupt PSD image"); - - // Check file type version. - if (stbi__get16be(s) != 1) - return stbi__errpuc("wrong version", "Unsupported version of PSD image"); - - // Skip 6 reserved bytes. - stbi__skip(s, 6); - - // Read the number of channels (R, G, B, A, etc). - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) - return stbi__errpuc("wrong channel count", - "Unsupported number of channels in PSD image"); - - // Read the rows and columns of the image. - h = stbi__get32be(s); - w = stbi__get32be(s); - - if (h > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - if (w > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - - // Make sure the depth is 8 bits. - bitdepth = stbi__get16be(s); - if (bitdepth != 8 && bitdepth != 16) - return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); - - // Make sure the color mode is RGB. - // Valid options are: - // 0: Bitmap - // 1: Grayscale - // 2: Indexed color - // 3: RGB color - // 4: CMYK color - // 7: Multichannel - // 8: Duotone - // 9: Lab color - if (stbi__get16be(s) != 3) - return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); - - // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) - stbi__skip(s, stbi__get32be(s)); - - // Skip the image resources. (resolution, pen tool paths, etc) - stbi__skip(s, stbi__get32be(s)); - - // Skip the reserved data. - stbi__skip(s, stbi__get32be(s)); - - // Find out if the data is compressed. - // Known values: - // 0: no compression - // 1: RLE compressed - compression = stbi__get16be(s); - if (compression > 1) - return stbi__errpuc("bad compression", "PSD has an unknown compression format"); - - // Check size - if (!stbi__mad3sizes_valid(4, w, h, 0)) - return stbi__errpuc("too large", "Corrupt PSD"); - - // Create the destination image. - - if (!compression && bitdepth == 16 && bpc == 16) { - out = (stbi_uc *)stbi__malloc_mad3(8, w, h, 0); - ri->bits_per_channel = 16; - } else - out = (stbi_uc *)stbi__malloc(4 * w * h); - - if (!out) - return stbi__errpuc("outofmem", "Out of memory"); - pixelCount = w * h; - - // Initialize the data to zero. - //memset( out, 0, pixelCount * 4 ); - - // Finally, the image data. - if (compression) { - // RLE as used by .PSD and .TIFF - // Loop until you get the number of unpacked bytes you are expecting: - // Read the next source byte into n. - // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. - // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. - // Else if n is 128, noop. - // Endloop - - // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, - // which we're going to just skip. - stbi__skip(s, h * channelCount * 2); - - // Read the RLE data by channel. - for (channel = 0; channel < 4; channel++) { - stbi_uc *p; - - p = out + channel; - if (channel >= channelCount) { - // Fill this channel with default data. - for (i = 0; i < pixelCount; i++, p += 4) - *p = (channel == 3 ? 255 : 0); - } else { - // Read the RLE data. - if (!stbi__psd_decode_rle(s, p, pixelCount)) { - STBI_FREE(out); - return stbi__errpuc("corrupt", "bad RLE data"); - } - } - } - } else { - // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) - // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. - - // Read the data by channel. - for (channel = 0; channel < 4; channel++) { - if (channel >= channelCount) { - // Fill this channel with default data. - if (bitdepth == 16 && bpc == 16) { - stbi__uint16 *q = ((stbi__uint16 *)out) + channel; - stbi__uint16 val = channel == 3 ? 65535 : 0; - for (i = 0; i < pixelCount; i++, q += 4) - *q = val; - } else { - stbi_uc *p = out + channel; - stbi_uc val = channel == 3 ? 255 : 0; - for (i = 0; i < pixelCount; i++, p += 4) - *p = val; - } - } else { - if (ri->bits_per_channel == 16) { // output bpc - stbi__uint16 *q = ((stbi__uint16 *)out) + channel; - for (i = 0; i < pixelCount; i++, q += 4) - *q = (stbi__uint16)stbi__get16be(s); - } else { - stbi_uc *p = out + channel; - if (bitdepth == 16) { // input bpc - for (i = 0; i < pixelCount; i++, p += 4) - *p = (stbi_uc)(stbi__get16be(s) >> 8); - } else { - for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get8(s); - } - } - } - } - } - - // remove weird white matte from PSD - if (channelCount >= 4) { - if (ri->bits_per_channel == 16) { - for (i = 0; i < w * h; ++i) { - stbi__uint16 *pixel = (stbi__uint16 *)out + 4 * i; - if (pixel[3] != 0 && pixel[3] != 65535) { - float a = pixel[3] / 65535.0f; - float ra = 1.0f / a; - float inv_a = 65535.0f * (1 - ra); - pixel[0] = (stbi__uint16)(pixel[0] * ra + inv_a); - pixel[1] = (stbi__uint16)(pixel[1] * ra + inv_a); - pixel[2] = (stbi__uint16)(pixel[2] * ra + inv_a); - } - } - } else { - for (i = 0; i < w * h; ++i) { - unsigned char *pixel = out + 4 * i; - if (pixel[3] != 0 && pixel[3] != 255) { - float a = pixel[3] / 255.0f; - float ra = 1.0f / a; - float inv_a = 255.0f * (1 - ra); - pixel[0] = (unsigned char)(pixel[0] * ra + inv_a); - pixel[1] = (unsigned char)(pixel[1] * ra + inv_a); - pixel[2] = (unsigned char)(pixel[2] * ra + inv_a); - } - } - } - } - - // convert to desired output format - if (req_comp && req_comp != 4) { - if (ri->bits_per_channel == 16) - out = (stbi_uc *)stbi__convert_format16((stbi__uint16 *)out, 4, req_comp, w, - h); - else - out = stbi__convert_format(out, 4, req_comp, w, h); - if (out == NULL) - return out; // stbi__convert_format frees input on failure - } - - if (comp) - *comp = 4; - *y = h; - *x = w; - - return out; -} -#endif - -// ************************************************************************************************* -// Softimage PIC loader -// by Tom Seddon -// -// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format -// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ - -#ifndef STBI_NO_PIC -static int stbi__pic_is4(stbi__context *s, const char *str) -{ - int i; - for (i = 0; i < 4; ++i) - if (stbi__get8(s) != (stbi_uc)str[i]) - return 0; - - return 1; -} - -static int stbi__pic_test_core(stbi__context *s) -{ - int i; - - if (!stbi__pic_is4(s, "\x53\x80\xF6\x34")) - return 0; - - for (i = 0; i < 84; ++i) - stbi__get8(s); - - if (!stbi__pic_is4(s, "PICT")) - return 0; - - return 1; -} - -typedef struct { - stbi_uc size, type, channel; -} stbi__pic_packet; - -static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) -{ - int mask = 0x80, i; - - for (i = 0; i < 4; ++i, mask >>= 1) { - if (channel & mask) { - if (stbi__at_eof(s)) - return stbi__errpuc("bad file", "PIC file too short"); - dest[i] = stbi__get8(s); - } - } - - return dest; -} - -static void stbi__copyval(int channel, stbi_uc *dest, const stbi_uc *src) -{ - int mask = 0x80, i; - - for (i = 0; i < 4; ++i, mask >>= 1) - if (channel & mask) - dest[i] = src[i]; -} - -static stbi_uc *stbi__pic_load_core(stbi__context *s, int width, int height, int *comp, - stbi_uc *result) -{ - int act_comp = 0, num_packets = 0, y, chained; - stbi__pic_packet packets[10]; - - // this will (should...) cater for even some bizarre stuff like having data - // for the same channel in multiple packets. - do { - stbi__pic_packet *packet; - - if (num_packets == sizeof(packets) / sizeof(packets[0])) - return stbi__errpuc("bad format", "too many packets"); - - packet = &packets[num_packets++]; - - chained = stbi__get8(s); - packet->size = stbi__get8(s); - packet->type = stbi__get8(s); - packet->channel = stbi__get8(s); - - act_comp |= packet->channel; - - if (stbi__at_eof(s)) - return stbi__errpuc("bad file", "file too short (reading packets)"); - if (packet->size != 8) - return stbi__errpuc("bad format", "packet isn't 8bpp"); - } while (chained); - - *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? - - for (y = 0; y < height; ++y) { - int packet_idx; - - for (packet_idx = 0; packet_idx < num_packets; ++packet_idx) { - stbi__pic_packet *packet = &packets[packet_idx]; - stbi_uc *dest = result + y * width * 4; - - switch (packet->type) { - default: - return stbi__errpuc("bad format", - "packet has bad compression type"); - - case 0: { //uncompressed - int x; - - for (x = 0; x < width; ++x, dest += 4) - if (!stbi__readval(s, packet->channel, dest)) - return 0; - break; - } - - case 1: //Pure RLE - { - int left = width, i; - - while (left > 0) { - stbi_uc count, value[4]; - - count = stbi__get8(s); - if (stbi__at_eof(s)) - return stbi__errpuc( - "bad file", - "file too short (pure read count)"); - - if (count > left) - count = (stbi_uc)left; - - if (!stbi__readval(s, packet->channel, value)) - return 0; - - for (i = 0; i < count; ++i, dest += 4) - stbi__copyval(packet->channel, dest, value); - left -= count; - } - } break; - - case 2: { //Mixed RLE - int left = width; - while (left > 0) { - int count = stbi__get8(s), i; - if (stbi__at_eof(s)) - return stbi__errpuc( - "bad file", - "file too short (mixed read count)"); - - if (count >= 128) { // Repeated - stbi_uc value[4]; - - if (count == 128) - count = stbi__get16be(s); - else - count -= 127; - if (count > left) - return stbi__errpuc("bad file", - "scanline overrun"); - - if (!stbi__readval(s, packet->channel, value)) - return 0; - - for (i = 0; i < count; ++i, dest += 4) - stbi__copyval(packet->channel, dest, value); - } else { // Raw - ++count; - if (count > left) - return stbi__errpuc("bad file", - "scanline overrun"); - - for (i = 0; i < count; ++i, dest += 4) - if (!stbi__readval(s, packet->channel, - dest)) - return 0; - } - left -= count; - } - break; - } - } - } - } - - return result; -} - -static void *stbi__pic_load(stbi__context *s, int *px, int *py, int *comp, int req_comp, - stbi__result_info *ri) -{ - stbi_uc *result; - int i, x, y, internal_comp; - STBI_NOTUSED(ri); - - if (!comp) - comp = &internal_comp; - - for (i = 0; i < 92; ++i) - stbi__get8(s); - - x = stbi__get16be(s); - y = stbi__get16be(s); - - if (y > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - if (x > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - - if (stbi__at_eof(s)) - return stbi__errpuc("bad file", "file too short (pic header)"); - if (!stbi__mad3sizes_valid(x, y, 4, 0)) - return stbi__errpuc("too large", "PIC image too large to decode"); - - stbi__get32be(s); //skip `ratio' - stbi__get16be(s); //skip `fields' - stbi__get16be(s); //skip `pad' - - // intermediate buffer is RGBA - result = (stbi_uc *)stbi__malloc_mad3(x, y, 4, 0); - if (!result) - return stbi__errpuc("outofmem", "Out of memory"); - memset(result, 0xff, x * y * 4); - - if (!stbi__pic_load_core(s, x, y, comp, result)) { - STBI_FREE(result); - result = 0; - } - *px = x; - *py = y; - if (req_comp == 0) - req_comp = *comp; - result = stbi__convert_format(result, 4, req_comp, x, y); - - return result; -} - -static int stbi__pic_test(stbi__context *s) -{ - int r = stbi__pic_test_core(s); - stbi__rewind(s); - return r; -} -#endif - -// ************************************************************************************************* -// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb - -#ifndef STBI_NO_GIF -typedef struct { - stbi__int16 prefix; - stbi_uc first; - stbi_uc suffix; -} stbi__gif_lzw; - -typedef struct { - int w, h; - stbi_uc *out; // output buffer (always 4 components) - stbi_uc *background; // The current "background" as far as a gif is concerned - stbi_uc *history; - int flags, bgindex, ratio, transparent, eflags; - stbi_uc pal[256][4]; - stbi_uc lpal[256][4]; - stbi__gif_lzw codes[8192]; - stbi_uc *color_table; - int parse, step; - int lflags; - int start_x, start_y; - int max_x, max_y; - int cur_x, cur_y; - int line_size; - int delay; -} stbi__gif; - -static int stbi__gif_test_raw(stbi__context *s) -{ - int sz; - if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || - stbi__get8(s) != '8') - return 0; - sz = stbi__get8(s); - if (sz != '9' && sz != '7') - return 0; - if (stbi__get8(s) != 'a') - return 0; - return 1; -} - -static int stbi__gif_test(stbi__context *s) -{ - int r = stbi__gif_test_raw(s); - stbi__rewind(s); - return r; -} - -static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, - int transp) -{ - int i; - for (i = 0; i < num_entries; ++i) { - pal[i][2] = stbi__get8(s); - pal[i][1] = stbi__get8(s); - pal[i][0] = stbi__get8(s); - pal[i][3] = transp == i ? 0 : 255; - } -} - -static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) -{ - stbi_uc version; - if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || - stbi__get8(s) != '8') - return stbi__err("not GIF", "Corrupt GIF"); - - version = stbi__get8(s); - if (version != '7' && version != '9') - return stbi__err("not GIF", "Corrupt GIF"); - if (stbi__get8(s) != 'a') - return stbi__err("not GIF", "Corrupt GIF"); - - stbi__g_failure_reason = ""; - g->w = stbi__get16le(s); - g->h = stbi__get16le(s); - g->flags = stbi__get8(s); - g->bgindex = stbi__get8(s); - g->ratio = stbi__get8(s); - g->transparent = -1; - - if (g->w > STBI_MAX_DIMENSIONS) - return stbi__err("too large", "Very large image (corrupt?)"); - if (g->h > STBI_MAX_DIMENSIONS) - return stbi__err("too large", "Very large image (corrupt?)"); - - if (comp != 0) - *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments - - if (is_info) - return 1; - - if (g->flags & 0x80) - stbi__gif_parse_colortable(s, g->pal, 2 << (g->flags & 7), -1); - - return 1; -} - -static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__gif *g = (stbi__gif *)stbi__malloc(sizeof(stbi__gif)); - if (!g) - return stbi__err("outofmem", "Out of memory"); - if (!stbi__gif_header(s, g, comp, 1)) { - STBI_FREE(g); - stbi__rewind(s); - return 0; - } - if (x) - *x = g->w; - if (y) - *y = g->h; - STBI_FREE(g); - return 1; -} - -static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) -{ - stbi_uc *p, *c; - int idx; - - // recurse to decode the prefixes, since the linked-list is backwards, - // and working backwards through an interleaved image would be nasty - if (g->codes[code].prefix >= 0) - stbi__out_gif_code(g, g->codes[code].prefix); - - if (g->cur_y >= g->max_y) - return; - - idx = g->cur_x + g->cur_y; - p = &g->out[idx]; - g->history[idx / 4] = 1; - - c = &g->color_table[g->codes[code].suffix * 4]; - if (c[3] > 128) { // don't render transparent pixels; - p[0] = c[2]; - p[1] = c[1]; - p[2] = c[0]; - p[3] = c[3]; - } - g->cur_x += 4; - - if (g->cur_x >= g->max_x) { - g->cur_x = g->start_x; - g->cur_y += g->step; - - while (g->cur_y >= g->max_y && g->parse > 0) { - g->step = (1 << g->parse) * g->line_size; - g->cur_y = g->start_y + (g->step >> 1); - --g->parse; - } - } -} - -static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) -{ - stbi_uc lzw_cs; - stbi__int32 len, init_code; - stbi__uint32 first; - stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; - stbi__gif_lzw *p; - - lzw_cs = stbi__get8(s); - if (lzw_cs > 12) - return NULL; - clear = 1 << lzw_cs; - first = 1; - codesize = lzw_cs + 1; - codemask = (1 << codesize) - 1; - bits = 0; - valid_bits = 0; - for (init_code = 0; init_code < clear; init_code++) { - g->codes[init_code].prefix = -1; - g->codes[init_code].first = (stbi_uc)init_code; - g->codes[init_code].suffix = (stbi_uc)init_code; - } - - // support no starting clear code - avail = clear + 2; - oldcode = -1; - - len = 0; - for (;;) { - if (valid_bits < codesize) { - if (len == 0) { - len = stbi__get8(s); // start new block - if (len == 0) - return g->out; - } - --len; - bits |= (stbi__int32)stbi__get8(s) << valid_bits; - valid_bits += 8; - } else { - stbi__int32 code = bits & codemask; - bits >>= codesize; - valid_bits -= codesize; - // @OPTIMIZE: is there some way we can accelerate the non-clear path? - if (code == clear) { // clear code - codesize = lzw_cs + 1; - codemask = (1 << codesize) - 1; - avail = clear + 2; - oldcode = -1; - first = 0; - } else if (code == clear + 1) { // end of stream code - stbi__skip(s, len); - while ((len = stbi__get8(s)) > 0) - stbi__skip(s, len); - return g->out; - } else if (code <= avail) { - if (first) { - return stbi__errpuc("no clear code", "Corrupt GIF"); - } - - if (oldcode >= 0) { - p = &g->codes[avail++]; - if (avail > 8192) { - return stbi__errpuc("too many codes", - "Corrupt GIF"); - } - - p->prefix = (stbi__int16)oldcode; - p->first = g->codes[oldcode].first; - p->suffix = (code == avail) ? p->first : - g->codes[code].first; - } else if (code == avail) - return stbi__errpuc("illegal code in raster", - "Corrupt GIF"); - - stbi__out_gif_code(g, (stbi__uint16)code); - - if ((avail & codemask) == 0 && avail <= 0x0FFF) { - codesize++; - codemask = (1 << codesize) - 1; - } - - oldcode = code; - } else { - return stbi__errpuc("illegal code in raster", "Corrupt GIF"); - } - } - } -} - -// this function is designed to support animated gifs, although stb_image doesn't support it -// two back is the image from two frames ago, used for a very specific disposal format -static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, - stbi_uc *two_back) -{ - int dispose; - int first_frame; - int pi; - int pcount; - STBI_NOTUSED(req_comp); - - // on first frame, any non-written pixels get the background colour (non-transparent) - first_frame = 0; - if (g->out == 0) { - if (!stbi__gif_header(s, g, comp, 0)) - return 0; // stbi__g_failure_reason set by stbi__gif_header - if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) - return stbi__errpuc("too large", "GIF image is too large"); - pcount = g->w * g->h; - g->out = (stbi_uc *)stbi__malloc(4 * pcount); - g->background = (stbi_uc *)stbi__malloc(4 * pcount); - g->history = (stbi_uc *)stbi__malloc(pcount); - if (!g->out || !g->background || !g->history) - return stbi__errpuc("outofmem", "Out of memory"); - - // image is treated as "transparent" at the start - ie, nothing overwrites the current background; - // background colour is only used for pixels that are not rendered first frame, after that "background" - // color refers to the color that was there the previous frame. - memset(g->out, 0x00, 4 * pcount); - memset(g->background, 0x00, - 4 * pcount); // state of the background (starts transparent) - memset(g->history, 0x00, - pcount); // pixels that were affected previous frame - first_frame = 1; - } else { - // second frame - how do we dispose of the previous one? - dispose = (g->eflags & 0x1C) >> 2; - pcount = g->w * g->h; - - if ((dispose == 3) && (two_back == 0)) { - dispose = - 2; // if I don't have an image to revert back to, default to the old background - } - - if (dispose == 3) { // use previous graphic - for (pi = 0; pi < pcount; ++pi) { - if (g->history[pi]) { - memcpy(&g->out[pi * 4], &two_back[pi * 4], 4); - } - } - } else if (dispose == 2) { - // restore what was changed last frame to background before that frame; - for (pi = 0; pi < pcount; ++pi) { - if (g->history[pi]) { - memcpy(&g->out[pi * 4], &g->background[pi * 4], 4); - } - } - } else { - // This is a non-disposal case eithe way, so just - // leave the pixels as is, and they will become the new background - // 1: do not dispose - // 0: not specified. - } - - // background is what out is after the undoing of the previou frame; - memcpy(g->background, g->out, 4 * g->w * g->h); - } - - // clear my history; - memset(g->history, 0x00, - g->w * g->h); // pixels that were affected previous frame - - for (;;) { - int tag = stbi__get8(s); - switch (tag) { - case 0x2C: /* Image Descriptor */ - { - stbi__int32 x, y, w, h; - stbi_uc *o; - - x = stbi__get16le(s); - y = stbi__get16le(s); - w = stbi__get16le(s); - h = stbi__get16le(s); - if (((x + w) > (g->w)) || ((y + h) > (g->h))) - return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); - - g->line_size = g->w * 4; - g->start_x = x * 4; - g->start_y = y * g->line_size; - g->max_x = g->start_x + w * 4; - g->max_y = g->start_y + h * g->line_size; - g->cur_x = g->start_x; - g->cur_y = g->start_y; - - // if the width of the specified rectangle is 0, that means - // we may not see *any* pixels or the image is malformed; - // to make sure this is caught, move the current y down to - // max_y (which is what out_gif_code checks). - if (w == 0) - g->cur_y = g->max_y; - - g->lflags = stbi__get8(s); - - if (g->lflags & 0x40) { - g->step = 8 * g->line_size; // first interlaced spacing - g->parse = 3; - } else { - g->step = g->line_size; - g->parse = 0; - } - - if (g->lflags & 0x80) { - stbi__gif_parse_colortable(s, g->lpal, 2 << (g->lflags & 7), - g->eflags & 0x01 ? g->transparent : -1); - g->color_table = (stbi_uc *)g->lpal; - } else if (g->flags & 0x80) { - g->color_table = (stbi_uc *)g->pal; - } else - return stbi__errpuc("missing color table", "Corrupt GIF"); - - o = stbi__process_gif_raster(s, g); - if (!o) - return NULL; - - // if this was the first frame, - pcount = g->w * g->h; - if (first_frame && (g->bgindex > 0)) { - // if first frame, any pixel not drawn to gets the background color - for (pi = 0; pi < pcount; ++pi) { - if (g->history[pi] == 0) { - g->pal[g->bgindex][3] = - 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; - memcpy(&g->out[pi * 4], &g->pal[g->bgindex], 4); - } - } - } - - return o; - } - - case 0x21: // Comment Extension. - { - int len; - int ext = stbi__get8(s); - if (ext == 0xF9) { // Graphic Control Extension. - len = stbi__get8(s); - if (len == 4) { - g->eflags = stbi__get8(s); - g->delay = - 10 * - stbi__get16le( - s); // delay - 1/100th of a second, saving as 1/1000ths. - - // unset old transparent - if (g->transparent >= 0) { - g->pal[g->transparent][3] = 255; - } - if (g->eflags & 0x01) { - g->transparent = stbi__get8(s); - if (g->transparent >= 0) { - g->pal[g->transparent][3] = 0; - } - } else { - // don't need transparent - stbi__skip(s, 1); - g->transparent = -1; - } - } else { - stbi__skip(s, len); - break; - } - } - while ((len = stbi__get8(s)) != 0) { - stbi__skip(s, len); - } - break; - } - - case 0x3B: // gif stream termination code - return (stbi_uc *)s; // using '1' causes warning on some compilers - - default: - return stbi__errpuc("unknown code", "Corrupt GIF"); - } - } -} - -static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) -{ - STBI_FREE(g->out); - STBI_FREE(g->history); - STBI_FREE(g->background); - - if (out) - STBI_FREE(out); - if (delays && *delays) - STBI_FREE(*delays); - return stbi__errpuc("outofmem", "Out of memory"); -} - -static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, - int req_comp) -{ - if (stbi__gif_test(s)) { - int layers = 0; - stbi_uc *u = 0; - stbi_uc *out = 0; - stbi_uc *two_back = 0; - stbi__gif g; - int stride; - int out_size = 0; - int delays_size = 0; - - STBI_NOTUSED(out_size); - STBI_NOTUSED(delays_size); - - memset(&g, 0, sizeof(g)); - if (delays) { - *delays = 0; - } - - do { - u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); - if (u == (stbi_uc *)s) - u = 0; // end of animated gif marker - - if (u) { - *x = g.w; - *y = g.h; - ++layers; - stride = g.w * g.h * 4; - - if (out) { - void *tmp = (stbi_uc *)STBI_REALLOC_SIZED(out, out_size, - layers * stride); - if (!tmp) - return stbi__load_gif_main_outofmem(&g, out, - delays); - else { - out = (stbi_uc *)tmp; - out_size = layers * stride; - } - - if (delays) { - int *new_delays = (int *)STBI_REALLOC_SIZED( - *delays, delays_size, sizeof(int) * layers); - if (!new_delays) - return stbi__load_gif_main_outofmem(&g, out, - delays); - *delays = new_delays; - delays_size = layers * sizeof(int); - } - } else { - out = (stbi_uc *)stbi__malloc(layers * stride); - if (!out) - return stbi__load_gif_main_outofmem(&g, out, - delays); - out_size = layers * stride; - if (delays) { - *delays = (int *)stbi__malloc(layers * sizeof(int)); - if (!*delays) - return stbi__load_gif_main_outofmem(&g, out, - delays); - delays_size = layers * sizeof(int); - } - } - memcpy(out + ((layers - 1) * stride), u, stride); - if (layers >= 2) { - two_back = out - 2 * stride; - } - - if (delays) { - (*delays)[layers - 1U] = g.delay; - } - } - } while (u != 0); - - // free temp buffer; - STBI_FREE(g.out); - STBI_FREE(g.history); - STBI_FREE(g.background); - - // do the final conversion after loading everything; - if (req_comp && req_comp != 4) - out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); - - *z = layers; - return out; - } else { - return stbi__errpuc("not GIF", "Image was not as a gif type."); - } -} - -static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - stbi_uc *u = 0; - stbi__gif g; - memset(&g, 0, sizeof(g)); - STBI_NOTUSED(ri); - - u = stbi__gif_load_next(s, &g, comp, req_comp, 0); - if (u == (stbi_uc *)s) - u = 0; // end of animated gif marker - if (u) { - *x = g.w; - *y = g.h; - - // moved conversion to after successful load so that the same - // can be done for multiple frames. - if (req_comp && req_comp != 4) - u = stbi__convert_format(u, 4, req_comp, g.w, g.h); - } else if (g.out) { - // if there was an error and we allocated an image buffer, free it! - STBI_FREE(g.out); - } - - // free buffers needed for multiple frame loading; - STBI_FREE(g.history); - STBI_FREE(g.background); - - return u; -} - -static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) -{ - return stbi__gif_info_raw(s, x, y, comp); -} -#endif - -// ************************************************************************************************* -// Radiance RGBE HDR loader -// originally by Nicolas Schulz -#ifndef STBI_NO_HDR -static int stbi__hdr_test_core(stbi__context *s, const char *signature) -{ - int i; - for (i = 0; signature[i]; ++i) - if (stbi__get8(s) != signature[i]) - return 0; - stbi__rewind(s); - return 1; -} - -static int stbi__hdr_test(stbi__context *s) -{ - int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); - stbi__rewind(s); - if (!r) { - r = stbi__hdr_test_core(s, "#?RGBE\n"); - stbi__rewind(s); - } - return r; -} - -#define STBI__HDR_BUFLEN 1024 -static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) -{ - int len = 0; - char c = '\0'; - - c = (char)stbi__get8(z); - - while (!stbi__at_eof(z) && c != '\n') { - buffer[len++] = c; - if (len == STBI__HDR_BUFLEN - 1) { - // flush to end of line - while (!stbi__at_eof(z) && stbi__get8(z) != '\n') - ; - break; - } - c = (char)stbi__get8(z); - } - - buffer[len] = 0; - return buffer; -} - -static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) -{ - if (input[3] != 0) { - float f1; - // Exponent - f1 = (float)ldexp(1.0f, input[3] - (int)(128 + 8)); - if (req_comp <= 2) - output[0] = (input[0] + input[1] + input[2]) * f1 / 3; - else { - output[0] = input[0] * f1; - output[1] = input[1] * f1; - output[2] = input[2] * f1; - } - if (req_comp == 2) - output[1] = 1; - if (req_comp == 4) - output[3] = 1; - } else { - switch (req_comp) { - case 4: - output[3] = 1; /* fallthrough */ - case 3: - output[0] = output[1] = output[2] = 0; - break; - case 2: - output[1] = 1; /* fallthrough */ - case 1: - output[0] = 0; - break; - } - } -} - -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - char buffer[STBI__HDR_BUFLEN]; - char *token; - int valid = 0; - int width, height; - stbi_uc *scanline; - float *hdr_data; - int len; - unsigned char count, value; - int i, j, k, c1, c2, z; - const char *headerToken; - STBI_NOTUSED(ri); - - // Check identifier - headerToken = stbi__hdr_gettoken(s, buffer); - if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) - return stbi__errpf("not HDR", "Corrupt HDR image"); - - // Parse header - for (;;) { - token = stbi__hdr_gettoken(s, buffer); - if (token[0] == 0) - break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) - valid = 1; - } - - if (!valid) - return stbi__errpf("unsupported format", "Unsupported HDR format"); - - // Parse width and height - // can't use sscanf() if we're not using stdio! - token = stbi__hdr_gettoken(s, buffer); - if (strncmp(token, "-Y ", 3)) - return stbi__errpf("unsupported data layout", "Unsupported HDR format"); - token += 3; - height = (int)strtol(token, &token, 10); - while (*token == ' ') - ++token; - if (strncmp(token, "+X ", 3)) - return stbi__errpf("unsupported data layout", "Unsupported HDR format"); - token += 3; - width = (int)strtol(token, NULL, 10); - - if (height > STBI_MAX_DIMENSIONS) - return stbi__errpf("too large", "Very large image (corrupt?)"); - if (width > STBI_MAX_DIMENSIONS) - return stbi__errpf("too large", "Very large image (corrupt?)"); - - *x = width; - *y = height; - - if (comp) - *comp = 3; - if (req_comp == 0) - req_comp = 3; - - if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) - return stbi__errpf("too large", "HDR image is too large"); - - // Read data - hdr_data = (float *)stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); - if (!hdr_data) - return stbi__errpf("outofmem", "Out of memory"); - - // Load image data - // image data is stored as some number of sca - if (width < 8 || width >= 32768) { - // Read flat data - for (j = 0; j < height; ++j) { - for (i = 0; i < width; ++i) { - stbi_uc rgbe[4]; -main_decode_loop: - stbi__getn(s, rgbe, 4); - stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, - rgbe, req_comp); - } - } - } else { - // Read RLE-encoded data - scanline = NULL; - - for (j = 0; j < height; ++j) { - c1 = stbi__get8(s); - c2 = stbi__get8(s); - len = stbi__get8(s); - if (c1 != 2 || c2 != 2 || (len & 0x80)) { - // not run-length encoded, so we have to actually use THIS data as a decoded - // pixel (note this can't be a valid pixel--one of RGB must be >= 128) - stbi_uc rgbe[4]; - rgbe[0] = (stbi_uc)c1; - rgbe[1] = (stbi_uc)c2; - rgbe[2] = (stbi_uc)len; - rgbe[3] = (stbi_uc)stbi__get8(s); - stbi__hdr_convert(hdr_data, rgbe, req_comp); - i = 1; - j = 0; - STBI_FREE(scanline); - goto main_decode_loop; // yes, this makes no sense - } - len <<= 8; - len |= stbi__get8(s); - if (len != width) { - STBI_FREE(hdr_data); - STBI_FREE(scanline); - return stbi__errpf("invalid decoded scanline length", - "corrupt HDR"); - } - if (scanline == NULL) { - scanline = (stbi_uc *)stbi__malloc_mad2(width, 4, 0); - if (!scanline) { - STBI_FREE(hdr_data); - return stbi__errpf("outofmem", "Out of memory"); - } - } - - for (k = 0; k < 4; ++k) { - int nleft; - i = 0; - while ((nleft = width - i) > 0) { - count = stbi__get8(s); - if (count > 128) { - // Run - value = stbi__get8(s); - count -= 128; - if ((count == 0) || (count > nleft)) { - STBI_FREE(hdr_data); - STBI_FREE(scanline); - return stbi__errpf("corrupt", - "bad RLE data in HDR"); - } - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = value; - } else { - // Dump - if ((count == 0) || (count > nleft)) { - STBI_FREE(hdr_data); - STBI_FREE(scanline); - return stbi__errpf("corrupt", - "bad RLE data in HDR"); - } - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = stbi__get8(s); - } - } - } - for (i = 0; i < width; ++i) - stbi__hdr_convert(hdr_data + (j * width + i) * req_comp, - scanline + i * 4, req_comp); - } - if (scanline) - STBI_FREE(scanline); - } - - return hdr_data; -} - -static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) -{ - char buffer[STBI__HDR_BUFLEN]; - char *token; - int valid = 0; - int dummy; - - if (!x) - x = &dummy; - if (!y) - y = &dummy; - if (!comp) - comp = &dummy; - - if (stbi__hdr_test(s) == 0) { - stbi__rewind(s); - return 0; - } - - for (;;) { - token = stbi__hdr_gettoken(s, buffer); - if (token[0] == 0) - break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) - valid = 1; - } - - if (!valid) { - stbi__rewind(s); - return 0; - } - token = stbi__hdr_gettoken(s, buffer); - if (strncmp(token, "-Y ", 3)) { - stbi__rewind(s); - return 0; - } - token += 3; - *y = (int)strtol(token, &token, 10); - while (*token == ' ') - ++token; - if (strncmp(token, "+X ", 3)) { - stbi__rewind(s); - return 0; - } - token += 3; - *x = (int)strtol(token, NULL, 10); - *comp = 3; - return 1; -} -#endif // STBI_NO_HDR - -#ifndef STBI_NO_BMP -static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) -{ - void *p; - stbi__bmp_data info; - - info.all_a = 255; - p = stbi__bmp_parse_header(s, &info); - if (p == NULL) { - stbi__rewind(s); - return 0; - } - if (x) - *x = s->img_x; - if (y) - *y = s->img_y; - if (comp) { - if (info.bpp == 24 && info.ma == 0xff000000) - *comp = 3; - else - *comp = info.ma ? 4 : 3; - } - return 1; -} -#endif - -#ifndef STBI_NO_PSD -static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) -{ - int channelCount, dummy, depth; - if (!x) - x = &dummy; - if (!y) - y = &dummy; - if (!comp) - comp = &dummy; - if (stbi__get32be(s) != 0x38425053) { - stbi__rewind(s); - return 0; - } - if (stbi__get16be(s) != 1) { - stbi__rewind(s); - return 0; - } - stbi__skip(s, 6); - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) { - stbi__rewind(s); - return 0; - } - *y = stbi__get32be(s); - *x = stbi__get32be(s); - depth = stbi__get16be(s); - if (depth != 8 && depth != 16) { - stbi__rewind(s); - return 0; - } - if (stbi__get16be(s) != 3) { - stbi__rewind(s); - return 0; - } - *comp = 4; - return 1; -} - -static int stbi__psd_is16(stbi__context *s) -{ - int channelCount, depth; - if (stbi__get32be(s) != 0x38425053) { - stbi__rewind(s); - return 0; - } - if (stbi__get16be(s) != 1) { - stbi__rewind(s); - return 0; - } - stbi__skip(s, 6); - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) { - stbi__rewind(s); - return 0; - } - STBI_NOTUSED(stbi__get32be(s)); - STBI_NOTUSED(stbi__get32be(s)); - depth = stbi__get16be(s); - if (depth != 16) { - stbi__rewind(s); - return 0; - } - return 1; -} -#endif - -#ifndef STBI_NO_PIC -static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) -{ - int act_comp = 0, num_packets = 0, chained, dummy; - stbi__pic_packet packets[10]; - - if (!x) - x = &dummy; - if (!y) - y = &dummy; - if (!comp) - comp = &dummy; - - if (!stbi__pic_is4(s, "\x53\x80\xF6\x34")) { - stbi__rewind(s); - return 0; - } - - stbi__skip(s, 88); - - *x = stbi__get16be(s); - *y = stbi__get16be(s); - if (stbi__at_eof(s)) { - stbi__rewind(s); - return 0; - } - if ((*x) != 0 && (1 << 28) / (*x) < (*y)) { - stbi__rewind(s); - return 0; - } - - stbi__skip(s, 8); - - do { - stbi__pic_packet *packet; - - if (num_packets == sizeof(packets) / sizeof(packets[0])) - return 0; - - packet = &packets[num_packets++]; - chained = stbi__get8(s); - packet->size = stbi__get8(s); - packet->type = stbi__get8(s); - packet->channel = stbi__get8(s); - act_comp |= packet->channel; - - if (stbi__at_eof(s)) { - stbi__rewind(s); - return 0; - } - if (packet->size != 8) { - stbi__rewind(s); - return 0; - } - } while (chained); - - *comp = (act_comp & 0x10 ? 4 : 3); - - return 1; -} -#endif - -// ************************************************************************************************* -// Portable Gray Map and Portable Pixel Map loader -// by Ken Miller -// -// PGM: http://netpbm.sourceforge.net/doc/pgm.html -// PPM: http://netpbm.sourceforge.net/doc/ppm.html -// -// Known limitations: -// Does not support comments in the header section -// Does not support ASCII image data (formats P2 and P3) - -#ifndef STBI_NO_PNM - -static int stbi__pnm_test(stbi__context *s) -{ - char p, t; - p = (char)stbi__get8(s); - t = (char)stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind(s); - return 0; - } - return 1; -} - -static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, - stbi__result_info *ri) -{ - stbi_uc *out; - STBI_NOTUSED(ri); - - ri->bits_per_channel = - stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); - if (ri->bits_per_channel == 0) - return 0; - - if (s->img_y > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - if (s->img_x > STBI_MAX_DIMENSIONS) - return stbi__errpuc("too large", "Very large image (corrupt?)"); - - *x = s->img_x; - *y = s->img_y; - if (comp) - *comp = s->img_n; - - if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) - return stbi__errpuc("too large", "PNM too large"); - - out = (stbi_uc *)stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, - 0); - if (!out) - return stbi__errpuc("outofmem", "Out of memory"); - if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { - STBI_FREE(out); - return stbi__errpuc("bad PNM", "PNM file truncated"); - } - - if (req_comp && req_comp != s->img_n) { - if (ri->bits_per_channel == 16) { - out = (stbi_uc *)stbi__convert_format16((stbi__uint16 *)out, s->img_n, - req_comp, s->img_x, s->img_y); - } else { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); - } - if (out == NULL) - return out; // stbi__convert_format frees input on failure - } - return out; -} - -static int stbi__pnm_isspace(char c) -{ - return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; -} - -static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) -{ - for (;;) { - while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) - *c = (char)stbi__get8(s); - - if (stbi__at_eof(s) || *c != '#') - break; - - while (!stbi__at_eof(s) && *c != '\n' && *c != '\r') - *c = (char)stbi__get8(s); - } -} - -static int stbi__pnm_isdigit(char c) -{ - return c >= '0' && c <= '9'; -} - -static int stbi__pnm_getinteger(stbi__context *s, char *c) -{ - int value = 0; - - while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { - value = value * 10 + (*c - '0'); - *c = (char)stbi__get8(s); - if ((value > 214748364) || (value == 214748364 && *c > '7')) - return stbi__err( - "integer parse overflow", - "Parsing an integer in the PPM header overflowed a 32-bit int"); - } - - return value; -} - -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) -{ - int maxv, dummy; - char c, p, t; - - if (!x) - x = &dummy; - if (!y) - y = &dummy; - if (!comp) - comp = &dummy; - - stbi__rewind(s); - - // Get identifier - p = (char)stbi__get8(s); - t = (char)stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind(s); - return 0; - } - - *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm - - c = (char)stbi__get8(s); - stbi__pnm_skip_whitespace(s, &c); - - *x = stbi__pnm_getinteger(s, &c); // read width - if (*x == 0) - return stbi__err("invalid width", "PPM image header had zero or overflowing width"); - stbi__pnm_skip_whitespace(s, &c); - - *y = stbi__pnm_getinteger(s, &c); // read height - if (*y == 0) - return stbi__err("invalid width", "PPM image header had zero or overflowing width"); - stbi__pnm_skip_whitespace(s, &c); - - maxv = stbi__pnm_getinteger(s, &c); // read max value - if (maxv > 65535) - return stbi__err("max value > 65535", - "PPM image supports only 8-bit and 16-bit images"); - else if (maxv > 255) - return 16; - else - return 8; -} - -static int stbi__pnm_is16(stbi__context *s) -{ - if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) - return 1; - return 0; -} -#endif - -static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) -{ -#ifndef STBI_NO_JPEG - if (stbi__jpeg_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_PNG - if (stbi__png_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_GIF - if (stbi__gif_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_BMP - if (stbi__bmp_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_PSD - if (stbi__psd_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_PIC - if (stbi__pic_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_PNM - if (stbi__pnm_info(s, x, y, comp)) - return 1; -#endif - -#ifndef STBI_NO_HDR - if (stbi__hdr_info(s, x, y, comp)) - return 1; -#endif - - // test tga last because it's a crappy test! -#ifndef STBI_NO_TGA - if (stbi__tga_info(s, x, y, comp)) - return 1; -#endif - return stbi__err("unknown image type", "Image not of any known type, or corrupt"); -} - -static int stbi__is_16_main(stbi__context *s) -{ -#ifndef STBI_NO_PNG - if (stbi__png_is16(s)) - return 1; -#endif - -#ifndef STBI_NO_PSD - if (stbi__psd_is16(s)) - return 1; -#endif - -#ifndef STBI_NO_PNM - if (stbi__pnm_is16(s)) - return 1; -#endif - return 0; -} - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result; - if (!f) - return stbi__err("can't fopen", "Unable to open file"); - result = stbi_info_from_file(f, x, y, comp); - fclose(f); - return result; -} - -STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) -{ - int r; - stbi__context s; - long pos = ftell(f); - stbi__start_file(&s, f); - r = stbi__info_main(&s, x, y, comp); - fseek(f, pos, SEEK_SET); - return r; -} - -STBIDEF int stbi_is_16_bit(char const *filename) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result; - if (!f) - return stbi__err("can't fopen", "Unable to open file"); - result = stbi_is_16_bit_from_file(f); - fclose(f); - return result; -} - -STBIDEF int stbi_is_16_bit_from_file(FILE *f) -{ - int r; - stbi__context s; - long pos = ftell(f); - stbi__start_file(&s, f); - r = stbi__is_16_main(&s); - fseek(f, pos, SEEK_SET); - return r; -} -#endif // !STBI_NO_STDIO - -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) -{ - stbi__context s; - stbi__start_mem(&s, buffer, len); - return stbi__info_main(&s, x, y, comp); -} - -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, - int *comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)c, user); - return stbi__info_main(&s, x, y, comp); -} - -STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) -{ - stbi__context s; - stbi__start_mem(&s, buffer, len); - return stbi__is_16_main(&s); -} - -STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *)c, user); - return stbi__is_16_main(&s); -} - -/* - revision history: - 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs - 2.19 (2018-02-11) fix warning - 2.18 (2018-01-30) fix warnings - 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug - 1-bit BMP - *_is_16_bit api - avoid warnings - 2.16 (2017-07-23) all functions have 16-bit variants; - STBI_NO_STDIO works again; - compilation fixes; - fix rounding in unpremultiply; - optimize vertical flip; - disable raw_len validation; - documentation fixes - 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; - warning fixes; disable run-time SSE detection on gcc; - uniform handling of optional "return" values; - thread-safe initialization of zlib tables - 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs - 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now - 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes - 2.11 (2016-04-02) allocate large structures on the stack - remove white matting for transparent PSD - fix reported channel count for PNG & BMP - re-enable SSE2 in non-gcc 64-bit - support RGB-formatted JPEG - read 16-bit PNGs (only as 8-bit) - 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED - 2.09 (2016-01-16) allow comments in PNM files - 16-bit-per-pixel TGA (not bit-per-component) - info() for TGA could break due to .hdr handling - info() for BMP to shares code instead of sloppy parse - can use STBI_REALLOC_SIZED if allocator doesn't support realloc - code cleanup - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) fix compiler warnings - partial animated GIF support - limited 16-bpc PSD support - #ifdef unused functions - bug with < 92 byte PIC,PNM,HDR,TGA - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) extra corruption checking (mmozeiko) - stbi_set_flip_vertically_on_load (nguillemot) - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) - progressive JPEG (stb) - PGM/PPM support (Ken Miller) - STBI_MALLOC,STBI_REALLOC,STBI_FREE - GIF bugfix -- seemingly never worked - STBI_NO_*, STBI_ONLY_* - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) - optimize PNG (ryg) - fix bug in interlaced PNG with user-specified channel count (stb) - 1.46 (2014-08-26) - fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG - 1.45 (2014-08-16) - fix MSVC-ARM internal compiler error by wrapping malloc - 1.44 (2014-08-07) - various warning fixes from Ronny Chevalier - 1.43 (2014-07-15) - fix MSVC-only compiler problem in code changed in 1.42 - 1.42 (2014-07-09) - don't define _CRT_SECURE_NO_WARNINGS (affects user code) - fixes to stbi__cleanup_jpeg path - added STBI_ASSERT to avoid requiring assert.h - 1.41 (2014-06-25) - fix search&replace from 1.36 that messed up comments/error messages - 1.40 (2014-06-22) - fix gcc struct-initialization warning - 1.39 (2014-06-15) - fix to TGA optimization when req_comp != number of components in TGA; - fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) - add support for BMP version 5 (more ignored fields) - 1.38 (2014-06-06) - suppress MSVC warnings on integer casts truncating values - fix accidental rename of 'skip' field of I/O - 1.37 (2014-06-04) - remove duplicate typedef - 1.36 (2014-06-03) - convert to header file single-file library - if de-iphone isn't set, load iphone images color-swapped instead of returning NULL - 1.35 (2014-05-27) - various warnings - fix broken STBI_SIMD path - fix bug where stbi_load_from_file no longer left file pointer in correct place - fix broken non-easy path for 32-bit BMP (possibly never used) - TGA optimization by Arseny Kapoulkine - 1.34 (unknown) - use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case - 1.33 (2011-07-14) - make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements - 1.32 (2011-07-13) - support for "info" function for all supported filetypes (SpartanJ) - 1.31 (2011-06-20) - a few more leak fixes, bug in PNG handling (SpartanJ) - 1.30 (2011-06-11) - added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) - removed deprecated format-specific test/load functions - removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway - error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) - fix inefficiency in decoding 32-bit BMP (David Woo) - 1.29 (2010-08-16) - various warning fixes from Aurelien Pocheville - 1.28 (2010-08-01) - fix bug in GIF palette transparency (SpartanJ) - 1.27 (2010-08-01) - cast-to-stbi_uc to fix warnings - 1.26 (2010-07-24) - fix bug in file buffering for PNG reported by SpartanJ - 1.25 (2010-07-17) - refix trans_data warning (Won Chun) - 1.24 (2010-07-12) - perf improvements reading from files on platforms with lock-heavy fgetc() - minor perf improvements for jpeg - deprecated type-specific functions so we'll get feedback if they're needed - attempt to fix trans_data warning (Won Chun) - 1.23 fixed bug in iPhone support - 1.22 (2010-07-10) - removed image *writing* support - stbi_info support from Jetro Lauha - GIF support from Jean-Marc Lienher - iPhone PNG-extensions from James Brown - warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) - 1.21 fix use of 'stbi_uc' in header (reported by jon blow) - 1.20 added support for Softimage PIC, by Tom Seddon - 1.19 bug in interlaced PNG corruption check (found by ryg) - 1.18 (2008-08-02) - fix a threading bug (local mutable static) - 1.17 support interlaced PNG - 1.16 major bugfix - stbi__convert_format converted one too many pixels - 1.15 initialize some fields for thread safety - 1.14 fix threadsafe conversion bug - header-file-only version (#define STBI_HEADER_FILE_ONLY before including) - 1.13 threadsafe - 1.12 const qualifiers in the API - 1.11 Support installable IDCT, colorspace conversion routines - 1.10 Fixes for 64-bit (don't use "unsigned long") - optimized upsampling by Fabian "ryg" Giesen - 1.09 Fix format-conversion for PSD code (bad global variables!) - 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz - 1.07 attempt to fix C++ warning/errors again - 1.06 attempt to fix C++ warning/errors again - 1.05 fix TGA loading to return correct *comp and use good luminance calc - 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free - 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR - 1.02 support for (subset of) HDR files, float interface for preferred access to them - 1.01 fix bug: possible bug in handling right-side up bmps... not sure - fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all - 1.00 interface to zlib that skips zlib header - 0.99 correct handling of alpha in palette - 0.98 TGA loader by lonesock; dynamically add loaders (untested) - 0.97 jpeg errors on too large a file; also catch another malloc failure - 0.96 fix detection of invalid v value - particleman@mollyrocket forum - 0.95 during header scan, seek to markers in case of padding - 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same - 0.93 handle jpegtran output; verbose errors - 0.92 read 4,8,16,24,32-bit BMP files of several formats - 0.91 output 24-bit Windows 3.0 BMP files - 0.90 fix a few more warnings; bump version number to approach 1.0 - 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd - 0.60 fix compiling as c++ - 0.59 fix warnings: merge Dave Moore's -Wall fixes - 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian - 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available - 0.56 fix bug: zlib uncompressed mode len vs. nlen - 0.55 fix bug: restart_interval not initialized to 0 - 0.54 allow NULL for 'int *comp' - 0.53 fix bug in png 3->4; speedup png decoding - 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments - 0.51 obey req_comp requests, 1-component jpegs return as 1-component, - on 'test' only check type, not whether we support this variant - 0.50 (2006-11-19) - first released version -*/ - -/* ------------------------------------------------------------------------------- -This software is available under 2 licenses -- choose whichever you prefer. ------------------------------------------------------------------------------- -ALTERNATIVE A - MIT License -Copyright (c) 2017 Sean Barrett -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. ------------------------------------------------------------------------------- -ALTERNATIVE B - Public Domain (www.unlicense.org) -This is free and unencumbered software released into the public domain. -Anyone is free to copy, modify, publish, use, compile, sell, or distribute this -software, either in source code form or as a compiled binary, for any purpose, -commercial or non-commercial, and by any means. -In jurisdictions that recognize copyright laws, the author or authors of this -software dedicate any and all copyright interest in the software to the public -domain. We make this dedication for the benefit of the public at large and to -the detriment of our heirs and successors. We intend this dedication to be an -overt act of relinquishment in perpetuity of all present and future rights to -this software under copyright law. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------- -*/