1 // Copyright Danny Arends 2020.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See: http://www.boost.org/LICENSE_1_0.txt)
4 
5 module bindbc.gles.egl;
6 
7 import bindbc.loader;
8 public import bindbc.gles.config,
9               bindbc.gles.egltypes;
10 
11 enum EGLNativeDisplayType EGL_DEFAULT_DISPLAY = cast(EGLNativeDisplayType)0;
12 enum EGLContext EGL_NO_CONTEXT = null;
13 enum EGLDisplay EGL_NO_DISPLAY = null;
14 struct ANativeWindow;
15 struct egl_native_pixmap_t;
16 
17 alias EGLNativeWindowType = ANativeWindow*;
18 alias EGLNativePixmapType = egl_native_pixmap_t*;
19 alias EGLNativeDisplayType = void*;
20 
21 private {
22     SharedLib lib;
23     EGLSupport contextVersion = EGLSupport.noContext;
24     EGLSupport loadedVersion = EGLSupport.noContext;
25     EGLint major;
26     EGLint minor;
27 }
28 
29 @nogc nothrow:
30 
31 void unloadEGL()
32 {
33     if(lib != invalidHandle) {
34         lib.unload();
35         contextVersion = loadedVersion = EGLSupport.noContext;
36     }
37 }
38 
39 EGLSupport loadEGL()
40 {
41     version(Windows) {
42         const(char)[][1] libNames = ["libegl.dll"];
43     }
44     else version(Posix) {
45         const(char)[][2] libNames = [
46             "libEGL.so.1",
47             "libEGL.so"
48         ];
49     }
50     else static assert(0, "bindbc-gles is not yet supported on this platform");
51 
52     EGLSupport ret;
53     foreach(name; libNames) {
54         ret = loadEGL(name.ptr);
55         if(ret != EGLSupport.noLibrary) break;
56     }
57     return ret;
58 }
59 
60 EGLSupport loadEGL(const(char)* libName)
61 {
62     // If the library isn't yet loaded, load it now.
63     if(lib == invalidHandle) {
64         lib = load(libName);
65         if(lib == invalidHandle) {
66             return EGLSupport.noLibrary;
67         }
68     }
69     if(!lib.loadEGL()) return EGLSupport.badLibrary;
70     return loadedVersion;
71 }
72 
73 extern(System) @nogc nothrow {
74     // V1.0
75     alias peglGetError = void function(  );
76     alias peglGetDisplay = EGLDisplay function( EGLNativeDisplayType );
77     alias peglInitialize = EGLBoolean function( EGLDisplay, EGLint*, EGLint* );
78     alias peglTerminate = EGLBoolean function( EGLDisplay );
79     alias peglQueryString = const( char )* function( EGLDisplay, EGLint );
80     alias peglGetConfigs = EGLBoolean function( EGLDisplay, EGLConfig*, EGLint, EGLint* );
81     alias peglChooseConfig = EGLBoolean function( EGLDisplay, const( EGLint )*, EGLConfig*, EGLint, EGLint* );
82     alias peglGetConfigAttrib = EGLBoolean function( EGLDisplay, EGLConfig, EGLint, EGLint* );
83     alias peglCreateWindowSurface = EGLSurface function( EGLDisplay, EGLConfig, EGLNativeWindowType, const( EGLint )* );
84     alias peglCreatePbufferSurface = EGLSurface function( EGLDisplay, EGLConfig, const( EGLint )* );
85     alias peglCreatePixmapSurface = EGLSurface function( EGLDisplay, EGLConfig, EGLNativePixmapType, const( EGLint )* );
86     alias peglDestroySurface = EGLBoolean function( EGLDisplay, EGLSurface );
87     alias peglQuerySurface = EGLBoolean function( EGLDisplay, EGLSurface, EGLint, EGLint* );
88     alias peglCreateContext = EGLContext function( EGLDisplay, EGLConfig, EGLContext, const( EGLint )* );
89     alias peglDestroyContext = EGLBoolean function( EGLDisplay, EGLContext );
90     alias peglMakeCurrent = EGLBoolean function( EGLDisplay, EGLSurface, EGLSurface, EGLContext );
91     alias peglGetCurrentSurface = EGLSurface function( EGLint );
92     alias peglGetCurrentDisplay = EGLDisplay function(  );
93     alias peglQueryContext = EGLBoolean function( EGLDisplay, EGLContext, EGLint, EGLint* );
94     alias peglWaitGL = EGLBoolean function(  );
95     alias peglWaitNative = EGLBoolean function( EGLint );
96     alias peglSwapBuffers = EGLBoolean function( EGLDisplay, EGLSurface );
97     alias peglCopyBuffers = EGLBoolean function( EGLDisplay, EGLSurface, EGLNativePixmapType );
98     /* This is a generic function pointer type, whose name indicates it must be cast to the proper type *and calling convention* before use. */
99     alias __eglMustCastToProperFunctionPointerType = void function(  );
100     /* Now, define eglGetProcAddress using the generic function ptr. type */
101     alias peglGetProcAddress = __eglMustCastToProperFunctionPointerType function( const( char )* );
102 
103     //V1.1
104     alias peglSurfaceAttrib = EGLBoolean function( EGLDisplay, EGLSurface, EGLint, EGLint );
105     alias peglBindTexImage = EGLBoolean function( EGLDisplay, EGLSurface, EGLint );
106     alias peglReleaseTexImage = EGLBoolean function( EGLDisplay, EGLSurface, EGLint );
107     alias peglSwapInterval = EGLBoolean function( EGLDisplay, EGLint );
108 
109     //V1.2
110     alias peglBindAPI = EGLBoolean function( EGLenum );
111     alias peglQueryAPI = EGLenum function(  );
112     alias peglWaitClient = EGLBoolean function(  );
113     alias peglReleaseThread = EGLBoolean function(  );
114     alias peglCreatePbufferFromClientBuffer = EGLSurface function( EGLDisplay, EGLenum, EGLClientBuffer, EGLConfig, const( EGLint )* );
115     
116     //V1.4
117     alias peglGetCurrentContext = EGLContext function(  );
118     
119     //V1.5
120     alias peglCreateSync = EGLSync function ( EGLDisplay, EGLenum, const( EGLAttrib )* );
121     alias peglDestroySync = EGLBoolean function ( EGLDisplay, EGLSync );
122     alias peglClientWaitSync = EGLint function ( EGLDisplay, EGLSync, EGLint, EGLTime );
123     alias peglGetSyncAttrib = EGLBoolean function ( EGLDisplay, EGLSync, EGLint, EGLAttrib* );
124     alias peglGetPlatformDisplay = EGLDisplay function ( EGLenum, void*, const( EGLAttrib )* );
125     alias peglCreatePlatformWindowSurface = EGLSurface function ( EGLDisplay, EGLConfig, void*, const( EGLAttrib )* );
126     alias peglCreatePlatformPixmapSurface = EGLSurface function ( EGLDisplay, EGLConfig, void*, const( EGLAttrib )* );
127     alias peglWaitSync = EGLBoolean function ( EGLDisplay, EGLSync, EGLint );
128 }
129 
130 __gshared {
131     peglGetError eglGetError;
132     peglGetDisplay eglGetDisplay;
133     peglInitialize eglInitialize;
134     peglTerminate eglTerminate;
135     
136     peglQueryString eglQueryString;
137     peglGetConfigs eglGetConfigs;
138     peglChooseConfig eglChooseConfig;
139     peglGetConfigAttrib eglGetConfigAttrib;
140     peglCreateWindowSurface eglCreateWindowSurface;
141     peglCreatePbufferSurface eglCreatePbufferSurface;
142     peglCreatePixmapSurface eglCreatePixmapSurface;
143     peglDestroySurface eglDestroySurface;
144     peglQuerySurface eglQuerySurface;
145     peglCreateContext eglCreateContext;
146     peglDestroyContext eglDestroyContext;
147     peglMakeCurrent eglMakeCurrent;
148     peglGetCurrentSurface eglGetCurrentSurface;
149     peglGetCurrentDisplay eglGetCurrentDisplay;
150     peglQueryContext eglQueryContext;
151     peglWaitGL eglWaitGL;
152     peglWaitNative eglWaitNative;
153     peglSwapBuffers eglSwapBuffers;
154     peglCopyBuffers eglCopyBuffers;
155     peglGetProcAddress eglGetProcAddress;
156     
157     peglSurfaceAttrib eglSurfaceAttrib;
158     peglBindTexImage eglBindTexImage;
159     peglReleaseTexImage eglReleaseTexImage;
160     peglSwapInterval eglSwapInterval;
161 
162     peglBindAPI eglBindAPI;
163     peglQueryAPI eglQueryAPI;
164     peglWaitClient eglWaitClient;
165     peglReleaseThread eglReleaseThread;
166     peglCreatePbufferFromClientBuffer eglCreatePbufferFromClientBuffer;
167 
168     peglGetCurrentContext eglGetCurrentContext;
169     
170     peglCreateSync eglCreateSync;
171     peglDestroySync eglDestroySync;
172     peglClientWaitSync eglClientWaitSync;
173     peglGetSyncAttrib eglGetSyncAttrib;
174     peglGetPlatformDisplay eglGetPlatformDisplay;
175     peglCreatePlatformWindowSurface eglCreatePlatformWindowSurface;
176     peglCreatePlatformPixmapSurface eglCreatePlatformPixmapSurface;
177     peglWaitSync eglWaitSync;
178 }
179 
180 package(bindbc.gles) @nogc nothrow
181 bool loadEGL(SharedLib lib){
182     auto startErrorCount = errorCount();
183     lib.bindSymbol( cast( void** )&eglGetError, "eglGetError" );
184     lib.bindSymbol( cast( void** )&eglGetDisplay, "eglGetDisplay" );
185     lib.bindSymbol( cast( void** )&eglInitialize, "eglInitialize" );
186     lib.bindSymbol( cast( void** )&eglTerminate, "eglTerminate" );
187     
188     EGLDisplay disp = eglGetDisplay( EGL_DEFAULT_DISPLAY );
189     if( disp == EGL_NO_DISPLAY ) {
190         assert(0, "Unable to get a display for EGL");
191     }
192 
193     if( eglInitialize( disp, &major, &minor ) == EGL_FALSE ) {
194       //assert( "Failed to initialize the EGL display: " ~ to!string( eglGetError(  ) ) );
195     }
196     if( major != 1 ) {
197       eglTerminate( disp );
198       //assert( "The EGL version is not recognized: " ~ to!string( eglGetError(  ) ) );
199     }
200 
201     if( minor >= 0 ) {
202         lib.bindSymbol( cast( void** )&eglQueryString, "eglQueryString" );
203         lib.bindSymbol( cast( void** )&eglGetConfigs, "eglGetConfigs" );
204         lib.bindSymbol( cast( void** )&eglChooseConfig, "eglChooseConfig" );
205         lib.bindSymbol( cast( void** )&eglGetConfigAttrib, "eglGetConfigAttrib" );
206         lib.bindSymbol( cast( void** )&eglCreateWindowSurface, "eglCreateWindowSurface" );
207         lib.bindSymbol( cast( void** )&eglCreatePbufferSurface, "eglCreatePbufferSurface" );
208         lib.bindSymbol( cast( void** )&eglCreatePixmapSurface, "eglCreatePixmapSurface" );
209         lib.bindSymbol( cast( void** )&eglDestroySurface, "eglDestroySurface" );
210         lib.bindSymbol( cast( void** )&eglQuerySurface, "eglQuerySurface" );
211         lib.bindSymbol( cast( void** )&eglCreateContext, "eglCreateContext" );
212         lib.bindSymbol( cast( void** )&eglDestroyContext, "eglDestroyContext" );
213         lib.bindSymbol( cast( void** )&eglMakeCurrent, "eglMakeCurrent" );
214         lib.bindSymbol( cast( void** )&eglGetCurrentSurface, "eglGetCurrentSurface" );
215         lib.bindSymbol( cast( void** )&eglGetCurrentDisplay, "eglGetCurrentDisplay" );
216         lib.bindSymbol( cast( void** )&eglQueryContext, "eglQueryContext" );
217         lib.bindSymbol( cast( void** )&eglWaitGL, "eglWaitGL" );
218         lib.bindSymbol( cast( void** )&eglWaitNative, "eglWaitNative" );
219         lib.bindSymbol( cast( void** )&eglSwapBuffers, "eglSwapBuffers" );
220         lib.bindSymbol( cast( void** )&eglCopyBuffers, "eglCopyBuffers" );
221         lib.bindSymbol( cast( void** )&eglGetProcAddress, "eglGetProcAddress" );
222         loadedVersion = EGLSupport.EGL10;
223     }
224     if( minor >= 1 ) {
225         lib.bindSymbol( cast( void** )&eglSurfaceAttrib, "eglSurfaceAttrib" );
226         lib.bindSymbol( cast( void** )&eglBindTexImage, "eglBindTexImage" );
227         lib.bindSymbol( cast( void** )&eglReleaseTexImage, "eglReleaseTexImage" );
228         lib.bindSymbol( cast( void** )&eglSwapInterval, "eglSwapInterval" );
229         loadedVersion = EGLSupport.EGL11;
230     }
231     if( minor >= 2 ) {
232         lib.bindSymbol( cast( void** )&eglBindAPI, "eglBindAPI" );
233         lib.bindSymbol( cast( void** )&eglQueryAPI, "eglQueryAPI" );
234         lib.bindSymbol( cast( void** )&eglWaitClient, "eglWaitClient" );
235         lib.bindSymbol( cast( void** )&eglReleaseThread, "eglReleaseThread" );
236         lib.bindSymbol( cast( void** )&eglCreatePbufferFromClientBuffer, "eglCreatePbufferFromClientBuffer" );
237         loadedVersion = EGLSupport.EGL12;
238     }
239     if( minor >= 3 ) {
240         loadedVersion = EGLSupport.EGL13;
241     }
242     if( minor >= 4 ) {
243         lib.bindSymbol( cast( void** )&eglGetCurrentContext, "eglGetCurrentContext" );
244         loadedVersion = EGLSupport.EGL14;
245     }
246     if( minor >= 5 ) {
247         lib.bindSymbol( cast( void** )&eglCreateSync, "eglCreateSync" );
248         lib.bindSymbol( cast( void** )&eglDestroySync, "eglDestroySync" );
249         lib.bindSymbol( cast( void** )&eglClientWaitSync, "eglClientWaitSync" );
250         lib.bindSymbol( cast( void** )&eglGetSyncAttrib, "eglGetSyncAttrib" );
251         lib.bindSymbol( cast( void** )&eglGetPlatformDisplay, "eglGetPlatformDisplay" );
252         lib.bindSymbol( cast( void** )&eglCreatePlatformWindowSurface, "eglCreatePlatformWindowSurface" );
253         lib.bindSymbol( cast( void** )&eglCreatePlatformPixmapSurface, "eglCreatePlatformPixmapSurface" );
254         lib.bindSymbol( cast( void** )&eglWaitSync, "eglWaitSync" );
255         loadedVersion = EGLSupport.EGL14;
256     }
257     return(errorCount() == startErrorCount);
258 }
259 EGLint EGLversionMajor() { return major; }
260 EGLint EGLversionMinor() { return minor; }
261 
262 package:
263     SharedLib libGLES() { return lib; }