1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 #ifndef GLLIBRARYEGL_H_
6 #define GLLIBRARYEGL_H_
7 
8 #if defined(MOZ_X11)
9 #include "mozilla/X11Util.h"
10 #endif
11 
12 #include "GLLibraryLoader.h"
13 #include "mozilla/StaticMutex.h"
14 #include "mozilla/ThreadLocal.h"
15 #include "nsIFile.h"
16 #include "GeckoProfiler.h"
17 
18 #include <bitset>
19 #include <vector>
20 
21 #ifdef XP_WIN
22     #ifndef WIN32_LEAN_AND_MEAN
23         #define WIN32_LEAN_AND_MEAN 1
24     #endif
25 
26     #include <windows.h>
27 
28     typedef HDC EGLNativeDisplayType;
29     typedef HBITMAP EGLNativePixmapType;
30     typedef HWND EGLNativeWindowType;
31 #else
32     typedef void* EGLNativeDisplayType;
33     typedef void* EGLNativePixmapType;
34     typedef void* EGLNativeWindowType;
35 
36     #ifdef ANDROID
37         // We only need to explicitly dlopen egltrace
38         // on android as we can use LD_PRELOAD or other tricks
39         // on other platforms. We look for it in /data/local
40         // as that's writeable by all users
41         //
42         // This should really go in GLLibraryEGL.cpp but we currently reference
43         // APITRACE_LIB in GLContextProviderEGL.cpp. Further refactoring
44         // will come in subsequent patches on Bug 732865
45         #define APITRACE_LIB "/data/local/tmp/egltrace.so"
46     #endif
47 #endif
48 
49 #if defined(MOZ_X11)
50 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
51 #else
52 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)0)
53 #endif
54 
55 namespace angle {
56 class Platform;
57 }
58 
59 namespace mozilla {
60 
61 namespace gfx {
62 class DataSourceSurface;
63 }
64 
65 namespace gl {
66 
67 #undef BEFORE_GL_CALL
68 #undef AFTER_GL_CALL
69 
70 #ifdef DEBUG
71 
72 #ifndef MOZ_FUNCTION_NAME
73 # ifdef __GNUC__
74 #  define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
75 # elif defined(_MSC_VER)
76 #  define MOZ_FUNCTION_NAME __FUNCTION__
77 # else
78 #  define MOZ_FUNCTION_NAME __func__  // defined in C99, supported in various C++ compilers. Just raw function name.
79 # endif
80 #endif
81 
82 #ifdef MOZ_WIDGET_ANDROID
83 // Record the name of the GL call for better hang stacks on Android.
84 #define BEFORE_GL_CALL                      \
85     PROFILER_LABEL_FUNC(                    \
86       js::ProfileEntry::Category::GRAPHICS);\
87     BeforeGLCall(MOZ_FUNCTION_NAME)
88 #else
89 #define BEFORE_GL_CALL do {          \
90     BeforeGLCall(MOZ_FUNCTION_NAME); \
91 } while (0)
92 #endif
93 
94 #define AFTER_GL_CALL do {           \
95     AfterGLCall(MOZ_FUNCTION_NAME);  \
96 } while (0)
97 #else
98 #ifdef MOZ_WIDGET_ANDROID
99 // Record the name of the GL call for better hang stacks on Android.
100 #define BEFORE_GL_CALL PROFILER_LABEL_FUNC(js::ProfileEntry::Category::GRAPHICS)
101 #else
102 #define BEFORE_GL_CALL
103 #endif
104 #define AFTER_GL_CALL
105 #endif
106 
107 class GLContext;
108 
109 class GLLibraryEGL
110 {
111 public:
GLLibraryEGL()112     GLLibraryEGL()
113         : mInitialized(false),
114           mEGLLibrary(nullptr),
115           mEGLDisplay(EGL_NO_DISPLAY),
116           mIsANGLE(false),
117           mIsWARP(false)
118     {
119         ClearSymbols();
120     }
121 
ClearSymbols()122     void ClearSymbols() {
123         mSymbols.fANGLEPlatformInitialize = nullptr;
124         mSymbols.fANGLEPlatformShutdown = nullptr;
125         mSymbols.fGetDisplay = nullptr;
126         mSymbols.fGetPlatformDisplayEXT = nullptr;
127         mSymbols.fTerminate = nullptr;
128         mSymbols.fGetCurrentSurface = nullptr;
129         mSymbols.fGetCurrentContext = nullptr;
130         mSymbols.fMakeCurrent = nullptr;
131         mSymbols.fDestroyContext = nullptr;
132         mSymbols.fCreateContext = nullptr;
133         mSymbols.fDestroySurface = nullptr;
134         mSymbols.fCreateWindowSurface = nullptr;
135         mSymbols.fCreatePbufferSurface = nullptr;
136         mSymbols.fCreatePixmapSurface = nullptr;
137         mSymbols.fBindAPI = nullptr;
138         mSymbols.fInitialize = nullptr;
139         mSymbols.fChooseConfig = nullptr;
140         mSymbols.fGetError = nullptr;
141         mSymbols.fGetConfigAttrib = nullptr;
142         mSymbols.fGetConfigs = nullptr;
143         mSymbols.fWaitNative = nullptr;
144         mSymbols.fGetProcAddress = nullptr;
145         mSymbols.fSwapBuffers = nullptr;
146         mSymbols.fCopyBuffers = nullptr;
147         mSymbols.fQueryString = nullptr;
148         mSymbols.fQueryStringImplementationANDROID = nullptr;
149         mSymbols.fQueryContext = nullptr;
150         mSymbols.fBindTexImage = nullptr;
151         mSymbols.fReleaseTexImage = nullptr;
152         mSymbols.fCreateImage = nullptr;
153         mSymbols.fDestroyImage = nullptr;
154         mSymbols.fLockSurface = nullptr;
155         mSymbols.fUnlockSurface = nullptr;
156         mSymbols.fQuerySurface = nullptr;
157         mSymbols.fQuerySurfacePointerANGLE = nullptr;
158         mSymbols.fCreateSync = nullptr;
159         mSymbols.fDestroySync = nullptr;
160         mSymbols.fClientWaitSync = nullptr;
161         mSymbols.fGetSyncAttrib = nullptr;
162         mSymbols.fDupNativeFenceFDANDROID = nullptr;
163     }
164 
165     void InitClientExtensions();
166     void InitDisplayExtensions();
167 
168     /**
169      * Known GL extensions that can be queried by
170      * IsExtensionSupported.  The results of this are cached, and as
171      * such it's safe to use this even in performance critical code.
172      * If you add to this array, remember to add to the string names
173      * in GLContext.cpp.
174      */
175     enum EGLExtensions {
176         KHR_image_base,
177         KHR_image_pixmap,
178         KHR_gl_texture_2D_image,
179         KHR_lock_surface,
180         ANGLE_surface_d3d_texture_2d_share_handle,
181         EXT_create_context_robustness,
182         KHR_image,
183         KHR_fence_sync,
184         ANDROID_native_fence_sync,
185         EGL_ANDROID_image_crop,
186         ANGLE_platform_angle,
187         ANGLE_platform_angle_d3d,
188         Extensions_Max
189     };
190 
IsExtensionSupported(EGLExtensions aKnownExtension)191     bool IsExtensionSupported(EGLExtensions aKnownExtension) const {
192         return mAvailableExtensions[aKnownExtension];
193     }
194 
MarkExtensionUnsupported(EGLExtensions aKnownExtension)195     void MarkExtensionUnsupported(EGLExtensions aKnownExtension) {
196         mAvailableExtensions[aKnownExtension] = false;
197     }
198 
199 protected:
200     std::bitset<Extensions_Max> mAvailableExtensions;
201 
202 public:
203 
fGetDisplay(void * display_id)204     EGLDisplay fGetDisplay(void* display_id)
205     {
206         BEFORE_GL_CALL;
207         EGLDisplay disp = mSymbols.fGetDisplay(display_id);
208         AFTER_GL_CALL;
209         return disp;
210     }
211 
fGetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)212     EGLDisplay fGetPlatformDisplayEXT(EGLenum platform, void* native_display, const EGLint* attrib_list)
213     {
214         BEFORE_GL_CALL;
215         EGLDisplay disp = mSymbols.fGetPlatformDisplayEXT(platform, native_display, attrib_list);
216         AFTER_GL_CALL;
217         return disp;
218     }
219 
fTerminate(EGLDisplay display)220     EGLBoolean fTerminate(EGLDisplay display)
221     {
222         BEFORE_GL_CALL;
223         EGLBoolean ret = mSymbols.fTerminate(display);
224         AFTER_GL_CALL;
225         return ret;
226     }
227 
fGetCurrentSurface(EGLint id)228     EGLSurface fGetCurrentSurface(EGLint id)
229     {
230         BEFORE_GL_CALL;
231         EGLSurface surf = mSymbols.fGetCurrentSurface(id);
232         AFTER_GL_CALL;
233         return surf;
234     }
235 
fGetCurrentContext()236     EGLContext fGetCurrentContext()
237     {
238         BEFORE_GL_CALL;
239         EGLContext context = mSymbols.fGetCurrentContext();
240         AFTER_GL_CALL;
241         return context;
242     }
243 
fMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)244     EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
245     {
246         BEFORE_GL_CALL;
247         EGLBoolean b = mSymbols.fMakeCurrent(dpy, draw, read, ctx);
248         AFTER_GL_CALL;
249         return b;
250     }
251 
fDestroyContext(EGLDisplay dpy,EGLContext ctx)252     EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx)
253     {
254         BEFORE_GL_CALL;
255         EGLBoolean b = mSymbols.fDestroyContext(dpy, ctx);
256         AFTER_GL_CALL;
257         return b;
258     }
259 
fCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)260     EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list)
261     {
262         BEFORE_GL_CALL;
263         EGLContext ctx = mSymbols.fCreateContext(dpy, config, share_context, attrib_list);
264         AFTER_GL_CALL;
265         return ctx;
266     }
267 
fDestroySurface(EGLDisplay dpy,EGLSurface surface)268     EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface)
269     {
270         BEFORE_GL_CALL;
271         EGLBoolean b = mSymbols.fDestroySurface(dpy, surface);
272         AFTER_GL_CALL;
273         return b;
274     }
275 
fCreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)276     EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list)
277     {
278         BEFORE_GL_CALL;
279         EGLSurface surf = mSymbols.fCreateWindowSurface(dpy, config, win, attrib_list);
280         AFTER_GL_CALL;
281         return surf;
282     }
283 
fCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)284     EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list)
285     {
286         BEFORE_GL_CALL;
287         EGLSurface surf = mSymbols.fCreatePbufferSurface(dpy, config, attrib_list);
288         AFTER_GL_CALL;
289         return surf;
290     }
291 
fCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)292     EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list)
293     {
294         BEFORE_GL_CALL;
295         EGLSurface surf = mSymbols.fCreatePixmapSurface(dpy, config, pixmap, attrib_list);
296         AFTER_GL_CALL;
297         return surf;
298     }
299 
fBindAPI(EGLenum api)300     EGLBoolean fBindAPI(EGLenum api)
301     {
302         BEFORE_GL_CALL;
303         EGLBoolean b = mSymbols.fBindAPI(api);
304         AFTER_GL_CALL;
305         return b;
306     }
307 
fInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)308     EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor)
309     {
310         BEFORE_GL_CALL;
311         EGLBoolean b = mSymbols.fInitialize(dpy, major, minor);
312         AFTER_GL_CALL;
313         return b;
314     }
315 
fChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)316     EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config)
317     {
318         BEFORE_GL_CALL;
319         EGLBoolean b = mSymbols.fChooseConfig(dpy, attrib_list, configs, config_size, num_config);
320         AFTER_GL_CALL;
321         return b;
322     }
323 
fGetError()324     EGLint fGetError()
325     {
326         BEFORE_GL_CALL;
327         EGLint i = mSymbols.fGetError();
328         AFTER_GL_CALL;
329         return i;
330     }
331 
fGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)332     EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value)
333     {
334         BEFORE_GL_CALL;
335         EGLBoolean b = mSymbols.fGetConfigAttrib(dpy, config, attribute, value);
336         AFTER_GL_CALL;
337         return b;
338     }
339 
fGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)340     EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config)
341     {
342         BEFORE_GL_CALL;
343         EGLBoolean b = mSymbols.fGetConfigs(dpy, configs, config_size, num_config);
344         AFTER_GL_CALL;
345         return b;
346     }
347 
fWaitNative(EGLint engine)348     EGLBoolean fWaitNative(EGLint engine)
349     {
350         BEFORE_GL_CALL;
351         EGLBoolean b = mSymbols.fWaitNative(engine);
352         AFTER_GL_CALL;
353         return b;
354     }
355 
fGetProcAddress(const char * procname)356     EGLCastToRelevantPtr fGetProcAddress(const char* procname)
357     {
358         BEFORE_GL_CALL;
359         EGLCastToRelevantPtr p = mSymbols.fGetProcAddress(procname);
360         AFTER_GL_CALL;
361         return p;
362     }
363 
fSwapBuffers(EGLDisplay dpy,EGLSurface surface)364     EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface)
365     {
366         BEFORE_GL_CALL;
367         EGLBoolean b = mSymbols.fSwapBuffers(dpy, surface);
368         AFTER_GL_CALL;
369         return b;
370     }
371 
fCopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)372     EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
373     {
374         BEFORE_GL_CALL;
375         EGLBoolean b = mSymbols.fCopyBuffers(dpy, surface, target);
376         AFTER_GL_CALL;
377         return b;
378     }
379 
fQueryString(EGLDisplay dpy,EGLint name)380     const GLubyte* fQueryString(EGLDisplay dpy, EGLint name)
381     {
382         BEFORE_GL_CALL;
383         const GLubyte* b;
384         if (mSymbols.fQueryStringImplementationANDROID) {
385           b = mSymbols.fQueryStringImplementationANDROID(dpy, name);
386         } else {
387           b = mSymbols.fQueryString(dpy, name);
388         }
389         AFTER_GL_CALL;
390         return b;
391     }
392 
fQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)393     EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value)
394     {
395         BEFORE_GL_CALL;
396         EGLBoolean b = mSymbols.fQueryContext(dpy, ctx, attribute, value);
397         AFTER_GL_CALL;
398         return b;
399     }
400 
fBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)401     EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
402     {
403         BEFORE_GL_CALL;
404         EGLBoolean b = mSymbols.fBindTexImage(dpy, surface, buffer);
405         AFTER_GL_CALL;
406         return b;
407     }
408 
fReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)409     EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
410     {
411         BEFORE_GL_CALL;
412         EGLBoolean b = mSymbols.fReleaseTexImage(dpy, surface, buffer);
413         AFTER_GL_CALL;
414         return b;
415     }
416 
fCreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)417     EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list)
418     {
419          BEFORE_GL_CALL;
420          EGLImage i = mSymbols.fCreateImage(dpy, ctx, target, buffer, attrib_list);
421          AFTER_GL_CALL;
422          return i;
423     }
424 
fDestroyImage(EGLDisplay dpy,EGLImage image)425     EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image)
426     {
427         BEFORE_GL_CALL;
428         EGLBoolean b = mSymbols.fDestroyImage(dpy, image);
429         AFTER_GL_CALL;
430         return b;
431     }
432 
433     // New extension which allow us to lock texture and get raw image pointer
fLockSurface(EGLDisplay dpy,EGLSurface surface,const EGLint * attrib_list)434     EGLBoolean fLockSurface(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list)
435     {
436         BEFORE_GL_CALL;
437         EGLBoolean b = mSymbols.fLockSurface(dpy, surface, attrib_list);
438         AFTER_GL_CALL;
439         return b;
440     }
441 
fUnlockSurface(EGLDisplay dpy,EGLSurface surface)442     EGLBoolean fUnlockSurface(EGLDisplay dpy, EGLSurface surface)
443     {
444         BEFORE_GL_CALL;
445         EGLBoolean b = mSymbols.fUnlockSurface(dpy, surface);
446         AFTER_GL_CALL;
447         return b;
448     }
449 
fQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)450     EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value)
451     {
452         BEFORE_GL_CALL;
453         EGLBoolean b = mSymbols.fQuerySurface(dpy, surface, attribute, value);
454         AFTER_GL_CALL;
455         return b;
456     }
457 
fQuerySurfacePointerANGLE(EGLDisplay dpy,EGLSurface surface,EGLint attribute,void ** value)458     EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value)
459     {
460         BEFORE_GL_CALL;
461         EGLBoolean b = mSymbols.fQuerySurfacePointerANGLE(dpy, surface, attribute, value);
462         AFTER_GL_CALL;
463         return b;
464     }
465 
fCreateSync(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)466     EGLSync fCreateSync(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list)
467     {
468         BEFORE_GL_CALL;
469         EGLSync ret = mSymbols.fCreateSync(dpy, type, attrib_list);
470         AFTER_GL_CALL;
471         return ret;
472     }
473 
fDestroySync(EGLDisplay dpy,EGLSync sync)474     EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync)
475     {
476         BEFORE_GL_CALL;
477         EGLBoolean b = mSymbols.fDestroySync(dpy, sync);
478         AFTER_GL_CALL;
479         return b;
480     }
481 
fClientWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)482     EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
483     {
484         BEFORE_GL_CALL;
485         EGLint ret = mSymbols.fClientWaitSync(dpy, sync, flags, timeout);
486         AFTER_GL_CALL;
487         return ret;
488     }
489 
fGetSyncAttrib(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLint * value)490     EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value)
491     {
492         BEFORE_GL_CALL;
493         EGLBoolean b = mSymbols.fGetSyncAttrib(dpy, sync, attribute, value);
494         AFTER_GL_CALL;
495         return b;
496     }
497 
fDupNativeFenceFDANDROID(EGLDisplay dpy,EGLSync sync)498     EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
499     {
500         MOZ_ASSERT(mSymbols.fDupNativeFenceFDANDROID);
501         BEFORE_GL_CALL;
502         EGLint ret = mSymbols.fDupNativeFenceFDANDROID(dpy, sync);
503         AFTER_GL_CALL;
504         return ret;
505     }
506 
fANGLEPlatformInitialize(angle::Platform * platform)507     void fANGLEPlatformInitialize(angle::Platform* platform)
508     {
509         MOZ_ASSERT(mSymbols.fANGLEPlatformInitialize);
510         BEFORE_GL_CALL;
511         mSymbols.fANGLEPlatformInitialize(platform);
512         AFTER_GL_CALL;
513     }
514 
fANGLEPlatformShutdown()515     void fANGLEPlatformShutdown()
516     {
517         MOZ_ASSERT(mSymbols.fANGLEPlatformShutdown);
518         BEFORE_GL_CALL;
519         mSymbols.fANGLEPlatformShutdown();
520         AFTER_GL_CALL;
521     }
522 
Display()523     EGLDisplay Display() {
524         MOZ_ASSERT(mInitialized);
525         return mEGLDisplay;
526     }
527 
IsANGLE()528     bool IsANGLE() const {
529         MOZ_ASSERT(mInitialized);
530         return mIsANGLE;
531     }
532 
IsWARP()533     bool IsWARP() const {
534         MOZ_ASSERT(mInitialized);
535         return mIsWARP;
536     }
537 
HasKHRImageBase()538     bool HasKHRImageBase() {
539         return IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_base);
540     }
541 
HasKHRImagePixmap()542     bool HasKHRImagePixmap() {
543         return IsExtensionSupported(KHR_image) || IsExtensionSupported(KHR_image_pixmap);
544     }
545 
HasKHRImageTexture2D()546     bool HasKHRImageTexture2D() {
547         return IsExtensionSupported(KHR_gl_texture_2D_image);
548     }
549 
HasANGLESurfaceD3DTexture2DShareHandle()550     bool HasANGLESurfaceD3DTexture2DShareHandle() {
551         return IsExtensionSupported(ANGLE_surface_d3d_texture_2d_share_handle);
552     }
553 
HasRobustness()554     bool HasRobustness() const {
555         return IsExtensionSupported(EXT_create_context_robustness);
556     }
557 
558     bool ReadbackEGLImage(EGLImage image, gfx::DataSourceSurface* out_surface);
559 
560     bool EnsureInitialized(bool forceAccel, nsACString* const out_failureId);
561 
562     void DumpEGLConfig(EGLConfig cfg);
563     void DumpEGLConfigs();
564 
565     struct {
566         typedef EGLDisplay (GLAPIENTRY * pfnGetDisplay)(void* display_id);
567         pfnGetDisplay fGetDisplay;
568         typedef EGLDisplay(GLAPIENTRY * pfnGetPlatformDisplayEXT)(EGLenum platform, void* native_display, const EGLint* attrib_list);
569         pfnGetPlatformDisplayEXT fGetPlatformDisplayEXT;
570         typedef EGLBoolean (GLAPIENTRY * pfnTerminate)(EGLDisplay dpy);
571         pfnTerminate fTerminate;
572         typedef EGLSurface (GLAPIENTRY * pfnGetCurrentSurface)(EGLint);
573         pfnGetCurrentSurface fGetCurrentSurface;
574         typedef EGLContext (GLAPIENTRY * pfnGetCurrentContext)(void);
575         pfnGetCurrentContext fGetCurrentContext;
576         typedef EGLBoolean (GLAPIENTRY * pfnMakeCurrent)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
577         pfnMakeCurrent fMakeCurrent;
578         typedef EGLBoolean (GLAPIENTRY * pfnDestroyContext)(EGLDisplay dpy, EGLContext ctx);
579         pfnDestroyContext fDestroyContext;
580         typedef EGLContext (GLAPIENTRY * pfnCreateContext)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint* attrib_list);
581         pfnCreateContext fCreateContext;
582         typedef EGLBoolean (GLAPIENTRY * pfnDestroySurface)(EGLDisplay dpy, EGLSurface surface);
583         pfnDestroySurface fDestroySurface;
584         typedef EGLSurface (GLAPIENTRY * pfnCreateWindowSurface)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list);
585         pfnCreateWindowSurface fCreateWindowSurface;
586         typedef EGLSurface (GLAPIENTRY * pfnCreatePbufferSurface)(EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list);
587         pfnCreatePbufferSurface fCreatePbufferSurface;
588         typedef EGLSurface (GLAPIENTRY * pfnCreatePixmapSurface)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint* attrib_list);
589         pfnCreatePixmapSurface fCreatePixmapSurface;
590         typedef EGLBoolean (GLAPIENTRY * pfnBindAPI)(EGLenum api);
591         pfnBindAPI fBindAPI;
592         typedef EGLBoolean (GLAPIENTRY * pfnInitialize)(EGLDisplay dpy, EGLint* major, EGLint* minor);
593         pfnInitialize fInitialize;
594         typedef EGLBoolean (GLAPIENTRY * pfnChooseConfig)(EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, EGLint config_size, EGLint* num_config);
595         pfnChooseConfig fChooseConfig;
596         typedef EGLint (GLAPIENTRY * pfnGetError)(void);
597         pfnGetError fGetError;
598         typedef EGLBoolean (GLAPIENTRY * pfnGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value);
599         pfnGetConfigAttrib fGetConfigAttrib;
600         typedef EGLBoolean (GLAPIENTRY * pfnGetConfigs)(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, EGLint* num_config);
601         pfnGetConfigs fGetConfigs;
602         typedef EGLBoolean (GLAPIENTRY * pfnWaitNative)(EGLint engine);
603         pfnWaitNative fWaitNative;
604         typedef EGLCastToRelevantPtr (GLAPIENTRY * pfnGetProcAddress)(const char* procname);
605         pfnGetProcAddress fGetProcAddress;
606         typedef EGLBoolean (GLAPIENTRY * pfnSwapBuffers)(EGLDisplay dpy, EGLSurface surface);
607         pfnSwapBuffers fSwapBuffers;
608         typedef EGLBoolean (GLAPIENTRY * pfnCopyBuffers)(EGLDisplay dpy, EGLSurface surface,
609                                                          EGLNativePixmapType target);
610         pfnCopyBuffers fCopyBuffers;
611         typedef const GLubyte* (GLAPIENTRY * pfnQueryString)(EGLDisplay, EGLint name);
612         pfnQueryString fQueryString;
613         pfnQueryString fQueryStringImplementationANDROID;
614         typedef EGLBoolean (GLAPIENTRY * pfnQueryContext)(EGLDisplay dpy, EGLContext ctx,
615                                                           EGLint attribute, EGLint* value);
616         pfnQueryContext fQueryContext;
617         typedef EGLBoolean (GLAPIENTRY * pfnBindTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
618         pfnBindTexImage fBindTexImage;
619         typedef EGLBoolean (GLAPIENTRY * pfnReleaseTexImage)(EGLDisplay, EGLSurface surface, EGLint buffer);
620         pfnReleaseTexImage fReleaseTexImage;
621         typedef EGLImage (GLAPIENTRY * pfnCreateImage)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint* attrib_list);
622         pfnCreateImage fCreateImage;
623         typedef EGLBoolean (GLAPIENTRY * pfnDestroyImage)(EGLDisplay dpy, EGLImage image);
624         pfnDestroyImage fDestroyImage;
625 
626         // New extension which allow us to lock texture and get raw image pointer
627         typedef EGLBoolean (GLAPIENTRY * pfnLockSurface)(EGLDisplay dpy, EGLSurface surface, const EGLint* attrib_list);
628         pfnLockSurface fLockSurface;
629         typedef EGLBoolean (GLAPIENTRY * pfnUnlockSurface)(EGLDisplay dpy, EGLSurface surface);
630         pfnUnlockSurface fUnlockSurface;
631         typedef EGLBoolean (GLAPIENTRY * pfnQuerySurface)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value);
632         pfnQuerySurface fQuerySurface;
633 
634         typedef EGLBoolean (GLAPIENTRY * pfnQuerySurfacePointerANGLE)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value);
635         pfnQuerySurfacePointerANGLE fQuerySurfacePointerANGLE;
636 
637         typedef EGLSync (GLAPIENTRY * pfnCreateSync)(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list);
638         pfnCreateSync fCreateSync;
639         typedef EGLBoolean (GLAPIENTRY * pfnDestroySync)(EGLDisplay dpy, EGLSync sync);
640         pfnDestroySync fDestroySync;
641         typedef EGLint (GLAPIENTRY * pfnClientWaitSync)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
642         pfnClientWaitSync fClientWaitSync;
643         typedef EGLBoolean (GLAPIENTRY * pfnGetSyncAttrib)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value);
644         pfnGetSyncAttrib fGetSyncAttrib;
645         typedef EGLint (GLAPIENTRY * pfnDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
646         pfnDupNativeFenceFDANDROID fDupNativeFenceFDANDROID;
647 
648         typedef void (GLAPIENTRY * pfnANGLEPlatformInitialize)(angle::Platform* platform);
649         pfnANGLEPlatformInitialize fANGLEPlatformInitialize;
650         typedef void (GLAPIENTRY * pfnANGLEPlatformShutdown)();
651         pfnANGLEPlatformShutdown fANGLEPlatformShutdown;
652     } mSymbols;
653 
654 #ifdef DEBUG
655     static void BeforeGLCall(const char* glFunction);
656     static void AfterGLCall(const char* glFunction);
657 #endif
658 
659 #ifdef MOZ_B2G
CachedCurrentContext()660     EGLContext CachedCurrentContext() {
661         return sCurrentContext.get();
662     }
UnsetCachedCurrentContext()663     void UnsetCachedCurrentContext() {
664         sCurrentContext.set(nullptr);
665     }
SetCachedCurrentContext(EGLContext aCtx)666     void SetCachedCurrentContext(EGLContext aCtx) {
667         sCurrentContext.set(aCtx);
668     }
CachedCurrentContextMatches()669     bool CachedCurrentContextMatches() {
670         return sCurrentContext.get() == fGetCurrentContext();
671     }
672 
673 private:
674     static MOZ_THREAD_LOCAL(EGLContext) sCurrentContext;
675 public:
676 
677 #else
678     EGLContext CachedCurrentContext() {
679         return nullptr;
680     }
681     void UnsetCachedCurrentContext() {}
682     void SetCachedCurrentContext(EGLContext aCtx) { }
683     bool CachedCurrentContextMatches() { return true; }
684 #endif
685 
686 private:
687     bool mInitialized;
688     PRLibrary* mEGLLibrary;
689     EGLDisplay mEGLDisplay;
690     RefPtr<GLContext> mReadbackGL;
691 
692     bool mIsANGLE;
693     bool mIsWARP;
694     static StaticMutex sMutex;
695 };
696 
697 extern GLLibraryEGL sEGLLibrary;
698 #define EGL_DISPLAY()        sEGLLibrary.Display()
699 
700 } /* namespace gl */
701 } /* namespace mozilla */
702 
703 #endif /* GLLIBRARYEGL_H_ */
704 
705