xref: /third_party/glfw/src/platform.c (revision b877906b)
1//========================================================================
2// GLFW 3.5 - www.glfw.org
3//------------------------------------------------------------------------
4// Copyright (c) 2002-2006 Marcus Geelnard
5// Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
6//
7// This software is provided 'as-is', without any express or implied
8// warranty. In no event will the authors be held liable for any damages
9// arising from the use of this software.
10//
11// Permission is granted to anyone to use this software for any purpose,
12// including commercial applications, and to alter it and redistribute it
13// freely, subject to the following restrictions:
14//
15// 1. The origin of this software must not be misrepresented; you must not
16//    claim that you wrote the original software. If you use this software
17//    in a product, an acknowledgment in the product documentation would
18//    be appreciated but is not required.
19//
20// 2. Altered source versions must be plainly marked as such, and must not
21//    be misrepresented as being the original software.
22//
23// 3. This notice may not be removed or altered from any source
24//    distribution.
25//
26//========================================================================
27
28#include "internal.h"
29
30#include <string.h>
31#include <stdlib.h>
32
33// These construct a string literal from individual numeric constants
34#define _GLFW_CONCAT_VERSION(m, n, r) #m "." #n "." #r
35#define _GLFW_MAKE_VERSION(m, n, r) _GLFW_CONCAT_VERSION(m, n, r)
36
37//////////////////////////////////////////////////////////////////////////
38//////                       GLFW internal API                      //////
39//////////////////////////////////////////////////////////////////////////
40
41static const struct
42{
43    int ID;
44    GLFWbool (*connect)(int,_GLFWplatform*);
45} supportedPlatforms[] =
46{
47#if defined(_GLFW_WIN32)
48    { GLFW_PLATFORM_WIN32, _glfwConnectWin32 },
49#endif
50#if defined(_GLFW_COCOA)
51    { GLFW_PLATFORM_COCOA, _glfwConnectCocoa },
52#endif
53#if defined(_GLFW_WAYLAND)
54    { GLFW_PLATFORM_WAYLAND, _glfwConnectWayland },
55#endif
56#if defined(_GLFW_X11)
57    { GLFW_PLATFORM_X11, _glfwConnectX11 },
58#endif
59};
60
61GLFWbool _glfwSelectPlatform(int desiredID, _GLFWplatform* platform)
62{
63    const size_t count = sizeof(supportedPlatforms) / sizeof(supportedPlatforms[0]);
64    size_t i;
65
66    if (desiredID != GLFW_ANY_PLATFORM &&
67        desiredID != GLFW_PLATFORM_WIN32 &&
68        desiredID != GLFW_PLATFORM_COCOA &&
69        desiredID != GLFW_PLATFORM_WAYLAND &&
70        desiredID != GLFW_PLATFORM_X11 &&
71        desiredID != GLFW_PLATFORM_NULL)
72    {
73        _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", desiredID);
74        return GLFW_FALSE;
75    }
76
77    // Only allow the Null platform if specifically requested
78    if (desiredID == GLFW_PLATFORM_NULL)
79        return _glfwConnectNull(desiredID, platform);
80    else if (count == 0)
81    {
82        _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "This binary only supports the Null platform");
83        return GLFW_FALSE;
84    }
85
86#if defined(_GLFW_WAYLAND) && defined(_GLFW_X11)
87    if (desiredID == GLFW_ANY_PLATFORM)
88    {
89        const char* const session = getenv("XDG_SESSION_TYPE");
90        if (session)
91        {
92            // Only follow XDG_SESSION_TYPE if it is set correctly and the
93            // environment looks plausble; otherwise fall back to detection
94            if (strcmp(session, "wayland") == 0 && getenv("WAYLAND_DISPLAY"))
95                desiredID = GLFW_PLATFORM_WAYLAND;
96            else if (strcmp(session, "x11") == 0 && getenv("DISPLAY"))
97                desiredID = GLFW_PLATFORM_X11;
98        }
99    }
100#endif
101
102    if (desiredID == GLFW_ANY_PLATFORM)
103    {
104        // If there is exactly one platform available for auto-selection, let it emit the
105        // error on failure as the platform-specific error description may be more helpful
106        if (count == 1)
107            return supportedPlatforms[0].connect(supportedPlatforms[0].ID, platform);
108
109        for (i = 0;  i < count;  i++)
110        {
111            if (supportedPlatforms[i].connect(desiredID, platform))
112                return GLFW_TRUE;
113        }
114
115        _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "Failed to detect any supported platform");
116    }
117    else
118    {
119        for (i = 0;  i < count;  i++)
120        {
121            if (supportedPlatforms[i].ID == desiredID)
122                return supportedPlatforms[i].connect(desiredID, platform);
123        }
124
125        _glfwInputError(GLFW_PLATFORM_UNAVAILABLE, "The requested platform is not supported");
126    }
127
128    return GLFW_FALSE;
129}
130
131//////////////////////////////////////////////////////////////////////////
132//////                        GLFW public API                       //////
133//////////////////////////////////////////////////////////////////////////
134
135GLFWAPI int glfwGetPlatform(void)
136{
137    _GLFW_REQUIRE_INIT_OR_RETURN(0);
138    return _glfw.platform.platformID;
139}
140
141GLFWAPI int glfwPlatformSupported(int platformID)
142{
143    const size_t count = sizeof(supportedPlatforms) / sizeof(supportedPlatforms[0]);
144    size_t i;
145
146    if (platformID != GLFW_PLATFORM_WIN32 &&
147        platformID != GLFW_PLATFORM_COCOA &&
148        platformID != GLFW_PLATFORM_WAYLAND &&
149        platformID != GLFW_PLATFORM_X11 &&
150        platformID != GLFW_PLATFORM_NULL)
151    {
152        _glfwInputError(GLFW_INVALID_ENUM, "Invalid platform ID 0x%08X", platformID);
153        return GLFW_FALSE;
154    }
155
156    if (platformID == GLFW_PLATFORM_NULL)
157        return GLFW_TRUE;
158
159    for (i = 0;  i < count;  i++)
160    {
161        if (platformID == supportedPlatforms[i].ID)
162            return GLFW_TRUE;
163    }
164
165    return GLFW_FALSE;
166}
167
168GLFWAPI const char* glfwGetVersionString(void)
169{
170    return _GLFW_MAKE_VERSION(GLFW_VERSION_MAJOR,
171                              GLFW_VERSION_MINOR,
172                              GLFW_VERSION_REVISION)
173#if defined(_GLFW_WIN32)
174        " Win32 WGL"
175#endif
176#if defined(_GLFW_COCOA)
177        " Cocoa NSGL"
178#endif
179#if defined(_GLFW_WAYLAND)
180        " Wayland"
181#endif
182#if defined(_GLFW_X11)
183        " X11 GLX"
184#endif
185        " Null"
186        " EGL"
187        " OSMesa"
188#if defined(__MINGW64_VERSION_MAJOR)
189        " MinGW-w64"
190#elif defined(__MINGW32__)
191        " MinGW"
192#elif defined(_MSC_VER)
193        " VisualC"
194#endif
195#if defined(_GLFW_USE_HYBRID_HPG) || defined(_GLFW_USE_OPTIMUS_HPG)
196        " hybrid-GPU"
197#endif
198#if defined(_POSIX_MONOTONIC_CLOCK)
199        " monotonic"
200#endif
201#if defined(_GLFW_BUILD_DLL)
202#if defined(_WIN32)
203        " DLL"
204#elif defined(__APPLE__)
205        " dynamic"
206#else
207        " shared"
208#endif
209#endif
210        ;
211}
212
213