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/. */
5 #ifndef GLLIBRARYEGL_H_
6 #define GLLIBRARYEGL_H_
9 # include "mozilla/X11Util.h"
12 #include "base/platform_thread.h" // for PlatformThreadId
14 #include "GLContext.h"
15 #include "mozilla/EnumTypeTraits.h"
16 #include "mozilla/gfx/Logging.h"
17 #include "mozilla/Maybe.h"
18 #include "mozilla/Mutex.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/StaticMutex.h"
21 #include "mozilla/StaticPtr.h"
22 #include "nsISupports.h"
27 #include <unordered_map>
29 #ifdef MOZ_WIDGET_ANDROID
30 # include "mozilla/ProfilerLabels.h"
31 # include "AndroidBuild.h"
35 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
37 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
43 struct AHardwareBuffer
;
53 class DataSourceSurface
;
60 PRLibrary
* LoadApitraceLibrary();
62 void BeforeEGLCall(const char* funcName
);
63 void AfterEGLCall(const char* funcName
);
67 * Known GL extensions that can be queried by
68 * IsExtensionSupported. The results of this are cached, and as
69 * such it's safe to use this even in performance critical code.
70 * If you add to this array, remember to add to the string names
71 * in GLLibraryEGL.cpp.
73 enum class EGLLibExtension
{
74 ANDROID_get_native_client_buffer
,
75 ANGLE_device_creation
,
76 ANGLE_device_creation_d3d11
,
78 ANGLE_platform_angle_d3d
,
79 EXT_device_enumeration
,
82 MESA_platform_surfaceless
,
87 * Known GL extensions that can be queried by
88 * IsExtensionSupported. The results of this are cached, and as
89 * such it's safe to use this even in performance critical code.
90 * If you add to this array, remember to add to the string names
91 * in GLLibraryEGL.cpp.
93 enum class EGLExtension
{
96 KHR_gl_texture_2D_image
,
97 ANGLE_surface_d3d_texture_2d_share_handle
,
98 EXT_create_context_robustness
,
102 ANDROID_native_fence_sync
,
103 EGL_ANDROID_image_crop
,
104 ANGLE_d3d_share_handle_client_buffer
,
107 KHR_stream_consumer_gltexture
,
108 NV_stream_consumer_gltexture_yuv
,
109 ANGLE_stream_producer_d3d_texture
,
110 KHR_surfaceless_context
,
111 KHR_create_context_no_error
,
112 MOZ_create_context_provoking_vertex_dont_care
,
113 EXT_swap_buffers_with_damage
,
114 KHR_swap_buffers_with_damage
,
117 NV_robustness_video_memory_purge
,
118 EXT_image_dma_buf_import
,
119 EXT_image_dma_buf_import_modifiers
,
120 MESA_image_dma_buf_export
,
121 KHR_no_config_context
,
127 class GLLibraryEGL final
{
128 friend class EglDisplay
;
131 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL
)
134 PRLibrary
* mEGLLibrary
= nullptr;
135 PRLibrary
* mGLLibrary
= nullptr;
136 bool mIsANGLE
= false;
137 std::bitset
<UnderlyingValue(EGLLibExtension::Max
)> mAvailableExtensions
;
138 std::weak_ptr
<EglDisplay
> mDefaultDisplay
;
139 std::unordered_map
<EGLDisplay
, std::weak_ptr
<EglDisplay
>> mActiveDisplays
;
142 static RefPtr
<GLLibraryEGL
> Get(nsACString
* const out_failureId
);
143 static void Shutdown();
146 ~GLLibraryEGL() = default;
148 static StaticMutex sMutex
;
149 static StaticRefPtr
<GLLibraryEGL
> sInstance
MOZ_GUARDED_BY(sMutex
);
151 bool Init(nsACString
* const out_failureId
);
152 void InitLibExtensions();
154 std::shared_ptr
<EglDisplay
> CreateDisplayLocked(
155 bool forceAccel
, nsACString
* const out_failureId
,
156 const StaticMutexAutoLock
& aProofOfLock
);
159 Maybe
<SymbolLoader
> GetSymbolLoader() const;
161 std::shared_ptr
<EglDisplay
> CreateDisplay(bool forceAccel
,
162 nsACString
* const out_failureId
);
163 std::shared_ptr
<EglDisplay
> CreateDisplay(ID3D11Device
*);
164 std::shared_ptr
<EglDisplay
> DefaultDisplay(nsACString
* const out_failureId
);
166 bool IsExtensionSupported(EGLLibExtension aKnownExtension
) const {
167 return mAvailableExtensions
[UnderlyingValue(aKnownExtension
)];
170 void MarkExtensionUnsupported(EGLLibExtension aKnownExtension
) {
171 mAvailableExtensions
[UnderlyingValue(aKnownExtension
)] = false;
174 bool IsANGLE() const { return mIsANGLE
; }
179 #ifdef MOZ_WIDGET_ANDROID
180 # define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
182 # define PROFILE_CALL
185 #ifndef MOZ_FUNCTION_NAME
187 # define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
188 # elif defined(_MSC_VER)
189 # define MOZ_FUNCTION_NAME __FUNCTION__
191 # define MOZ_FUNCTION_NAME \
192 __func__ // defined in C99, supported in various C++ compilers. Just raw
198 # define BEFORE_CALL BeforeEGLCall(MOZ_FUNCTION_NAME);
199 # define AFTER_CALL AfterEGLCall(MOZ_FUNCTION_NAME);
208 const auto ret = mSymbols.X; \
213 EGLDisplay
fGetDisplay(void* display_id
) const {
214 WRAP(fGetDisplay(display_id
));
217 EGLDisplay
fGetPlatformDisplay(EGLenum platform
, void* native_display
,
218 const EGLAttrib
* attrib_list
) const {
219 WRAP(fGetPlatformDisplay(platform
, native_display
, attrib_list
));
222 EGLSurface
fGetCurrentSurface(EGLint id
) const {
223 WRAP(fGetCurrentSurface(id
));
226 EGLContext
fGetCurrentContext() const { WRAP(fGetCurrentContext()); }
228 EGLBoolean
fBindAPI(EGLenum api
) const { WRAP(fBindAPI(api
)); }
230 EGLint
fGetError() const { WRAP(fGetError()); }
232 EGLBoolean
fWaitNative(EGLint engine
) const { WRAP(fWaitNative(engine
)); }
234 EGLCastToRelevantPtr
fGetProcAddress(const char* procname
) const {
235 WRAP(fGetProcAddress(procname
));
238 // ANGLE_device_creation
239 EGLDeviceEXT
fCreateDeviceANGLE(EGLint device_type
, void* native_device
,
240 const EGLAttrib
* attrib_list
) const {
241 WRAP(fCreateDeviceANGLE(device_type
, native_device
, attrib_list
));
244 EGLBoolean
fReleaseDeviceANGLE(EGLDeviceEXT device
) {
245 WRAP(fReleaseDeviceANGLE(device
));
248 // ANDROID_get_native_client_buffer
249 EGLClientBuffer
fGetNativeClientBufferANDROID(
250 const struct AHardwareBuffer
* buffer
) {
251 WRAP(fGetNativeClientBufferANDROID(buffer
));
255 EGLBoolean
fTerminate(EGLDisplay display
) const { WRAP(fTerminate(display
)); }
259 mutable Mutex mMutex
= Mutex
{"GLLibraryEGL::mMutex"};
260 mutable std::unordered_map
<EGLContext
, PlatformThreadId
>
261 mOwningThreadByContext
MOZ_GUARDED_BY(mMutex
);
263 EGLBoolean
fMakeCurrent(EGLDisplay dpy
, EGLSurface draw
, EGLSurface read
,
264 EGLContext ctx
) const {
265 const bool CHECK_CONTEXT_OWNERSHIP
= true;
266 if (CHECK_CONTEXT_OWNERSHIP
) {
267 const MutexAutoLock
lock(mMutex
);
268 const auto tid
= PlatformThread::CurrentId();
269 const auto prevCtx
= fGetCurrentContext();
272 mOwningThreadByContext
[prevCtx
] = 0;
275 auto& ctxOwnerThread
= mOwningThreadByContext
[ctx
];
276 if (ctxOwnerThread
&& ctxOwnerThread
!= tid
) {
278 << "EGLContext#" << ctx
<< " is owned by/Current on"
279 << " thread#" << ctxOwnerThread
<< " but MakeCurrent requested on"
280 << " thread#" << tid
<< "!";
281 if (gfxEnv::MOZ_EGL_RELEASE_ASSERT_CONTEXT_OWNERSHIP()) {
282 MOZ_CRASH("MOZ_EGL_RELEASE_ASSERT_CONTEXT_OWNERSHIP");
286 ctxOwnerThread
= tid
;
290 // Always reset the TLS current context.
291 // If we're called by TLS-caching MakeCurrent, after we return true,
292 // the caller will set the TLS correctly anyway.
293 GLContext::ResetTLSCurrentContext();
295 WRAP(fMakeCurrent(dpy
, draw
, read
, ctx
));
300 EGLBoolean
fDestroyContext(EGLDisplay dpy
, EGLContext ctx
) const {
302 const MutexAutoLock
lock(mMutex
);
303 mOwningThreadByContext
.erase(ctx
);
306 WRAP(fDestroyContext(dpy
, ctx
));
309 EGLContext
fCreateContext(EGLDisplay dpy
, EGLConfig config
,
310 EGLContext share_context
,
311 const EGLint
* attrib_list
) const {
312 WRAP(fCreateContext(dpy
, config
, share_context
, attrib_list
));
315 EGLBoolean
fDestroySurface(EGLDisplay dpy
, EGLSurface surface
) const {
316 WRAP(fDestroySurface(dpy
, surface
));
320 EGLSurface
fCreateWindowSurface(EGLDisplay dpy
, EGLConfig config
,
321 EGLNativeWindowType win
,
322 const EGLint
* attrib_list
) const {
323 WRAP(fCreateWindowSurface(dpy
, config
, win
, attrib_list
));
327 EGLSurface
fCreatePbufferSurface(EGLDisplay dpy
, EGLConfig config
,
328 const EGLint
* attrib_list
) const {
329 WRAP(fCreatePbufferSurface(dpy
, config
, attrib_list
));
332 EGLSurface
fCreatePbufferFromClientBuffer(EGLDisplay dpy
, EGLenum buftype
,
333 EGLClientBuffer buffer
,
335 const EGLint
* attrib_list
) const {
336 WRAP(fCreatePbufferFromClientBuffer(dpy
, buftype
, buffer
, config
,
340 EGLSurface
fCreatePixmapSurface(EGLDisplay dpy
, EGLConfig config
,
341 EGLNativePixmapType pixmap
,
342 const EGLint
* attrib_list
) const {
343 WRAP(fCreatePixmapSurface(dpy
, config
, pixmap
, attrib_list
));
346 EGLBoolean
fInitialize(EGLDisplay dpy
, EGLint
* major
, EGLint
* minor
) const {
347 WRAP(fInitialize(dpy
, major
, minor
));
350 EGLBoolean
fChooseConfig(EGLDisplay dpy
, const EGLint
* attrib_list
,
351 EGLConfig
* configs
, EGLint config_size
,
352 EGLint
* num_config
) const {
353 WRAP(fChooseConfig(dpy
, attrib_list
, configs
, config_size
, num_config
));
356 EGLBoolean
fGetConfigAttrib(EGLDisplay dpy
, EGLConfig config
,
357 EGLint attribute
, EGLint
* value
) const {
358 WRAP(fGetConfigAttrib(dpy
, config
, attribute
, value
));
361 EGLBoolean
fGetConfigs(EGLDisplay dpy
, EGLConfig
* configs
, EGLint config_size
,
362 EGLint
* num_config
) const {
363 WRAP(fGetConfigs(dpy
, configs
, config_size
, num_config
));
366 EGLBoolean
fSwapBuffers(EGLDisplay dpy
, EGLSurface surface
) const {
367 WRAP(fSwapBuffers(dpy
, surface
));
370 EGLBoolean
fCopyBuffers(EGLDisplay dpy
, EGLSurface surface
,
371 EGLNativePixmapType target
) const {
372 WRAP(fCopyBuffers(dpy
, surface
, target
));
376 const GLubyte
* fQueryString(EGLDisplay dpy
, EGLint name
) const {
377 WRAP(fQueryString(dpy
, name
));
381 EGLBoolean
fQueryContext(EGLDisplay dpy
, EGLContext ctx
, EGLint attribute
,
382 EGLint
* value
) const {
383 WRAP(fQueryContext(dpy
, ctx
, attribute
, value
));
386 EGLBoolean
fBindTexImage(EGLDisplay dpy
, EGLSurface surface
,
387 EGLint buffer
) const {
388 WRAP(fBindTexImage(dpy
, surface
, buffer
));
391 EGLBoolean
fReleaseTexImage(EGLDisplay dpy
, EGLSurface surface
,
392 EGLint buffer
) const {
393 WRAP(fReleaseTexImage(dpy
, surface
, buffer
));
396 EGLBoolean
fSwapInterval(EGLDisplay dpy
, EGLint interval
) const {
397 WRAP(fSwapInterval(dpy
, interval
));
400 EGLImage
fCreateImage(EGLDisplay dpy
, EGLContext ctx
, EGLenum target
,
401 EGLClientBuffer buffer
,
402 const EGLint
* attrib_list
) const {
403 WRAP(fCreateImageKHR(dpy
, ctx
, target
, buffer
, attrib_list
));
406 EGLBoolean
fDestroyImage(EGLDisplay dpy
, EGLImage image
) const {
407 WRAP(fDestroyImageKHR(dpy
, image
));
410 EGLBoolean
fQuerySurface(EGLDisplay dpy
, EGLSurface surface
, EGLint attribute
,
411 EGLint
* value
) const {
412 WRAP(fQuerySurface(dpy
, surface
, attribute
, value
));
415 EGLBoolean
fQuerySurfacePointerANGLE(EGLDisplay dpy
, EGLSurface surface
,
416 EGLint attribute
, void** value
) const {
417 WRAP(fQuerySurfacePointerANGLE(dpy
, surface
, attribute
, value
));
420 EGLSync
fCreateSync(EGLDisplay dpy
, EGLenum type
,
421 const EGLint
* attrib_list
) const {
422 WRAP(fCreateSyncKHR(dpy
, type
, attrib_list
));
425 EGLBoolean
fDestroySync(EGLDisplay dpy
, EGLSync sync
) const {
426 WRAP(fDestroySyncKHR(dpy
, sync
));
429 EGLint
fClientWaitSync(EGLDisplay dpy
, EGLSync sync
, EGLint flags
,
430 EGLTime timeout
) const {
431 WRAP(fClientWaitSyncKHR(dpy
, sync
, flags
, timeout
));
434 EGLBoolean
fGetSyncAttrib(EGLDisplay dpy
, EGLSync sync
, EGLint attribute
,
435 EGLint
* value
) const {
436 WRAP(fGetSyncAttribKHR(dpy
, sync
, attribute
, value
));
439 EGLint
fWaitSync(EGLDisplay dpy
, EGLSync sync
, EGLint flags
) const {
440 WRAP(fWaitSyncKHR(dpy
, sync
, flags
));
443 EGLint
fDupNativeFenceFDANDROID(EGLDisplay dpy
, EGLSync sync
) const {
444 WRAP(fDupNativeFenceFDANDROID(dpy
, sync
));
448 EGLStreamKHR
fCreateStreamKHR(EGLDisplay dpy
,
449 const EGLint
* attrib_list
) const {
450 WRAP(fCreateStreamKHR(dpy
, attrib_list
));
453 EGLBoolean
fDestroyStreamKHR(EGLDisplay dpy
, EGLStreamKHR stream
) const {
454 WRAP(fDestroyStreamKHR(dpy
, stream
));
457 EGLBoolean
fQueryStreamKHR(EGLDisplay dpy
, EGLStreamKHR stream
,
458 EGLenum attribute
, EGLint
* value
) const {
459 WRAP(fQueryStreamKHR(dpy
, stream
, attribute
, value
));
462 // KHR_stream_consumer_gltexture
463 EGLBoolean
fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy
,
464 EGLStreamKHR stream
) const {
465 WRAP(fStreamConsumerGLTextureExternalKHR(dpy
, stream
));
468 EGLBoolean
fStreamConsumerAcquireKHR(EGLDisplay dpy
,
469 EGLStreamKHR stream
) const {
470 WRAP(fStreamConsumerAcquireKHR(dpy
, stream
));
473 EGLBoolean
fStreamConsumerReleaseKHR(EGLDisplay dpy
,
474 EGLStreamKHR stream
) const {
475 WRAP(fStreamConsumerReleaseKHR(dpy
, stream
));
479 EGLBoolean
fQueryDisplayAttribEXT(EGLDisplay dpy
, EGLint attribute
,
480 EGLAttrib
* value
) const {
481 WRAP(fQueryDisplayAttribEXT(dpy
, attribute
, value
));
485 EGLBoolean
fQueryDeviceAttribEXT(EGLDeviceEXT device
, EGLint attribute
,
486 EGLAttrib
* value
) const {
487 WRAP(fQueryDeviceAttribEXT(device
, attribute
, value
));
490 const char* fQueryDeviceStringEXT(EGLDeviceEXT device
, EGLint name
) {
491 WRAP(fQueryDeviceStringEXT(device
, name
));
495 // NV_stream_consumer_gltexture_yuv
496 EGLBoolean
fStreamConsumerGLTextureExternalAttribsNV(
497 EGLDisplay dpy
, EGLStreamKHR stream
, const EGLAttrib
* attrib_list
) const {
498 WRAP(fStreamConsumerGLTextureExternalAttribsNV(dpy
, stream
, attrib_list
));
501 // ANGLE_stream_producer_d3d_texture
502 EGLBoolean
fCreateStreamProducerD3DTextureANGLE(
503 EGLDisplay dpy
, EGLStreamKHR stream
, const EGLAttrib
* attrib_list
) const {
504 WRAP(fCreateStreamProducerD3DTextureANGLE(dpy
, stream
, attrib_list
));
507 EGLBoolean
fStreamPostD3DTextureANGLE(EGLDisplay dpy
, EGLStreamKHR stream
,
509 const EGLAttrib
* attrib_list
) const {
510 WRAP(fStreamPostD3DTextureANGLE(dpy
, stream
, texture
, attrib_list
));
513 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
514 EGLBoolean
fSwapBuffersWithDamage(EGLDisplay dpy
, EGLSurface surface
,
515 const EGLint
* rects
, EGLint n_rects
) {
516 WRAP(fSwapBuffersWithDamage(dpy
, surface
, rects
, n_rects
));
519 // EGL_KHR_partial_update
520 EGLBoolean
fSetDamageRegion(EGLDisplay dpy
, EGLSurface surface
,
521 const EGLint
* rects
, EGLint n_rects
) {
522 WRAP(fSetDamageRegion(dpy
, surface
, rects
, n_rects
));
524 // EGL_MESA_image_dma_buf_export
525 EGLBoolean
fExportDMABUFImageQuery(EGLDisplay dpy
, EGLImage image
,
526 int* fourcc
, int* num_planes
,
527 uint64_t* modifiers
) {
529 fExportDMABUFImageQueryMESA(dpy
, image
, fourcc
, num_planes
, modifiers
));
531 EGLBoolean
fExportDMABUFImage(EGLDisplay dpy
, EGLImage image
, int* fds
,
532 EGLint
* strides
, EGLint
* offsets
) {
533 WRAP(fExportDMABUFImageMESA(dpy
, image
, fds
, strides
, offsets
));
537 // EGL_EXT_device_enumeration
538 EGLBoolean
fQueryDevicesEXT(EGLint max_devices
, EGLDeviceEXT
* devices
,
539 EGLint
* num_devices
) {
540 WRAP(fQueryDevicesEXT(max_devices
, devices
, num_devices
));
549 #undef MOZ_FUNCTION_NAME
555 EGLCastToRelevantPtr(GLAPIENTRY
* fGetProcAddress
)(const char* procname
);
556 EGLDisplay(GLAPIENTRY
* fGetDisplay
)(void* display_id
);
557 EGLDisplay(GLAPIENTRY
* fGetPlatformDisplay
)(EGLenum platform
,
558 void* native_display
,
559 const EGLAttrib
* attrib_list
);
560 EGLBoolean(GLAPIENTRY
* fTerminate
)(EGLDisplay dpy
);
561 EGLSurface(GLAPIENTRY
* fGetCurrentSurface
)(EGLint
);
562 EGLContext(GLAPIENTRY
* fGetCurrentContext
)(void);
563 EGLBoolean(GLAPIENTRY
* fMakeCurrent
)(EGLDisplay dpy
, EGLSurface draw
,
564 EGLSurface read
, EGLContext ctx
);
565 EGLBoolean(GLAPIENTRY
* fDestroyContext
)(EGLDisplay dpy
, EGLContext ctx
);
566 EGLContext(GLAPIENTRY
* fCreateContext
)(EGLDisplay dpy
, EGLConfig config
,
567 EGLContext share_context
,
568 const EGLint
* attrib_list
);
569 EGLBoolean(GLAPIENTRY
* fDestroySurface
)(EGLDisplay dpy
, EGLSurface surface
);
570 EGLSurface(GLAPIENTRY
* fCreateWindowSurface
)(EGLDisplay dpy
,
572 EGLNativeWindowType win
,
573 const EGLint
* attrib_list
);
574 EGLSurface(GLAPIENTRY
* fCreatePbufferSurface
)(EGLDisplay dpy
,
576 const EGLint
* attrib_list
);
577 EGLSurface(GLAPIENTRY
* fCreatePbufferFromClientBuffer
)(
578 EGLDisplay dpy
, EGLenum buftype
, EGLClientBuffer buffer
,
579 EGLConfig config
, const EGLint
* attrib_list
);
580 EGLSurface(GLAPIENTRY
* fCreatePixmapSurface
)(EGLDisplay dpy
,
582 EGLNativePixmapType pixmap
,
583 const EGLint
* attrib_list
);
584 EGLBoolean(GLAPIENTRY
* fBindAPI
)(EGLenum api
);
585 EGLBoolean(GLAPIENTRY
* fInitialize
)(EGLDisplay dpy
, EGLint
* major
,
587 EGLBoolean(GLAPIENTRY
* fChooseConfig
)(EGLDisplay dpy
,
588 const EGLint
* attrib_list
,
592 EGLint(GLAPIENTRY
* fGetError
)(void);
593 EGLBoolean(GLAPIENTRY
* fGetConfigAttrib
)(EGLDisplay dpy
, EGLConfig config
,
594 EGLint attribute
, EGLint
* value
);
595 EGLBoolean(GLAPIENTRY
* fGetConfigs
)(EGLDisplay dpy
, EGLConfig
* configs
,
596 EGLint config_size
, EGLint
* num_config
);
597 EGLBoolean(GLAPIENTRY
* fWaitNative
)(EGLint engine
);
598 EGLBoolean(GLAPIENTRY
* fSwapBuffers
)(EGLDisplay dpy
, EGLSurface surface
);
599 EGLBoolean(GLAPIENTRY
* fCopyBuffers
)(EGLDisplay dpy
, EGLSurface surface
,
600 EGLNativePixmapType target
);
601 const GLubyte
*(GLAPIENTRY
* fQueryString
)(EGLDisplay
, EGLint name
);
602 EGLBoolean(GLAPIENTRY
* fQueryContext
)(EGLDisplay dpy
, EGLContext ctx
,
603 EGLint attribute
, EGLint
* value
);
604 EGLBoolean(GLAPIENTRY
* fBindTexImage
)(EGLDisplay
, EGLSurface surface
,
606 EGLBoolean(GLAPIENTRY
* fReleaseTexImage
)(EGLDisplay
, EGLSurface surface
,
608 EGLBoolean(GLAPIENTRY
* fSwapInterval
)(EGLDisplay dpy
, EGLint interval
);
609 EGLImage(GLAPIENTRY
* fCreateImageKHR
)(EGLDisplay dpy
, EGLContext ctx
,
611 EGLClientBuffer buffer
,
612 const EGLint
* attrib_list
);
613 EGLBoolean(GLAPIENTRY
* fDestroyImageKHR
)(EGLDisplay dpy
, EGLImage image
);
614 EGLBoolean(GLAPIENTRY
* fQuerySurface
)(EGLDisplay dpy
, EGLSurface surface
,
615 EGLint attribute
, EGLint
* value
);
616 EGLBoolean(GLAPIENTRY
* fQuerySurfacePointerANGLE
)(EGLDisplay dpy
,
620 EGLSync(GLAPIENTRY
* fCreateSyncKHR
)(EGLDisplay dpy
, EGLenum type
,
621 const EGLint
* attrib_list
);
622 EGLBoolean(GLAPIENTRY
* fDestroySyncKHR
)(EGLDisplay dpy
, EGLSync sync
);
623 EGLint(GLAPIENTRY
* fClientWaitSyncKHR
)(EGLDisplay dpy
, EGLSync sync
,
624 EGLint flags
, EGLTime timeout
);
625 EGLBoolean(GLAPIENTRY
* fGetSyncAttribKHR
)(EGLDisplay dpy
, EGLSync sync
,
626 EGLint attribute
, EGLint
* value
);
627 EGLint(GLAPIENTRY
* fWaitSyncKHR
)(EGLDisplay dpy
, EGLSync sync
,
629 EGLint(GLAPIENTRY
* fDupNativeFenceFDANDROID
)(EGLDisplay dpy
, EGLSync sync
);
631 EGLStreamKHR(GLAPIENTRY
* fCreateStreamKHR
)(EGLDisplay dpy
,
632 const EGLint
* attrib_list
);
633 EGLBoolean(GLAPIENTRY
* fDestroyStreamKHR
)(EGLDisplay dpy
,
634 EGLStreamKHR stream
);
635 EGLBoolean(GLAPIENTRY
* fQueryStreamKHR
)(EGLDisplay dpy
, EGLStreamKHR stream
,
636 EGLenum attribute
, EGLint
* value
);
637 // KHR_stream_consumer_gltexture
638 EGLBoolean(GLAPIENTRY
* fStreamConsumerGLTextureExternalKHR
)(
639 EGLDisplay dpy
, EGLStreamKHR stream
);
640 EGLBoolean(GLAPIENTRY
* fStreamConsumerAcquireKHR
)(EGLDisplay dpy
,
641 EGLStreamKHR stream
);
642 EGLBoolean(GLAPIENTRY
* fStreamConsumerReleaseKHR
)(EGLDisplay dpy
,
643 EGLStreamKHR stream
);
645 EGLBoolean(GLAPIENTRY
* fQueryDisplayAttribEXT
)(EGLDisplay dpy
,
648 EGLBoolean(GLAPIENTRY
* fQueryDeviceAttribEXT
)(EGLDeviceEXT device
,
651 const char*(GLAPIENTRY
* fQueryDeviceStringEXT
)(EGLDeviceEXT device
,
654 // NV_stream_consumer_gltexture_yuv
655 EGLBoolean(GLAPIENTRY
* fStreamConsumerGLTextureExternalAttribsNV
)(
656 EGLDisplay dpy
, EGLStreamKHR stream
, const EGLAttrib
* attrib_list
);
657 // ANGLE_stream_producer_d3d_texture
658 EGLBoolean(GLAPIENTRY
* fCreateStreamProducerD3DTextureANGLE
)(
659 EGLDisplay dpy
, EGLStreamKHR stream
, const EGLAttrib
* attrib_list
);
660 EGLBoolean(GLAPIENTRY
* fStreamPostD3DTextureANGLE
)(
661 EGLDisplay dpy
, EGLStreamKHR stream
, void* texture
,
662 const EGLAttrib
* attrib_list
);
663 // ANGLE_device_creation
664 EGLDeviceEXT(GLAPIENTRY
* fCreateDeviceANGLE
)(EGLint device_type
,
666 const EGLAttrib
* attrib_list
);
667 EGLBoolean(GLAPIENTRY
* fReleaseDeviceANGLE
)(EGLDeviceEXT device
);
668 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
669 EGLBoolean(GLAPIENTRY
* fSwapBuffersWithDamage
)(EGLDisplay dpy
,
673 // EGL_KHR_partial_update
674 EGLBoolean(GLAPIENTRY
* fSetDamageRegion
)(EGLDisplay dpy
, EGLSurface surface
,
677 EGLClientBuffer(GLAPIENTRY
* fGetNativeClientBufferANDROID
)(
678 const struct AHardwareBuffer
* buffer
);
680 // EGL_MESA_image_dma_buf_export
681 EGLBoolean(GLAPIENTRY
* fExportDMABUFImageQueryMESA
)(EGLDisplay dpy
,
685 uint64_t* modifiers
);
686 EGLBoolean(GLAPIENTRY
* fExportDMABUFImageMESA
)(EGLDisplay dpy
,
687 EGLImage image
, int* fds
,
691 EGLBoolean(GLAPIENTRY
* fQueryDevicesEXT
)(EGLint max_devices
,
692 EGLDeviceEXT
* devices
,
693 EGLint
* num_devices
);
698 static bool ShouldLeakEglDisplay() {
699 // We are seeing crashes in eglTerminate on the Samsung S22 family of devices
700 // running Android 14, so we leak the EGLDisplay rather than call
702 #ifdef MOZ_WIDGET_ANDROID
703 if (jni::GetAPIVersion() >= 34) {
704 const auto board
= java::sdk::Build::BOARD()->ToString();
705 if (board
.EqualsASCII("s5e9925")) {
713 class EglDisplay final
{
715 const RefPtr
<GLLibraryEGL
> mLib
;
716 const EGLDisplay mDisplay
;
720 std::bitset
<UnderlyingValue(EGLExtension::Max
)> mAvailableExtensions
;
722 struct PrivateUseOnly final
{};
725 static std::shared_ptr
<EglDisplay
> Create(
726 GLLibraryEGL
&, EGLDisplay
, bool isWarp
,
727 const StaticMutexAutoLock
& aProofOfLock
);
729 // Only `public` for make_shared.
730 EglDisplay(const PrivateUseOnly
&, GLLibraryEGL
&, EGLDisplay
, bool isWarp
);
735 bool IsExtensionSupported(EGLExtension aKnownExtension
) const {
736 return mAvailableExtensions
[UnderlyingValue(aKnownExtension
)];
739 void MarkExtensionUnsupported(EGLExtension aKnownExtension
) {
740 mAvailableExtensions
[UnderlyingValue(aKnownExtension
)] = false;
743 void DumpEGLConfig(EGLConfig
) const;
744 void DumpEGLConfigs() const;
750 bool HasKHRImageBase() const {
751 return IsExtensionSupported(EGLExtension::KHR_image
) ||
752 IsExtensionSupported(EGLExtension::KHR_image_base
);
755 bool HasKHRImagePixmap() const {
756 return IsExtensionSupported(EGLExtension::KHR_image
) ||
757 IsExtensionSupported(EGLExtension::KHR_image_pixmap
);
762 EGLBoolean
fTerminate() {
763 static const bool shouldLeak
= ShouldLeakEglDisplay();
765 return LOCAL_EGL_TRUE
;
767 return mLib
->fTerminate(mDisplay
);
770 EGLBoolean
fMakeCurrent(EGLSurface draw
, EGLSurface read
,
771 EGLContext ctx
) const {
772 return mLib
->fMakeCurrent(mDisplay
, draw
, read
, ctx
);
775 EGLBoolean
fDestroyContext(EGLContext ctx
) const {
776 return mLib
->fDestroyContext(mDisplay
, ctx
);
779 EGLContext
fCreateContext(EGLConfig config
, EGLContext share_context
,
780 const EGLint
* attrib_list
) const {
781 return mLib
->fCreateContext(mDisplay
, config
, share_context
, attrib_list
);
784 EGLBoolean
fDestroySurface(EGLSurface surface
) const {
785 return mLib
->fDestroySurface(mDisplay
, surface
);
788 EGLSurface
fCreateWindowSurface(EGLConfig config
, EGLNativeWindowType win
,
789 const EGLint
* attrib_list
) const {
790 return mLib
->fCreateWindowSurface(mDisplay
, config
, win
, attrib_list
);
793 EGLSurface
fCreatePbufferSurface(EGLConfig config
,
794 const EGLint
* attrib_list
) const {
795 return mLib
->fCreatePbufferSurface(mDisplay
, config
, attrib_list
);
798 EGLSurface
fCreatePbufferFromClientBuffer(EGLenum buftype
,
799 EGLClientBuffer buffer
,
801 const EGLint
* attrib_list
) const {
802 return mLib
->fCreatePbufferFromClientBuffer(mDisplay
, buftype
, buffer
,
803 config
, attrib_list
);
806 EGLBoolean
fChooseConfig(const EGLint
* attrib_list
, EGLConfig
* configs
,
807 EGLint config_size
, EGLint
* num_config
) const {
808 return mLib
->fChooseConfig(mDisplay
, attrib_list
, configs
, config_size
,
812 EGLBoolean
fGetConfigAttrib(EGLConfig config
, EGLint attribute
,
813 EGLint
* value
) const {
814 return mLib
->fGetConfigAttrib(mDisplay
, config
, attribute
, value
);
817 EGLBoolean
fGetConfigs(EGLConfig
* configs
, EGLint config_size
,
818 EGLint
* num_config
) const {
819 return mLib
->fGetConfigs(mDisplay
, configs
, config_size
, num_config
);
822 EGLBoolean
fSwapBuffers(EGLSurface surface
) const {
823 return mLib
->fSwapBuffers(mDisplay
, surface
);
826 EGLBoolean
fBindTexImage(EGLSurface surface
, EGLint buffer
) const {
827 return mLib
->fBindTexImage(mDisplay
, surface
, buffer
);
830 EGLBoolean
fReleaseTexImage(EGLSurface surface
, EGLint buffer
) const {
831 return mLib
->fReleaseTexImage(mDisplay
, surface
, buffer
);
834 EGLBoolean
fSwapInterval(EGLint interval
) const {
835 return mLib
->fSwapInterval(mDisplay
, interval
);
838 EGLImage
fCreateImage(EGLContext ctx
, EGLenum target
, EGLClientBuffer buffer
,
839 const EGLint
* attribList
) const {
840 MOZ_ASSERT(HasKHRImageBase());
841 return mLib
->fCreateImage(mDisplay
, ctx
, target
, buffer
, attribList
);
844 EGLBoolean
fDestroyImage(EGLImage image
) const {
845 MOZ_ASSERT(HasKHRImageBase());
846 return mLib
->fDestroyImage(mDisplay
, image
);
849 EGLBoolean
fQuerySurface(EGLSurface surface
, EGLint attribute
,
850 EGLint
* value
) const {
851 return mLib
->fQuerySurface(mDisplay
, surface
, attribute
, value
);
854 EGLBoolean
fQuerySurfacePointerANGLE(EGLSurface surface
, EGLint attribute
,
855 void** value
) const {
856 MOZ_ASSERT(IsExtensionSupported(
857 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle
));
858 return mLib
->fQuerySurfacePointerANGLE(mDisplay
, surface
, attribute
, value
);
861 EGLSync
fCreateSync(EGLenum type
, const EGLint
* attrib_list
) const {
862 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync
));
863 return mLib
->fCreateSync(mDisplay
, type
, attrib_list
);
866 EGLBoolean
fDestroySync(EGLSync sync
) const {
867 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync
));
868 return mLib
->fDestroySync(mDisplay
, sync
);
871 EGLint
fClientWaitSync(EGLSync sync
, EGLint flags
, EGLTime timeout
) const {
872 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync
));
873 return mLib
->fClientWaitSync(mDisplay
, sync
, flags
, timeout
);
876 EGLBoolean
fGetSyncAttrib(EGLSync sync
, EGLint attribute
,
877 EGLint
* value
) const {
878 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync
));
879 return mLib
->fGetSyncAttrib(mDisplay
, sync
, attribute
, value
);
882 EGLint
fWaitSync(EGLSync sync
, EGLint flags
) const {
883 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_wait_sync
));
884 return mLib
->fWaitSync(mDisplay
, sync
, flags
);
887 EGLint
fDupNativeFenceFDANDROID(EGLSync sync
) const {
888 MOZ_ASSERT(IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync
));
889 return mLib
->fDupNativeFenceFDANDROID(mDisplay
, sync
);
893 EGLBoolean
fQueryDisplayAttribEXT(EGLint attribute
, EGLAttrib
* value
) const {
894 MOZ_ASSERT(mLib
->IsExtensionSupported(EGLLibExtension::EXT_device_query
));
895 return mLib
->fQueryDisplayAttribEXT(mDisplay
, attribute
, value
);
899 EGLStreamKHR
fCreateStreamKHR(const EGLint
* attrib_list
) const {
900 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream
));
901 return mLib
->fCreateStreamKHR(mDisplay
, attrib_list
);
904 EGLBoolean
fDestroyStreamKHR(EGLStreamKHR stream
) const {
905 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream
));
906 return mLib
->fDestroyStreamKHR(mDisplay
, stream
);
909 EGLBoolean
fQueryStreamKHR(EGLStreamKHR stream
, EGLenum attribute
,
910 EGLint
* value
) const {
911 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream
));
912 return mLib
->fQueryStreamKHR(mDisplay
, stream
, attribute
, value
);
915 // KHR_stream_consumer_gltexture
916 EGLBoolean
fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream
) const {
918 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture
));
919 return mLib
->fStreamConsumerGLTextureExternalKHR(mDisplay
, stream
);
922 EGLBoolean
fStreamConsumerAcquireKHR(EGLStreamKHR stream
) const {
924 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture
));
925 return mLib
->fStreamConsumerAcquireKHR(mDisplay
, stream
);
928 EGLBoolean
fStreamConsumerReleaseKHR(EGLStreamKHR stream
) const {
930 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture
));
931 return mLib
->fStreamConsumerReleaseKHR(mDisplay
, stream
);
934 // NV_stream_consumer_gltexture_yuv
935 EGLBoolean
fStreamConsumerGLTextureExternalAttribsNV(
936 EGLStreamKHR stream
, const EGLAttrib
* attrib_list
) const {
938 IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv
));
939 return mLib
->fStreamConsumerGLTextureExternalAttribsNV(mDisplay
, stream
,
943 // ANGLE_stream_producer_d3d_texture
944 EGLBoolean
fCreateStreamProducerD3DTextureANGLE(
945 EGLStreamKHR stream
, const EGLAttrib
* attrib_list
) const {
947 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture
));
948 return mLib
->fCreateStreamProducerD3DTextureANGLE(mDisplay
, stream
,
952 EGLBoolean
fStreamPostD3DTextureANGLE(EGLStreamKHR stream
, void* texture
,
953 const EGLAttrib
* attrib_list
) const {
955 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture
));
956 return mLib
->fStreamPostD3DTextureANGLE(mDisplay
, stream
, texture
,
960 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
961 EGLBoolean
fSwapBuffersWithDamage(EGLSurface surface
, const EGLint
* rects
,
964 IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage
) ||
965 IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage
));
966 return mLib
->fSwapBuffersWithDamage(mDisplay
, surface
, rects
, n_rects
);
969 // EGL_KHR_partial_update
970 EGLBoolean
fSetDamageRegion(EGLSurface surface
, const EGLint
* rects
,
972 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update
));
973 return mLib
->fSetDamageRegion(mDisplay
, surface
, rects
, n_rects
);
976 EGLBoolean
fExportDMABUFImageQuery(EGLImage image
, int* fourcc
,
978 uint64_t* modifiers
) const {
979 MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export
));
980 return mLib
->fExportDMABUFImageQuery(mDisplay
, image
, fourcc
, num_planes
,
983 EGLBoolean
fExportDMABUFImage(EGLImage image
, int* fds
, EGLint
* strides
,
984 EGLint
* offsets
) const {
985 MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export
));
986 return mLib
->fExportDMABUFImage(mDisplay
, image
, fds
, strides
, offsets
);
991 } /* namespace mozilla */
993 #endif /* GLLIBRARYEGL_H_ */