Bug 1874684 - Part 28: Return DateDuration from DifferenceISODateTime. r=mgaudet
[gecko.git] / gfx / gl / GLLibraryEGL.h
blobde296508bbb020c938ab03c3fa1049bb5052ff72
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_
8 #if defined(MOZ_X11)
9 # include "mozilla/X11Util.h"
10 #endif
12 #include "base/platform_thread.h" // for PlatformThreadId
13 #include "gfxEnv.h"
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"
23 #include "prlink.h"
25 #include <bitset>
26 #include <memory>
27 #include <unordered_map>
29 #ifdef MOZ_WIDGET_ANDROID
30 # include "mozilla/ProfilerLabels.h"
31 # include "AndroidBuild.h"
32 #endif
34 #if defined(MOZ_X11)
35 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
36 #else
37 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0)
38 #endif
40 struct ID3D11Device;
42 extern "C" {
43 struct AHardwareBuffer;
46 namespace angle {
47 class Platform;
50 namespace mozilla {
52 namespace gfx {
53 class DataSourceSurface;
56 namespace gl {
58 class SymbolLoader;
60 PRLibrary* LoadApitraceLibrary();
62 void BeforeEGLCall(const char* funcName);
63 void AfterEGLCall(const char* funcName);
65 class EglDisplay;
66 /**
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,
77 ANGLE_platform_angle,
78 ANGLE_platform_angle_d3d,
79 EXT_device_enumeration,
80 EXT_device_query,
81 EXT_platform_device,
82 MESA_platform_surfaceless,
83 Max
86 /**
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 {
94 KHR_image_base,
95 KHR_image_pixmap,
96 KHR_gl_texture_2D_image,
97 ANGLE_surface_d3d_texture_2d_share_handle,
98 EXT_create_context_robustness,
99 KHR_image,
100 KHR_fence_sync,
101 KHR_wait_sync,
102 ANDROID_native_fence_sync,
103 EGL_ANDROID_image_crop,
104 ANGLE_d3d_share_handle_client_buffer,
105 KHR_create_context,
106 KHR_stream,
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,
115 EXT_buffer_age,
116 KHR_partial_update,
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,
125 // -
127 class GLLibraryEGL final {
128 friend class EglDisplay;
130 public:
131 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL)
133 private:
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;
141 public:
142 static RefPtr<GLLibraryEGL> Get(nsACString* const out_failureId);
143 static void Shutdown();
145 private:
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);
158 public:
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; }
176 // -
177 // PFN wrappers
179 #ifdef MOZ_WIDGET_ANDROID
180 # define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS);
181 #else
182 # define PROFILE_CALL
183 #endif
185 #ifndef MOZ_FUNCTION_NAME
186 # ifdef __GNUC__
187 # define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__
188 # elif defined(_MSC_VER)
189 # define MOZ_FUNCTION_NAME __FUNCTION__
190 # else
191 # define MOZ_FUNCTION_NAME \
192 __func__ // defined in C99, supported in various C++ compilers. Just raw
193 // function name.
194 # endif
195 #endif
197 #ifdef DEBUG
198 # define BEFORE_CALL BeforeEGLCall(MOZ_FUNCTION_NAME);
199 # define AFTER_CALL AfterEGLCall(MOZ_FUNCTION_NAME);
200 #else
201 # define BEFORE_CALL
202 # define AFTER_CALL
203 #endif
205 #define WRAP(X) \
206 PROFILE_CALL \
207 BEFORE_CALL \
208 const auto ret = mSymbols.X; \
209 AFTER_CALL \
210 return ret
212 public:
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));
254 private:
255 EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); }
257 // -
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();
271 if (prevCtx) {
272 mOwningThreadByContext[prevCtx] = 0;
274 if (ctx) {
275 auto& ctxOwnerThread = mOwningThreadByContext[ctx];
276 if (ctxOwnerThread && ctxOwnerThread != tid) {
277 gfxCriticalError()
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");
284 return false;
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));
298 // -
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));
319 public:
320 EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
321 EGLNativeWindowType win,
322 const EGLint* attrib_list) const {
323 WRAP(fCreateWindowSurface(dpy, config, win, attrib_list));
326 private:
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,
334 EGLConfig config,
335 const EGLint* attrib_list) const {
336 WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config,
337 attrib_list));
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));
375 public:
376 const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const {
377 WRAP(fQueryString(dpy, name));
380 private:
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));
447 // KHR_stream
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));
478 // EXT_device_query
479 EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute,
480 EGLAttrib* value) const {
481 WRAP(fQueryDisplayAttribEXT(dpy, attribute, value));
484 public:
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));
494 private:
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,
508 void* texture,
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) {
528 WRAP(
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));
536 public:
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));
543 #undef WRAP
545 #undef WRAP
546 #undef PROFILE_CALL
547 #undef BEFORE_CALL
548 #undef AFTER_CALL
549 #undef MOZ_FUNCTION_NAME
551 ////
553 private:
554 struct {
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,
571 EGLConfig config,
572 EGLNativeWindowType win,
573 const EGLint* attrib_list);
574 EGLSurface(GLAPIENTRY* fCreatePbufferSurface)(EGLDisplay dpy,
575 EGLConfig config,
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,
581 EGLConfig config,
582 EGLNativePixmapType pixmap,
583 const EGLint* attrib_list);
584 EGLBoolean(GLAPIENTRY* fBindAPI)(EGLenum api);
585 EGLBoolean(GLAPIENTRY* fInitialize)(EGLDisplay dpy, EGLint* major,
586 EGLint* minor);
587 EGLBoolean(GLAPIENTRY* fChooseConfig)(EGLDisplay dpy,
588 const EGLint* attrib_list,
589 EGLConfig* configs,
590 EGLint config_size,
591 EGLint* num_config);
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,
605 EGLint buffer);
606 EGLBoolean(GLAPIENTRY* fReleaseTexImage)(EGLDisplay, EGLSurface surface,
607 EGLint buffer);
608 EGLBoolean(GLAPIENTRY* fSwapInterval)(EGLDisplay dpy, EGLint interval);
609 EGLImage(GLAPIENTRY* fCreateImageKHR)(EGLDisplay dpy, EGLContext ctx,
610 EGLenum target,
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,
617 EGLSurface surface,
618 EGLint attribute,
619 void** value);
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,
628 EGLint flags);
629 EGLint(GLAPIENTRY* fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
630 // KHR_stream
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);
644 // EXT_device_query
645 EGLBoolean(GLAPIENTRY* fQueryDisplayAttribEXT)(EGLDisplay dpy,
646 EGLint attribute,
647 EGLAttrib* value);
648 EGLBoolean(GLAPIENTRY* fQueryDeviceAttribEXT)(EGLDeviceEXT device,
649 EGLint attribute,
650 EGLAttrib* value);
651 const char*(GLAPIENTRY* fQueryDeviceStringEXT)(EGLDeviceEXT device,
652 EGLint name);
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,
665 void* native_device,
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,
670 EGLSurface surface,
671 const EGLint* rects,
672 EGLint n_rects);
673 // EGL_KHR_partial_update
674 EGLBoolean(GLAPIENTRY* fSetDamageRegion)(EGLDisplay dpy, EGLSurface surface,
675 const EGLint* rects,
676 EGLint n_rects);
677 EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)(
678 const struct AHardwareBuffer* buffer);
680 // EGL_MESA_image_dma_buf_export
681 EGLBoolean(GLAPIENTRY* fExportDMABUFImageQueryMESA)(EGLDisplay dpy,
682 EGLImage image,
683 int* fourcc,
684 int* num_planes,
685 uint64_t* modifiers);
686 EGLBoolean(GLAPIENTRY* fExportDMABUFImageMESA)(EGLDisplay dpy,
687 EGLImage image, int* fds,
688 EGLint* strides,
689 EGLint* offsets);
691 EGLBoolean(GLAPIENTRY* fQueryDevicesEXT)(EGLint max_devices,
692 EGLDeviceEXT* devices,
693 EGLint* num_devices);
695 } mSymbols = {};
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
701 // eglTerminate.
702 #ifdef MOZ_WIDGET_ANDROID
703 if (jni::GetAPIVersion() >= 34) {
704 const auto board = java::sdk::Build::BOARD()->ToString();
705 if (board.EqualsASCII("s5e9925")) {
706 return true;
709 #endif
710 return false;
713 class EglDisplay final {
714 public:
715 const RefPtr<GLLibraryEGL> mLib;
716 const EGLDisplay mDisplay;
717 const bool mIsWARP;
719 private:
720 std::bitset<UnderlyingValue(EGLExtension::Max)> mAvailableExtensions;
722 struct PrivateUseOnly final {};
724 public:
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);
732 public:
733 ~EglDisplay();
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;
746 void Shutdown();
748 // -
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);
760 // -
762 EGLBoolean fTerminate() {
763 static const bool shouldLeak = ShouldLeakEglDisplay();
764 if (shouldLeak) {
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,
800 EGLConfig config,
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,
809 num_config);
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);
892 // EXT_device_query
893 EGLBoolean fQueryDisplayAttribEXT(EGLint attribute, EGLAttrib* value) const {
894 MOZ_ASSERT(mLib->IsExtensionSupported(EGLLibExtension::EXT_device_query));
895 return mLib->fQueryDisplayAttribEXT(mDisplay, attribute, value);
898 // KHR_stream
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 {
917 MOZ_ASSERT(
918 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
919 return mLib->fStreamConsumerGLTextureExternalKHR(mDisplay, stream);
922 EGLBoolean fStreamConsumerAcquireKHR(EGLStreamKHR stream) const {
923 MOZ_ASSERT(
924 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture));
925 return mLib->fStreamConsumerAcquireKHR(mDisplay, stream);
928 EGLBoolean fStreamConsumerReleaseKHR(EGLStreamKHR stream) const {
929 MOZ_ASSERT(
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 {
937 MOZ_ASSERT(
938 IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv));
939 return mLib->fStreamConsumerGLTextureExternalAttribsNV(mDisplay, stream,
940 attrib_list);
943 // ANGLE_stream_producer_d3d_texture
944 EGLBoolean fCreateStreamProducerD3DTextureANGLE(
945 EGLStreamKHR stream, const EGLAttrib* attrib_list) const {
946 MOZ_ASSERT(
947 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
948 return mLib->fCreateStreamProducerD3DTextureANGLE(mDisplay, stream,
949 attrib_list);
952 EGLBoolean fStreamPostD3DTextureANGLE(EGLStreamKHR stream, void* texture,
953 const EGLAttrib* attrib_list) const {
954 MOZ_ASSERT(
955 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture));
956 return mLib->fStreamPostD3DTextureANGLE(mDisplay, stream, texture,
957 attrib_list);
960 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage
961 EGLBoolean fSwapBuffersWithDamage(EGLSurface surface, const EGLint* rects,
962 EGLint n_rects) {
963 MOZ_ASSERT(
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,
971 EGLint n_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,
977 int* num_planes,
978 uint64_t* modifiers) const {
979 MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export));
980 return mLib->fExportDMABUFImageQuery(mDisplay, image, fourcc, num_planes,
981 modifiers);
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);
990 } /* namespace gl */
991 } /* namespace mozilla */
993 #endif /* GLLIBRARYEGL_H_ */