1 /// Translated from C to D 2 module glfw3.egl_context; 3 4 extern(C): @nogc: nothrow: __gshared: 5 //======================================================================== 6 // GLFW 3.3 EGL - www.glfw.org 7 //------------------------------------------------------------------------ 8 // Copyright (c) 2002-2006 Marcus Geelnard 9 // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org> 10 // 11 // This software is provided 'as-is', without any express or implied 12 // warranty. In no event will the authors be held liable for any damages 13 // arising from the use of this software. 14 // 15 // Permission is granted to anyone to use this software for any purpose, 16 // including commercial applications, and to alter it and redistribute it 17 // freely, subject to the following restrictions: 18 // 19 // 1. The origin of this software must not be misrepresented; you must not 20 // claim that you wrote the original software. If you use this software 21 // in a product, an acknowledgment in the product documentation would 22 // be appreciated but is not required. 23 // 24 // 2. Altered source versions must be plainly marked as such, and must not 25 // be misrepresented as being the original software. 26 // 27 // 3. This notice may not be removed or altered from any source 28 // distribution. 29 // 30 //======================================================================== 31 // Please use C89 style variable declarations in this file because VS 2010 32 //======================================================================== 33 34 // HEADER 35 version (_GLFW_WIN32) { 36 alias EGLNativeDisplayType = HDC; 37 alias EGLNativeWindowType = HWND; 38 } else version (_GLFW_COCOA) { 39 alias EGLNativeDisplayType = void*; 40 alias EGLNativeWindowType = id ; 41 } else version (_GLFW_X11) { 42 alias EGLNativeDisplayType = Display*; 43 alias EGLNativeWindowType = Window; 44 } else version (_GLFW_WAYLAND) { 45 alias EGLNativeDisplayType = wl_display*; 46 alias EGLNativeWindowType = wl_egl_window*; 47 } else { 48 static assert(0, "No supported EGL platform selected"); 49 } 50 51 enum EGL_SUCCESS = 0x3000; 52 enum EGL_NOT_INITIALIZED = 0x3001; 53 enum EGL_BAD_ACCESS = 0x3002; 54 enum EGL_BAD_ALLOC = 0x3003; 55 enum EGL_BAD_ATTRIBUTE = 0x3004; 56 enum EGL_BAD_CONFIG = 0x3005; 57 enum EGL_BAD_CONTEXT = 0x3006; 58 enum EGL_BAD_CURRENT_SURFACE = 0x3007; 59 enum EGL_BAD_DISPLAY = 0x3008; 60 enum EGL_BAD_MATCH = 0x3009; 61 enum EGL_BAD_NATIVE_PIXMAP = 0x300a; 62 enum EGL_BAD_NATIVE_WINDOW = 0x300b; 63 enum EGL_BAD_PARAMETER = 0x300c; 64 enum EGL_BAD_SURFACE = 0x300d; 65 enum EGL_CONTEXT_LOST = 0x300e; 66 enum EGL_COLOR_BUFFER_TYPE = 0x303f; 67 enum EGL_RGB_BUFFER = 0x308e; 68 enum EGL_SURFACE_TYPE = 0x3033; 69 enum EGL_WINDOW_BIT = 0x0004; 70 enum EGL_RENDERABLE_TYPE = 0x3040; 71 enum EGL_OPENGL_ES_BIT = 0x0001; 72 enum EGL_OPENGL_ES2_BIT = 0x0004; 73 enum EGL_OPENGL_BIT = 0x0008; 74 enum EGL_ALPHA_SIZE = 0x3021; 75 enum EGL_BLUE_SIZE = 0x3022; 76 enum EGL_GREEN_SIZE = 0x3023; 77 enum EGL_RED_SIZE = 0x3024; 78 enum EGL_DEPTH_SIZE = 0x3025; 79 enum EGL_STENCIL_SIZE = 0x3026; 80 enum EGL_SAMPLES = 0x3031; 81 enum EGL_OPENGL_ES_API = 0x30a0; 82 enum EGL_OPENGL_API = 0x30a2; 83 enum EGL_NONE = 0x3038; 84 enum EGL_EXTENSIONS = 0x3055; 85 enum EGL_CONTEXT_CLIENT_VERSION = 0x3098; 86 enum EGL_NATIVE_VISUAL_ID = 0x302e; 87 enum EGL_NO_SURFACE = (cast(EGLSurface) 0); 88 enum EGL_NO_DISPLAY = (cast(EGLDisplay) 0); 89 enum EGL_NO_CONTEXT = (cast(EGLContext) 0); 90 enum EGL_DEFAULT_DISPLAY = (cast(EGLNativeDisplayType) 0); 91 92 enum EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR = 0x00000002; 93 enum EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR = 0x00000001; 94 enum EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR = 0x00000002; 95 enum EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR = 0x00000001; 96 enum EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR = 0x31bd; 97 enum EGL_NO_RESET_NOTIFICATION_KHR = 0x31be; 98 enum EGL_LOSE_CONTEXT_ON_RESET_KHR = 0x31bf; 99 enum EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR = 0x00000004; 100 enum EGL_CONTEXT_MAJOR_VERSION_KHR = 0x3098; 101 enum EGL_CONTEXT_MINOR_VERSION_KHR = 0x30fb; 102 enum EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR = 0x30fd; 103 enum EGL_CONTEXT_FLAGS_KHR = 0x30fc; 104 enum EGL_CONTEXT_OPENGL_NO_ERROR_KHR = 0x31b3; 105 enum EGL_GL_COLORSPACE_KHR = 0x309d; 106 enum EGL_GL_COLORSPACE_SRGB_KHR = 0x3089; 107 enum EGL_CONTEXT_RELEASE_BEHAVIOR_KHR = 0x2097; 108 enum EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR = 0; 109 enum EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR = 0x2098; 110 111 alias int EGLint; 112 alias uint EGLBoolean; 113 alias uint EGLenum; 114 alias void* EGLConfig; 115 alias void* EGLContext; 116 alias void* EGLDisplay; 117 alias void* EGLSurface; 118 119 // EGL function pointer typedefs 120 extern(System) { 121 alias EGLBoolean function(EGLDisplay, EGLConfig, EGLint, EGLint*) PFN_eglGetConfigAttrib; 122 alias EGLBoolean function(EGLDisplay, EGLConfig*, EGLint, EGLint*) PFN_eglGetConfigs; 123 alias EGLDisplay function(EGLNativeDisplayType) PFN_eglGetDisplay; 124 alias EGLint function() PFN_eglGetError; 125 alias EGLBoolean function(EGLDisplay, EGLint*, EGLint*) PFN_eglInitialize; 126 alias EGLBoolean function(EGLDisplay) PFN_eglTerminate; 127 alias EGLBoolean function(EGLenum) PFN_eglBindAPI; 128 alias EGLContext function(EGLDisplay, EGLConfig, EGLContext, const(EGLint)*) PFN_eglCreateContext; 129 alias EGLBoolean function(EGLDisplay, EGLSurface) PFN_eglDestroySurface; 130 alias EGLBoolean function(EGLDisplay, EGLContext) PFN_eglDestroyContext; 131 alias EGLSurface function(EGLDisplay, EGLConfig, EGLNativeWindowType, const(EGLint)*) PFN_eglCreateWindowSurface; 132 alias EGLBoolean function(EGLDisplay, EGLSurface, EGLSurface, EGLContext) PFN_eglMakeCurrent; 133 alias EGLBoolean function(EGLDisplay, EGLSurface) PFN_eglSwapBuffers; 134 alias EGLBoolean function(EGLDisplay, EGLint) PFN_eglSwapInterval; 135 alias const(char)* function(EGLDisplay, EGLint) PFN_eglQueryString; 136 alias GLFWglproc function(const(char)*) PFN_eglGetProcAddress; 137 } 138 alias eglGetConfigAttrib = _glfw.egl.GetConfigAttrib; 139 alias eglGetConfigs = _glfw.egl.GetConfigs; 140 alias eglGetDisplay = _glfw.egl.GetDisplay; 141 alias eglGetError = _glfw.egl.GetError; 142 alias eglInitialize = _glfw.egl.Initialize; 143 alias eglTerminate = _glfw.egl.Terminate; 144 alias eglBindAPI = _glfw.egl.BindAPI; 145 alias eglCreateContext = _glfw.egl.CreateContext; 146 alias eglDestroySurface = _glfw.egl.DestroySurface; 147 alias eglDestroyContext = _glfw.egl.DestroyContext; 148 alias eglCreateWindowSurface = _glfw.egl.CreateWindowSurface; 149 alias eglMakeCurrent = _glfw.egl.MakeCurrent; 150 alias eglSwapBuffers = _glfw.egl.SwapBuffers; 151 alias eglSwapInterval = _glfw.egl.SwapInterval; 152 alias eglQueryString = _glfw.egl.QueryString; 153 alias eglGetProcAddress = _glfw.egl.GetProcAddress; 154 155 mixin template _GLFW_EGL_CONTEXT_STATE() { _GLFWcontextEGL egl;} 156 mixin template _GLFW_EGL_LIBRARY_CONTEXT_STATE() {_GLFWlibraryEGL egl;} 157 158 // EGL-specific per-context data 159 // 160 struct _GLFWcontextEGL { 161 EGLConfig config; 162 EGLContext handle; 163 EGLSurface surface; 164 165 void* client; 166 167 }/+alias _GLFWcontextEGL _GLFWcontextEGL;+/ 168 169 // EGL-specific global data 170 // 171 struct _GLFWlibraryEGL { 172 EGLDisplay display; 173 EGLint major;EGLint minor; 174 GLFWbool prefix; 175 176 GLFWbool KHR_create_context; 177 GLFWbool KHR_create_context_no_error; 178 GLFWbool KHR_gl_colorspace; 179 GLFWbool KHR_get_all_proc_addresses; 180 GLFWbool KHR_context_flush_control; 181 182 void* handle; 183 184 PFN_eglGetConfigAttrib GetConfigAttrib; 185 PFN_eglGetConfigs GetConfigs; 186 PFN_eglGetDisplay GetDisplay; 187 PFN_eglGetError GetError; 188 PFN_eglInitialize Initialize; 189 PFN_eglTerminate Terminate; 190 PFN_eglBindAPI BindAPI; 191 PFN_eglCreateContext CreateContext; 192 PFN_eglDestroySurface DestroySurface; 193 PFN_eglDestroyContext DestroyContext; 194 PFN_eglCreateWindowSurface CreateWindowSurface; 195 PFN_eglMakeCurrent MakeCurrent; 196 PFN_eglSwapBuffers SwapBuffers; 197 PFN_eglSwapInterval SwapInterval; 198 PFN_eglQueryString QueryString; 199 PFN_eglGetProcAddress GetProcAddress; 200 201 }/+alias _GLFWlibraryEGL _GLFWlibraryEGL;+/ 202 203 204 GLFWbool _glfwInitEGL(); 205 void _glfwTerminateEGL(); 206 GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig); 207 version (_GLFW_X11) { 208 GLFWbool _glfwChooseVisualEGL(const(_GLFWwndconfig)* wndconfig, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig, Visual** visual, int* depth); 209 } /*_GLFW_X11*/ 210 211 ////////////////////// 212 213 import glfw3.internal; 214 215 import core.stdc.stdio; 216 import core.stdc.string; 217 import core.stdc.stdlib; 218 import core.stdc.assert_; 219 import core.stdc.stdint; 220 221 // Return a description of the specified EGL error 222 // 223 static const(char)* getEGLErrorString(EGLint error) { 224 switch (error) 225 { 226 case EGL_SUCCESS: 227 return "Success"; 228 case EGL_NOT_INITIALIZED: 229 return "EGL is not or could not be initialized"; 230 case EGL_BAD_ACCESS: 231 return "EGL cannot access a requested resource"; 232 case EGL_BAD_ALLOC: 233 return "EGL failed to allocate resources for the requested operation"; 234 case EGL_BAD_ATTRIBUTE: 235 return "An unrecognized attribute or attribute value was passed in the attribute list"; 236 case EGL_BAD_CONTEXT: 237 return "An EGLContext argument does not name a valid EGL rendering context"; 238 case EGL_BAD_CONFIG: 239 return "An EGLConfig argument does not name a valid EGL frame buffer configuration"; 240 case EGL_BAD_CURRENT_SURFACE: 241 return "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid"; 242 case EGL_BAD_DISPLAY: 243 return "An EGLDisplay argument does not name a valid EGL display connection"; 244 case EGL_BAD_SURFACE: 245 return "An EGLSurface argument does not name a valid surface configured for GL rendering"; 246 case EGL_BAD_MATCH: 247 return "Arguments are inconsistent"; 248 case EGL_BAD_PARAMETER: 249 return "One or more argument values are invalid"; 250 case EGL_BAD_NATIVE_PIXMAP: 251 return "A NativePixmapType argument does not refer to a valid native pixmap"; 252 case EGL_BAD_NATIVE_WINDOW: 253 return "A NativeWindowType argument does not refer to a valid native window"; 254 case EGL_CONTEXT_LOST: 255 return "The application must destroy all contexts and reinitialise"; 256 default: 257 return "ERROR: UNKNOWN EGL ERROR"; 258 } 259 } 260 261 // Returns the specified attribute of the specified EGLConfig 262 // 263 static int getEGLConfigAttrib(EGLConfig config, int attrib) { 264 int value; 265 _glfw.egl.GetConfigAttrib(_glfw.egl.display, config, attrib, &value); 266 return value; 267 } 268 269 // Return the EGLConfig most closely matching the specified hints 270 // 271 static GLFWbool chooseEGLConfig(const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* desired, EGLConfig* result) { 272 EGLConfig* nativeConfigs; 273 _GLFWfbconfig* usableConfigs; 274 const(_GLFWfbconfig)* closest; 275 int i;int nativeCount;int usableCount; 276 277 _glfw.egl.GetConfigs(_glfw.egl.display, null, 0, &nativeCount); 278 if (!nativeCount) 279 { 280 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: No EGLConfigs returned"); 281 return GLFW_FALSE; 282 } 283 284 nativeConfigs = cast(typeof(nativeConfigs)) calloc(nativeCount, EGLConfig.sizeof); 285 _glfw.egl.GetConfigs(_glfw.egl.display, nativeConfigs, nativeCount, &nativeCount); 286 287 usableConfigs = cast(typeof(usableConfigs)) calloc(nativeCount, _GLFWfbconfig.sizeof); 288 usableCount = 0; 289 290 for (i = 0; i < nativeCount; i++) 291 { 292 EGLConfig n = nativeConfigs[i]; 293 _GLFWfbconfig* u = usableConfigs + usableCount; 294 295 // Only consider RGB(A) EGLConfigs 296 if (getEGLConfigAttrib(n, EGL_COLOR_BUFFER_TYPE) != EGL_RGB_BUFFER) 297 continue; 298 299 // Only consider window EGLConfigs 300 if (!(getEGLConfigAttrib(n, EGL_SURFACE_TYPE) & EGL_WINDOW_BIT)) 301 continue; 302 303 version (_GLFW_X11) 304 { 305 XVisualInfo vi = XVisualInfo(null); 306 307 // Only consider EGLConfigs with associated Visuals 308 vi.visualid = getEGLConfigAttrib(n, EGL_NATIVE_VISUAL_ID); 309 if (!vi.visualid) 310 continue; 311 312 if (desired.transparent) 313 { 314 int count; 315 XVisualInfo* vis = XGetVisualInfo(_glfw.x11.display, VisualIDMask, &vi, &count); 316 if (vis) 317 { 318 u.transparent = _glfwIsVisualTransparentX11(vis[0].visual); 319 XFree(vis); 320 } 321 } 322 } 323 324 if (ctxconfig.client == GLFW_OPENGL_ES_API) 325 { 326 if (ctxconfig.major == 1) 327 { 328 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES_BIT)) 329 continue; 330 } 331 else 332 { 333 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_ES2_BIT)) 334 continue; 335 } 336 } 337 else if (ctxconfig.client == GLFW_OPENGL_API) 338 { 339 if (!(getEGLConfigAttrib(n, EGL_RENDERABLE_TYPE) & EGL_OPENGL_BIT)) 340 continue; 341 } 342 343 u.redBits = getEGLConfigAttrib(n, EGL_RED_SIZE); 344 u.greenBits = getEGLConfigAttrib(n, EGL_GREEN_SIZE); 345 u.blueBits = getEGLConfigAttrib(n, EGL_BLUE_SIZE); 346 347 u.alphaBits = getEGLConfigAttrib(n, EGL_ALPHA_SIZE); 348 u.depthBits = getEGLConfigAttrib(n, EGL_DEPTH_SIZE); 349 u.stencilBits = getEGLConfigAttrib(n, EGL_STENCIL_SIZE); 350 351 u.samples = getEGLConfigAttrib(n, EGL_SAMPLES); 352 u.doublebuffer = GLFW_TRUE; 353 354 u.handle = cast(uintptr_t) n; 355 usableCount++; 356 } 357 358 closest = _glfwChooseFBConfig(desired, usableConfigs, usableCount); 359 if (closest) 360 *result = cast(EGLConfig) closest.handle; 361 362 free(nativeConfigs); 363 free(usableConfigs); 364 365 return closest != null; 366 } 367 368 static void makeContextCurrentEGL(_GLFWwindow* window) { 369 if (window) 370 { 371 if (!_glfw.egl.MakeCurrent(_glfw.egl.display, 372 window.context.egl.surface, 373 window.context.egl.surface, 374 window.context.egl.handle)) 375 { 376 _glfwInputError(GLFW_PLATFORM_ERROR, 377 "EGL: Failed to make context current: %s", 378 getEGLErrorString(_glfw.egl.GetError())); 379 return; 380 } 381 } 382 else 383 { 384 if (!_glfw.egl.MakeCurrent(_glfw.egl.display, 385 EGL_NO_SURFACE, 386 EGL_NO_SURFACE, 387 EGL_NO_CONTEXT)) 388 { 389 _glfwInputError(GLFW_PLATFORM_ERROR, 390 "EGL: Failed to clear current context: %s", 391 getEGLErrorString(_glfw.egl.GetError())); 392 return; 393 } 394 } 395 396 _glfwPlatformSetTls(&_glfw.contextSlot, window); 397 } 398 399 static void swapBuffersEGL(_GLFWwindow* window) { 400 if (window != _glfwPlatformGetTls(&_glfw.contextSlot)) 401 { 402 _glfwInputError(GLFW_PLATFORM_ERROR, 403 "EGL: The context must be current on the calling thread when swapping buffers"); 404 return; 405 } 406 407 _glfw.egl.SwapBuffers(_glfw.egl.display, window.context.egl.surface); 408 } 409 410 static void swapIntervalEGL(int interval) { 411 _glfw.egl.SwapInterval(_glfw.egl.display, interval); 412 } 413 414 static int extensionSupportedEGL(const(char)* extension) { 415 const(char)* extensions = _glfw.egl.QueryString(_glfw.egl.display, EGL_EXTENSIONS); 416 if (extensions) 417 { 418 if (_glfwStringInExtensionString(extension, extensions)) 419 return GLFW_TRUE; 420 } 421 422 return GLFW_FALSE; 423 } 424 425 static GLFWglproc getProcAddressEGL(const(char)* procname) { 426 auto window = cast(_GLFWwindow*) _glfwPlatformGetTls(&_glfw.contextSlot); 427 428 if (window.context.egl.client) 429 { 430 GLFWglproc proc = cast(GLFWglproc) _glfw_dlsym(window.context.egl.client, 431 procname); 432 if (proc) 433 return proc; 434 } 435 436 return _glfw.egl.GetProcAddress(procname); 437 } 438 439 static void destroyContextEGL(_GLFWwindow* window) { 440 // NOTE: Do not unload libGL.so.1 while the X11 display is still open, 441 // as it will make XCloseDisplay segfault 442 version (_GLFW_X11) { 443 const bool condition = window.context.client != GLFW_OPENGL_API; 444 } else { 445 const bool condition = true; 446 } 447 if (condition) 448 { 449 if (window.context.egl.client) 450 { 451 _glfw_dlclose(window.context.egl.client); 452 window.context.egl.client = null; 453 } 454 } 455 456 if (window.context.egl.surface) 457 { 458 _glfw.egl.DestroySurface(_glfw.egl.display, window.context.egl.surface); 459 window.context.egl.surface = EGL_NO_SURFACE; 460 } 461 462 if (window.context.egl.handle) 463 { 464 _glfw.egl.DestroyContext(_glfw.egl.display, window.context.egl.handle); 465 window.context.egl.handle = EGL_NO_CONTEXT; 466 } 467 } 468 469 470 ////////////////////////////////////////////////////////////////////////// 471 ////// GLFW internal API ////// 472 ////////////////////////////////////////////////////////////////////////// 473 474 // Initialize EGL 475 // 476 GLFWbool _glfwInitEGL() { 477 int i; 478 version(_GLFW_WIN32) { 479 static immutable char*[] sonames = ["libEGL.dll", "EGL.dll", null]; 480 } else version(_GLFW_COCOA) { 481 static immutable char*[] sonames = ["libEGL.dylib", null]; 482 } else version(Cygwin) { 483 static immutable char*[] sonames = ["libEGL-1.so", null]; 484 } else { 485 static immutable char*[] sonames = ["libEGL.so.1",null]; 486 } 487 488 if (_glfw.egl.handle) 489 return GLFW_TRUE; 490 491 for (i = 0; sonames[i]; i++) 492 { 493 _glfw.egl.handle = _glfw_dlopen(sonames[i]); 494 if (_glfw.egl.handle) 495 break; 496 } 497 498 if (!_glfw.egl.handle) 499 { 500 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: Library not found"); 501 return GLFW_FALSE; 502 } 503 504 _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); 505 506 _glfw.egl.GetConfigAttrib = cast(PFN_eglGetConfigAttrib) 507 _glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); 508 _glfw.egl.GetConfigs = cast(PFN_eglGetConfigs) 509 _glfw_dlsym(_glfw.egl.handle, "eglGetConfigs"); 510 _glfw.egl.GetDisplay = cast(PFN_eglGetDisplay) 511 _glfw_dlsym(_glfw.egl.handle, "eglGetDisplay"); 512 _glfw.egl.GetError = cast(PFN_eglGetError) 513 _glfw_dlsym(_glfw.egl.handle, "eglGetError"); 514 _glfw.egl.Initialize = cast(PFN_eglInitialize) 515 _glfw_dlsym(_glfw.egl.handle, "eglInitialize"); 516 _glfw.egl.Terminate = cast(PFN_eglTerminate) 517 _glfw_dlsym(_glfw.egl.handle, "eglTerminate"); 518 _glfw.egl.BindAPI = cast(PFN_eglBindAPI) 519 _glfw_dlsym(_glfw.egl.handle, "eglBindAPI"); 520 _glfw.egl.CreateContext = cast(PFN_eglCreateContext) 521 _glfw_dlsym(_glfw.egl.handle, "eglCreateContext"); 522 _glfw.egl.DestroySurface = cast(PFN_eglDestroySurface) 523 _glfw_dlsym(_glfw.egl.handle, "eglDestroySurface"); 524 _glfw.egl.DestroyContext = cast(PFN_eglDestroyContext) 525 _glfw_dlsym(_glfw.egl.handle, "eglDestroyContext"); 526 _glfw.egl.CreateWindowSurface = cast(PFN_eglCreateWindowSurface) 527 _glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface"); 528 _glfw.egl.MakeCurrent = cast(PFN_eglMakeCurrent) 529 _glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent"); 530 _glfw.egl.SwapBuffers = cast(PFN_eglSwapBuffers) 531 _glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers"); 532 _glfw.egl.SwapInterval = cast(PFN_eglSwapInterval) 533 _glfw_dlsym(_glfw.egl.handle, "eglSwapInterval"); 534 _glfw.egl.QueryString = cast(PFN_eglQueryString) 535 _glfw_dlsym(_glfw.egl.handle, "eglQueryString"); 536 _glfw.egl.GetProcAddress = cast(PFN_eglGetProcAddress) 537 _glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress"); 538 539 if (!_glfw.egl.GetConfigAttrib || 540 !_glfw.egl.GetConfigs || 541 !_glfw.egl.GetDisplay || 542 !_glfw.egl.GetError || 543 !_glfw.egl.Initialize || 544 !_glfw.egl.Terminate || 545 !_glfw.egl.BindAPI || 546 !_glfw.egl.CreateContext || 547 !_glfw.egl.DestroySurface || 548 !_glfw.egl.DestroyContext || 549 !_glfw.egl.CreateWindowSurface || 550 !_glfw.egl.MakeCurrent || 551 !_glfw.egl.SwapBuffers || 552 !_glfw.egl.SwapInterval || 553 !_glfw.egl.QueryString || 554 !_glfw.egl.GetProcAddress) 555 { 556 _glfwInputError(GLFW_PLATFORM_ERROR, 557 "EGL: Failed to load required entry points"); 558 559 _glfwTerminateEGL(); 560 return GLFW_FALSE; 561 } 562 563 _glfw.egl.display = _glfw.egl.GetDisplay(mixin(_GLFW_EGL_NATIVE_DISPLAY)); 564 if (_glfw.egl.display == EGL_NO_DISPLAY) 565 { 566 _glfwInputError(GLFW_API_UNAVAILABLE, 567 "EGL: Failed to get EGL display: %s", 568 getEGLErrorString(_glfw.egl.GetError())); 569 570 _glfwTerminateEGL(); 571 return GLFW_FALSE; 572 } 573 574 if (!_glfw.egl.Initialize(_glfw.egl.display, &_glfw.egl.major, &_glfw.egl.minor)) 575 { 576 _glfwInputError(GLFW_API_UNAVAILABLE, 577 "EGL: Failed to initialize EGL: %s", 578 getEGLErrorString(_glfw.egl.GetError())); 579 580 _glfwTerminateEGL(); 581 return GLFW_FALSE; 582 } 583 584 _glfw.egl.KHR_create_context = 585 extensionSupportedEGL("EGL_KHR_create_context"); 586 _glfw.egl.KHR_create_context_no_error = 587 extensionSupportedEGL("EGL_KHR_create_context_no_error"); 588 _glfw.egl.KHR_gl_colorspace = 589 extensionSupportedEGL("EGL_KHR_gl_colorspace"); 590 _glfw.egl.KHR_get_all_proc_addresses = 591 extensionSupportedEGL("EGL_KHR_get_all_proc_addresses"); 592 _glfw.egl.KHR_context_flush_control = 593 extensionSupportedEGL("EGL_KHR_context_flush_control"); 594 595 return GLFW_TRUE; 596 } 597 598 // Terminate EGL 599 // 600 void _glfwTerminateEGL() { 601 if (_glfw.egl.display) 602 { 603 _glfw.egl.Terminate(_glfw.egl.display); 604 _glfw.egl.display = EGL_NO_DISPLAY; 605 } 606 607 if (_glfw.egl.handle) 608 { 609 _glfw_dlclose(_glfw.egl.handle); 610 _glfw.egl.handle = null; 611 } 612 } 613 614 615 // Create the OpenGL or OpenGL ES context 616 // 617 GLFWbool _glfwCreateContextEGL(_GLFWwindow* window, const(_GLFWctxconfig)* ctxconfig, const(_GLFWfbconfig)* fbconfig) { 618 EGLint[40] attribs; 619 int index = 0; 620 void setAttrib(EGLint a, EGLint v) { 621 assert((cast(size_t) index + 1) < attribs.length); 622 attribs[index++] = a; 623 attribs[index++] = v; 624 } 625 EGLConfig config; 626 EGLContext share = null; 627 628 if (!_glfw.egl.display) 629 { 630 _glfwInputError(GLFW_API_UNAVAILABLE, "EGL: API not available"); 631 return GLFW_FALSE; 632 } 633 634 if (ctxconfig.share) 635 share = cast(void*) ctxconfig.share.context.egl.handle; 636 637 if (!chooseEGLConfig(ctxconfig, fbconfig, &config)) 638 { 639 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 640 "EGL: Failed to find a suitable EGLConfig"); 641 return GLFW_FALSE; 642 } 643 644 if (ctxconfig.client == GLFW_OPENGL_ES_API) 645 { 646 if (!_glfw.egl.BindAPI(EGL_OPENGL_ES_API)) 647 { 648 _glfwInputError(GLFW_API_UNAVAILABLE, 649 "EGL: Failed to bind OpenGL ES: %s", 650 getEGLErrorString(_glfw.egl.GetError())); 651 return GLFW_FALSE; 652 } 653 } 654 else 655 { 656 if (!_glfw.egl.BindAPI(EGL_OPENGL_API)) 657 { 658 _glfwInputError(GLFW_API_UNAVAILABLE, 659 "EGL: Failed to bind OpenGL: %s", 660 getEGLErrorString(_glfw.egl.GetError())); 661 return GLFW_FALSE; 662 } 663 } 664 665 if (_glfw.egl.KHR_create_context) 666 { 667 int mask = 0;int flags = 0; 668 669 if (ctxconfig.client == GLFW_OPENGL_API) 670 { 671 if (ctxconfig.forward) 672 flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 673 674 if (ctxconfig.profile == GLFW_OPENGL_CORE_PROFILE) 675 mask |= EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 676 else if (ctxconfig.profile == GLFW_OPENGL_COMPAT_PROFILE) 677 mask |= EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; 678 } 679 680 if (ctxconfig.debug_) 681 flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; 682 683 if (ctxconfig.robustness) 684 { 685 if (ctxconfig.robustness == GLFW_NO_RESET_NOTIFICATION) 686 { 687 setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, 688 EGL_NO_RESET_NOTIFICATION_KHR); 689 } 690 else if (ctxconfig.robustness == GLFW_LOSE_CONTEXT_ON_RESET) 691 { 692 setAttrib(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR, 693 EGL_LOSE_CONTEXT_ON_RESET_KHR); 694 } 695 696 flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 697 } 698 699 if (ctxconfig.noerror) 700 { 701 if (_glfw.egl.KHR_create_context_no_error) 702 setAttrib(EGL_CONTEXT_OPENGL_NO_ERROR_KHR, GLFW_TRUE); 703 } 704 705 if (ctxconfig.major != 1 || ctxconfig.minor != 0) 706 { 707 setAttrib(EGL_CONTEXT_MAJOR_VERSION_KHR, ctxconfig.major); 708 setAttrib(EGL_CONTEXT_MINOR_VERSION_KHR, ctxconfig.minor); 709 } 710 711 if (mask) 712 setAttrib(EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, mask); 713 714 if (flags) 715 setAttrib(EGL_CONTEXT_FLAGS_KHR, flags); 716 } 717 else 718 { 719 if (ctxconfig.client == GLFW_OPENGL_ES_API) 720 setAttrib(EGL_CONTEXT_CLIENT_VERSION, ctxconfig.major); 721 } 722 723 if (_glfw.egl.KHR_context_flush_control) 724 { 725 if (ctxconfig.release == GLFW_RELEASE_BEHAVIOR_NONE) 726 { 727 setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 728 EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR); 729 } 730 else if (ctxconfig.release == GLFW_RELEASE_BEHAVIOR_FLUSH) 731 { 732 setAttrib(EGL_CONTEXT_RELEASE_BEHAVIOR_KHR, 733 EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR); 734 } 735 } 736 737 setAttrib(EGL_NONE, EGL_NONE); 738 739 window.context.egl.handle = _glfw.egl.CreateContext(_glfw.egl.display, 740 config, share, attribs.ptr); 741 742 if (window.context.egl.handle == EGL_NO_CONTEXT) 743 { 744 _glfwInputError(GLFW_VERSION_UNAVAILABLE, 745 "EGL: Failed to create context: %s", 746 getEGLErrorString(_glfw.egl.GetError())); 747 return GLFW_FALSE; 748 } 749 750 // Set up attributes for surface creation 751 { 752 index = 0; 753 754 if (fbconfig.sRGB) 755 { 756 if (_glfw.egl.KHR_gl_colorspace) 757 setAttrib(EGL_GL_COLORSPACE_KHR, EGL_GL_COLORSPACE_SRGB_KHR); 758 } 759 760 setAttrib(EGL_NONE, EGL_NONE); 761 } 762 763 window.context.egl.surface = 764 _glfw.egl.CreateWindowSurface(_glfw.egl.display, 765 config, 766 mixin(_GLFW_EGL_NATIVE_WINDOW), 767 attribs.ptr); 768 if (window.context.egl.surface == EGL_NO_SURFACE) 769 { 770 _glfwInputError(GLFW_PLATFORM_ERROR, 771 "EGL: Failed to create window surface: %s", 772 getEGLErrorString(_glfw.egl.GetError())); 773 return GLFW_FALSE; 774 } 775 776 window.context.egl.config = config; 777 778 // Load the appropriate client library 779 if (!_glfw.egl.KHR_get_all_proc_addresses) 780 { 781 int i; 782 const(char*)* sonames; 783 784 version(_GLFW_WIN32) { 785 static immutable char*[3] es1sonames = ["GLESv1_CM.dll","libGLES_CM.dll", null]; 786 } else version(_GLFW_COCOA) { 787 static immutable char*[2] es1sonames = ["libGLESv1_CM.dylib", null]; 788 } else { 789 static immutable char*[3] es1sonames = ["libGLESv1_CM.so.1","libGLES_CM.so.1", null]; 790 } 791 792 version(_GLFW_WIN32) { 793 static immutable char*[3] es2sonames = ["GLESv2.dll","libGLESv2.dll",null]; 794 } else version(_GLFW_COCOA) { 795 static immutable char*[2] es2sonames = ["libGLESv2.dylib",null]; 796 } else version(Cygwin) { 797 static immutable char*[2] es2sonames = ["libGLESv2-2.so",null]; 798 } else { 799 static immutable char*[2] es2sonames = ["libGLESv2.so.2",null]; 800 } 801 802 version(_GLFW_WIN32) { 803 static immutable char*[1] glsonames = [null]; 804 } else version(_GLFW_COCOA) { 805 static immutable char*[1] glsonames = [null]; 806 } else { 807 static immutable char*[2] glsonames = ["libGL.so.1",null]; 808 } 809 810 if (ctxconfig.client == GLFW_OPENGL_ES_API) 811 { 812 if (ctxconfig.major == 1) 813 sonames = es1sonames.ptr; 814 else 815 sonames = es2sonames.ptr; 816 } 817 else 818 sonames = glsonames.ptr; 819 820 for (i = 0; sonames[i]; i++) 821 { 822 // HACK: Match presence of lib prefix to increase chance of finding 823 // a matching pair in the jungle that is Win32 EGL/GLES 824 if (_glfw.egl.prefix != (strncmp(sonames[i], "lib", 3) == 0)) 825 continue; 826 827 window.context.egl.client = _glfw_dlopen(sonames[i]); 828 if (window.context.egl.client) 829 break; 830 } 831 832 if (!window.context.egl.client) 833 { 834 _glfwInputError(GLFW_API_UNAVAILABLE, 835 "EGL: Failed to load client library"); 836 return GLFW_FALSE; 837 } 838 } 839 840 window.context.makeCurrent = &makeContextCurrentEGL; 841 window.context.swapBuffers = &swapBuffersEGL; 842 window.context.swapInterval = &swapIntervalEGL; 843 window.context.extensionSupported = &extensionSupportedEGL; 844 window.context.getProcAddress = &getProcAddressEGL; 845 window.context.destroy = &destroyContextEGL; 846 847 return GLFW_TRUE; 848 } 849 850 // Returns the Visual and depth of the chosen EGLConfig 851 // 852 version (_GLFW_X11) { 853 GLFWbool _glfwChooseVisualEGL( 854 const(_GLFWwndconfig)* wndconfig, const(_GLFWctxconfig)* ctxconfig, 855 const(_GLFWfbconfig)* fbconfig, Visual** visual, int* depth 856 ) { 857 XVisualInfo* result; 858 XVisualInfo desired; 859 EGLConfig native; 860 EGLint visualID = 0;EGLint count = 0; 861 const(int) vimask = VisualScreenMask | VisualIDMask; 862 863 if (!chooseEGLConfig(ctxconfig, fbconfig, &native)) 864 { 865 _glfwInputError(GLFW_FORMAT_UNAVAILABLE, 866 "EGL: Failed to find a suitable EGLConfig"); 867 return GLFW_FALSE; 868 } 869 870 _glfw.egl.GetConfigAttrib(_glfw.egl.display, native, 871 EGL_NATIVE_VISUAL_ID, &visualID); 872 873 desired.screen = _glfw.x11.screen; 874 desired.visualid = visualID; 875 876 result = XGetVisualInfo(_glfw.x11.display, vimask, &desired, &count); 877 if (!result) 878 { 879 _glfwInputError(GLFW_PLATFORM_ERROR, 880 "EGL: Failed to retrieve Visual for EGLConfig"); 881 return GLFW_FALSE; 882 } 883 884 *visual = result.visual; 885 *depth = result.depth; 886 887 XFree(result); 888 return GLFW_TRUE; 889 } 890 } // _GLFW_X11 891 892 893 ////////////////////////////////////////////////////////////////////////// 894 ////// GLFW native API ////// 895 ////////////////////////////////////////////////////////////////////////// 896 897 EGLDisplay glfwGetEGLDisplay() { 898 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("EGL_NO_DISPLAY")); 899 return _glfw.egl.display; 900 } 901 902 EGLContext glfwGetEGLContext(GLFWwindow* handle) { 903 _GLFWwindow* window = cast(_GLFWwindow*) handle; 904 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("EGL_NO_CONTEXT")); 905 906 if (window.context.client == GLFW_NO_API) 907 { 908 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, null); 909 return EGL_NO_CONTEXT; 910 } 911 912 return window.context.egl.handle; 913 } 914 915 EGLSurface glfwGetEGLSurface(GLFWwindow* handle) { 916 _GLFWwindow* window = cast(_GLFWwindow*) handle; 917 mixin(_GLFW_REQUIRE_INIT_OR_RETURN!("EGL_NO_SURFACE")); 918 919 if (window.context.client == GLFW_NO_API) 920 { 921 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, null); 922 return EGL_NO_SURFACE; 923 } 924 925 return window.context.egl.surface; 926 }