GLLibraryEGL.h (37309B)
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 "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" 24 25 #include <bitset> 26 #include <memory> 27 #include <unordered_map> 28 29 #ifdef MOZ_WIDGET_ANDROID 30 # include "mozilla/ProfilerLabels.h" 31 # include "AndroidBuild.h" 32 #endif 33 34 #if defined(MOZ_X11) 35 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay()) 36 #else 37 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) 38 #endif 39 40 struct ID3D11Device; 41 42 extern "C" { 43 struct AHardwareBuffer; 44 } 45 46 namespace angle { 47 class Platform; 48 } 49 50 namespace mozilla { 51 52 namespace gfx { 53 class DataSourceSurface; 54 } 55 56 namespace gl { 57 58 class SymbolLoader; 59 60 PRLibrary* LoadApitraceLibrary(); 61 62 void BeforeEGLCall(const char* funcName); 63 void AfterEGLCall(const char* funcName); 64 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. 72 */ 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 84 }; 85 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. 92 */ 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, 122 Max 123 }; 124 125 // - 126 127 class GLLibraryEGL final { 128 friend class EglDisplay; 129 130 public: 131 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL) 132 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; 140 141 public: 142 static RefPtr<GLLibraryEGL> Get(nsACString* const out_failureId); 143 static void Shutdown(); 144 145 private: 146 ~GLLibraryEGL() = default; 147 148 static StaticMutex sMutex; 149 static StaticRefPtr<GLLibraryEGL> sInstance MOZ_GUARDED_BY(sMutex); 150 151 bool Init(nsACString* const out_failureId); 152 void InitLibExtensions(); 153 154 std::shared_ptr<EglDisplay> CreateDisplayLocked( 155 bool forceAccel, bool forceSoftware, nsACString* const out_failureId, 156 const StaticMutexAutoLock& aProofOfLock); 157 158 public: 159 Maybe<SymbolLoader> GetSymbolLoader() const; 160 161 std::shared_ptr<EglDisplay> CreateDisplay(bool forceAccel, bool forceSoftware, 162 nsACString* const out_failureId); 163 std::shared_ptr<EglDisplay> CreateDisplay(ID3D11Device*); 164 std::shared_ptr<EglDisplay> DefaultDisplay(nsACString* const out_failureId); 165 166 bool IsExtensionSupported(EGLLibExtension aKnownExtension) const { 167 return mAvailableExtensions[UnderlyingValue(aKnownExtension)]; 168 } 169 170 void MarkExtensionUnsupported(EGLLibExtension aKnownExtension) { 171 mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false; 172 } 173 174 bool IsANGLE() const { return mIsANGLE; } 175 176 // - 177 // PFN wrappers 178 179 #ifdef MOZ_WIDGET_ANDROID 180 # define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS); 181 #else 182 # define PROFILE_CALL 183 #endif 184 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 196 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 204 205 #define WRAP(X) \ 206 PROFILE_CALL \ 207 BEFORE_CALL \ 208 const auto ret = mSymbols.X; \ 209 AFTER_CALL \ 210 return ret 211 212 public: 213 EGLDisplay fGetDisplay(void* display_id) const { 214 WRAP(fGetDisplay(display_id)); 215 } 216 217 EGLDisplay fGetPlatformDisplay(EGLenum platform, void* native_display, 218 const EGLAttrib* attrib_list) const { 219 WRAP(fGetPlatformDisplay(platform, native_display, attrib_list)); 220 } 221 222 EGLSurface fGetCurrentSurface(EGLint id) const { 223 WRAP(fGetCurrentSurface(id)); 224 } 225 226 EGLContext fGetCurrentContext() const { WRAP(fGetCurrentContext()); } 227 228 EGLBoolean fBindAPI(EGLenum api) const { WRAP(fBindAPI(api)); } 229 230 EGLint fGetError() const { WRAP(fGetError()); } 231 232 EGLBoolean fWaitNative(EGLint engine) const { WRAP(fWaitNative(engine)); } 233 234 EGLCastToRelevantPtr fGetProcAddress(const char* procname) const { 235 WRAP(fGetProcAddress(procname)); 236 } 237 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)); 242 } 243 244 EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device) { 245 WRAP(fReleaseDeviceANGLE(device)); 246 } 247 248 // ANDROID_get_native_client_buffer 249 EGLClientBuffer fGetNativeClientBufferANDROID( 250 const struct AHardwareBuffer* buffer) { 251 WRAP(fGetNativeClientBufferANDROID(buffer)); 252 } 253 254 private: 255 EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); } 256 257 // - 258 259 mutable Mutex mMutex = Mutex{"GLLibraryEGL::mMutex"}; 260 mutable std::unordered_map<EGLContext, PlatformThreadId> 261 mOwningThreadByContext MOZ_GUARDED_BY(mMutex); 262 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(); 270 271 if (prevCtx) { 272 mOwningThreadByContext[prevCtx] = 0; 273 } 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"); 283 } 284 return false; 285 } 286 ctxOwnerThread = tid; 287 } 288 } 289 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(); 294 295 WRAP(fMakeCurrent(dpy, draw, read, ctx)); 296 } 297 298 // - 299 300 EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const { 301 { 302 const MutexAutoLock lock(mMutex); 303 mOwningThreadByContext.erase(ctx); 304 } 305 306 WRAP(fDestroyContext(dpy, ctx)); 307 } 308 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)); 313 } 314 315 EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const { 316 WRAP(fDestroySurface(dpy, surface)); 317 } 318 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)); 324 } 325 326 private: 327 EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, 328 const EGLint* attrib_list) const { 329 WRAP(fCreatePbufferSurface(dpy, config, attrib_list)); 330 } 331 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)); 338 } 339 340 EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, 341 EGLNativePixmapType pixmap, 342 const EGLint* attrib_list) const { 343 WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list)); 344 } 345 346 EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const { 347 WRAP(fInitialize(dpy, major, minor)); 348 } 349 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)); 354 } 355 356 EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 357 EGLint attribute, EGLint* value) const { 358 WRAP(fGetConfigAttrib(dpy, config, attribute, value)); 359 } 360 361 EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, 362 EGLint* num_config) const { 363 WRAP(fGetConfigs(dpy, configs, config_size, num_config)); 364 } 365 366 EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const { 367 WRAP(fSwapBuffers(dpy, surface)); 368 } 369 370 EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface, 371 EGLNativePixmapType target) const { 372 WRAP(fCopyBuffers(dpy, surface, target)); 373 } 374 375 public: 376 const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const { 377 WRAP(fQueryString(dpy, name)); 378 } 379 380 private: 381 EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, 382 EGLint* value) const { 383 WRAP(fQueryContext(dpy, ctx, attribute, value)); 384 } 385 386 EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface, 387 EGLint buffer) const { 388 WRAP(fBindTexImage(dpy, surface, buffer)); 389 } 390 391 EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, 392 EGLint buffer) const { 393 WRAP(fReleaseTexImage(dpy, surface, buffer)); 394 } 395 396 EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const { 397 WRAP(fSwapInterval(dpy, interval)); 398 } 399 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)); 404 } 405 406 EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const { 407 WRAP(fDestroyImageKHR(dpy, image)); 408 } 409 410 EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, 411 EGLint* value) const { 412 WRAP(fQuerySurface(dpy, surface, attribute, value)); 413 } 414 415 EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, 416 EGLint attribute, void** value) const { 417 WRAP(fQuerySurfacePointerANGLE(dpy, surface, attribute, value)); 418 } 419 420 EGLSync fCreateSync(EGLDisplay dpy, EGLenum type, 421 const EGLint* attrib_list) const { 422 WRAP(fCreateSyncKHR(dpy, type, attrib_list)); 423 } 424 425 EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const { 426 WRAP(fDestroySyncKHR(dpy, sync)); 427 } 428 429 EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, 430 EGLTime timeout) const { 431 WRAP(fClientWaitSyncKHR(dpy, sync, flags, timeout)); 432 } 433 434 EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, 435 EGLint* value) const { 436 WRAP(fGetSyncAttribKHR(dpy, sync, attribute, value)); 437 } 438 439 EGLint fWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) const { 440 WRAP(fWaitSyncKHR(dpy, sync, flags)); 441 } 442 443 EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const { 444 WRAP(fDupNativeFenceFDANDROID(dpy, sync)); 445 } 446 447 // KHR_stream 448 EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, 449 const EGLint* attrib_list) const { 450 WRAP(fCreateStreamKHR(dpy, attrib_list)); 451 } 452 453 EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const { 454 WRAP(fDestroyStreamKHR(dpy, stream)); 455 } 456 457 EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, 458 EGLenum attribute, EGLint* value) const { 459 WRAP(fQueryStreamKHR(dpy, stream, attribute, value)); 460 } 461 462 // KHR_stream_consumer_gltexture 463 EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, 464 EGLStreamKHR stream) const { 465 WRAP(fStreamConsumerGLTextureExternalKHR(dpy, stream)); 466 } 467 468 EGLBoolean fStreamConsumerAcquireKHR(EGLDisplay dpy, 469 EGLStreamKHR stream) const { 470 WRAP(fStreamConsumerAcquireKHR(dpy, stream)); 471 } 472 473 EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, 474 EGLStreamKHR stream) const { 475 WRAP(fStreamConsumerReleaseKHR(dpy, stream)); 476 } 477 478 // EXT_device_query 479 EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, 480 EGLAttrib* value) const { 481 WRAP(fQueryDisplayAttribEXT(dpy, attribute, value)); 482 } 483 484 public: 485 EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, 486 EGLAttrib* value) const { 487 WRAP(fQueryDeviceAttribEXT(device, attribute, value)); 488 } 489 490 const char* fQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name) { 491 WRAP(fQueryDeviceStringEXT(device, name)); 492 } 493 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)); 499 } 500 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)); 505 } 506 507 EGLBoolean fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream, 508 void* texture, 509 const EGLAttrib* attrib_list) const { 510 WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list)); 511 } 512 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)); 517 } 518 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)); 523 } 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)); 530 } 531 EGLBoolean fExportDMABUFImage(EGLDisplay dpy, EGLImage image, int* fds, 532 EGLint* strides, EGLint* offsets) { 533 WRAP(fExportDMABUFImageMESA(dpy, image, fds, strides, offsets)); 534 } 535 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)); 541 } 542 543 #undef WRAP 544 545 #undef WRAP 546 #undef PROFILE_CALL 547 #undef BEFORE_CALL 548 #undef AFTER_CALL 549 #undef MOZ_FUNCTION_NAME 550 551 //// 552 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); 653 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); 679 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); 690 691 EGLBoolean(GLAPIENTRY* fQueryDevicesEXT)(EGLint max_devices, 692 EGLDeviceEXT* devices, 693 EGLint* num_devices); 694 695 } mSymbols = {}; 696 }; 697 698 class EglDisplay final { 699 public: 700 const RefPtr<GLLibraryEGL> mLib; 701 const EGLDisplay mDisplay; 702 const bool mIsWARP; 703 704 private: 705 std::bitset<UnderlyingValue(EGLExtension::Max)> mAvailableExtensions; 706 707 bool mShouldLeakEGLDisplay = false; 708 709 struct PrivateUseOnly final {}; 710 711 public: 712 static std::shared_ptr<EglDisplay> Create( 713 GLLibraryEGL&, EGLDisplay, bool isWarp, 714 const StaticMutexAutoLock& aProofOfLock); 715 716 // Only `public` for make_shared. 717 EglDisplay(const PrivateUseOnly&, GLLibraryEGL&, EGLDisplay, bool isWarp); 718 719 public: 720 ~EglDisplay(); 721 722 bool IsExtensionSupported(EGLExtension aKnownExtension) const { 723 return mAvailableExtensions[UnderlyingValue(aKnownExtension)]; 724 } 725 726 void MarkExtensionUnsupported(EGLExtension aKnownExtension) { 727 mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false; 728 } 729 730 void DumpEGLConfig(EGLConfig) const; 731 void DumpEGLConfigs() const; 732 733 // When called, ensure we deliberately leak the EGLDisplay rather than call 734 // eglTerminate. Used as a workaround on buggy drivers. 735 void SetShouldLeakEGLDisplay() { mShouldLeakEGLDisplay = true; } 736 737 void Shutdown(); 738 739 // - 740 741 bool HasKHRImageBase() const { 742 return IsExtensionSupported(EGLExtension::KHR_image) || 743 IsExtensionSupported(EGLExtension::KHR_image_base); 744 } 745 746 bool HasKHRImagePixmap() const { 747 return IsExtensionSupported(EGLExtension::KHR_image) || 748 IsExtensionSupported(EGLExtension::KHR_image_pixmap); 749 } 750 751 // - 752 753 EGLBoolean fTerminate() { 754 if (mShouldLeakEGLDisplay) { 755 return LOCAL_EGL_TRUE; 756 } 757 return mLib->fTerminate(mDisplay); 758 } 759 760 EGLBoolean fMakeCurrent(EGLSurface draw, EGLSurface read, 761 EGLContext ctx) const { 762 return mLib->fMakeCurrent(mDisplay, draw, read, ctx); 763 } 764 765 EGLBoolean fDestroyContext(EGLContext ctx) const { 766 return mLib->fDestroyContext(mDisplay, ctx); 767 } 768 769 EGLContext fCreateContext(EGLConfig config, EGLContext share_context, 770 const EGLint* attrib_list) const { 771 return mLib->fCreateContext(mDisplay, config, share_context, attrib_list); 772 } 773 774 EGLBoolean fDestroySurface(EGLSurface surface) const { 775 return mLib->fDestroySurface(mDisplay, surface); 776 } 777 778 EGLSurface fCreateWindowSurface(EGLConfig config, EGLNativeWindowType win, 779 const EGLint* attrib_list) const { 780 return mLib->fCreateWindowSurface(mDisplay, config, win, attrib_list); 781 } 782 783 EGLSurface fCreatePbufferSurface(EGLConfig config, 784 const EGLint* attrib_list) const { 785 return mLib->fCreatePbufferSurface(mDisplay, config, attrib_list); 786 } 787 788 EGLSurface fCreatePbufferFromClientBuffer(EGLenum buftype, 789 EGLClientBuffer buffer, 790 EGLConfig config, 791 const EGLint* attrib_list) const { 792 return mLib->fCreatePbufferFromClientBuffer(mDisplay, buftype, buffer, 793 config, attrib_list); 794 } 795 796 EGLBoolean fChooseConfig(const EGLint* attrib_list, EGLConfig* configs, 797 EGLint config_size, EGLint* num_config) const { 798 return mLib->fChooseConfig(mDisplay, attrib_list, configs, config_size, 799 num_config); 800 } 801 802 EGLBoolean fGetConfigAttrib(EGLConfig config, EGLint attribute, 803 EGLint* value) const { 804 return mLib->fGetConfigAttrib(mDisplay, config, attribute, value); 805 } 806 807 EGLBoolean fGetConfigs(EGLConfig* configs, EGLint config_size, 808 EGLint* num_config) const { 809 return mLib->fGetConfigs(mDisplay, configs, config_size, num_config); 810 } 811 812 EGLBoolean fSwapBuffers(EGLSurface surface) const { 813 return mLib->fSwapBuffers(mDisplay, surface); 814 } 815 816 EGLBoolean fBindTexImage(EGLSurface surface, EGLint buffer) const { 817 return mLib->fBindTexImage(mDisplay, surface, buffer); 818 } 819 820 EGLBoolean fReleaseTexImage(EGLSurface surface, EGLint buffer) const { 821 return mLib->fReleaseTexImage(mDisplay, surface, buffer); 822 } 823 824 EGLBoolean fSwapInterval(EGLint interval) const { 825 return mLib->fSwapInterval(mDisplay, interval); 826 } 827 828 EGLImage fCreateImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, 829 const EGLint* attribList) const { 830 MOZ_ASSERT(HasKHRImageBase()); 831 return mLib->fCreateImage(mDisplay, ctx, target, buffer, attribList); 832 } 833 834 EGLBoolean fDestroyImage(EGLImage image) const { 835 MOZ_ASSERT(HasKHRImageBase()); 836 return mLib->fDestroyImage(mDisplay, image); 837 } 838 839 EGLBoolean fQuerySurface(EGLSurface surface, EGLint attribute, 840 EGLint* value) const { 841 return mLib->fQuerySurface(mDisplay, surface, attribute, value); 842 } 843 844 EGLBoolean fQuerySurfacePointerANGLE(EGLSurface surface, EGLint attribute, 845 void** value) const { 846 MOZ_ASSERT(IsExtensionSupported( 847 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle)); 848 return mLib->fQuerySurfacePointerANGLE(mDisplay, surface, attribute, value); 849 } 850 851 EGLSync fCreateSync(EGLenum type, const EGLint* attrib_list) const { 852 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 853 return mLib->fCreateSync(mDisplay, type, attrib_list); 854 } 855 856 EGLBoolean fDestroySync(EGLSync sync) const { 857 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 858 return mLib->fDestroySync(mDisplay, sync); 859 } 860 861 EGLint fClientWaitSync(EGLSync sync, EGLint flags, EGLTime timeout) const { 862 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 863 return mLib->fClientWaitSync(mDisplay, sync, flags, timeout); 864 } 865 866 EGLBoolean fGetSyncAttrib(EGLSync sync, EGLint attribute, 867 EGLint* value) const { 868 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 869 return mLib->fGetSyncAttrib(mDisplay, sync, attribute, value); 870 } 871 872 EGLint fWaitSync(EGLSync sync, EGLint flags) const { 873 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_wait_sync)); 874 return mLib->fWaitSync(mDisplay, sync, flags); 875 } 876 877 EGLint fDupNativeFenceFDANDROID(EGLSync sync) const { 878 MOZ_ASSERT(IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync)); 879 return mLib->fDupNativeFenceFDANDROID(mDisplay, sync); 880 } 881 882 // EXT_device_query 883 EGLBoolean fQueryDisplayAttribEXT(EGLint attribute, EGLAttrib* value) const { 884 MOZ_ASSERT(mLib->IsExtensionSupported(EGLLibExtension::EXT_device_query)); 885 return mLib->fQueryDisplayAttribEXT(mDisplay, attribute, value); 886 } 887 888 // KHR_stream 889 EGLStreamKHR fCreateStreamKHR(const EGLint* attrib_list) const { 890 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream)); 891 return mLib->fCreateStreamKHR(mDisplay, attrib_list); 892 } 893 894 EGLBoolean fDestroyStreamKHR(EGLStreamKHR stream) const { 895 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream)); 896 return mLib->fDestroyStreamKHR(mDisplay, stream); 897 } 898 899 EGLBoolean fQueryStreamKHR(EGLStreamKHR stream, EGLenum attribute, 900 EGLint* value) const { 901 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream)); 902 return mLib->fQueryStreamKHR(mDisplay, stream, attribute, value); 903 } 904 905 // KHR_stream_consumer_gltexture 906 EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream) const { 907 MOZ_ASSERT( 908 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture)); 909 return mLib->fStreamConsumerGLTextureExternalKHR(mDisplay, stream); 910 } 911 912 EGLBoolean fStreamConsumerAcquireKHR(EGLStreamKHR stream) const { 913 MOZ_ASSERT( 914 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture)); 915 return mLib->fStreamConsumerAcquireKHR(mDisplay, stream); 916 } 917 918 EGLBoolean fStreamConsumerReleaseKHR(EGLStreamKHR stream) const { 919 MOZ_ASSERT( 920 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture)); 921 return mLib->fStreamConsumerReleaseKHR(mDisplay, stream); 922 } 923 924 // NV_stream_consumer_gltexture_yuv 925 EGLBoolean fStreamConsumerGLTextureExternalAttribsNV( 926 EGLStreamKHR stream, const EGLAttrib* attrib_list) const { 927 MOZ_ASSERT( 928 IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv)); 929 return mLib->fStreamConsumerGLTextureExternalAttribsNV(mDisplay, stream, 930 attrib_list); 931 } 932 933 // ANGLE_stream_producer_d3d_texture 934 EGLBoolean fCreateStreamProducerD3DTextureANGLE( 935 EGLStreamKHR stream, const EGLAttrib* attrib_list) const { 936 MOZ_ASSERT( 937 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture)); 938 return mLib->fCreateStreamProducerD3DTextureANGLE(mDisplay, stream, 939 attrib_list); 940 } 941 942 EGLBoolean fStreamPostD3DTextureANGLE(EGLStreamKHR stream, void* texture, 943 const EGLAttrib* attrib_list) const { 944 MOZ_ASSERT( 945 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture)); 946 return mLib->fStreamPostD3DTextureANGLE(mDisplay, stream, texture, 947 attrib_list); 948 } 949 950 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage 951 EGLBoolean fSwapBuffersWithDamage(EGLSurface surface, const EGLint* rects, 952 EGLint n_rects) { 953 MOZ_ASSERT( 954 IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage) || 955 IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage)); 956 return mLib->fSwapBuffersWithDamage(mDisplay, surface, rects, n_rects); 957 } 958 959 // EGL_KHR_partial_update 960 EGLBoolean fSetDamageRegion(EGLSurface surface, const EGLint* rects, 961 EGLint n_rects) { 962 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update)); 963 return mLib->fSetDamageRegion(mDisplay, surface, rects, n_rects); 964 } 965 966 EGLBoolean fExportDMABUFImageQuery(EGLImage image, int* fourcc, 967 int* num_planes, 968 uint64_t* modifiers) const { 969 MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export)); 970 return mLib->fExportDMABUFImageQuery(mDisplay, image, fourcc, num_planes, 971 modifiers); 972 } 973 EGLBoolean fExportDMABUFImage(EGLImage image, int* fds, EGLint* strides, 974 EGLint* offsets) const { 975 MOZ_ASSERT(IsExtensionSupported(EGLExtension::MESA_image_dma_buf_export)); 976 return mLib->fExportDMABUFImage(mDisplay, image, fds, strides, offsets); 977 } 978 }; 979 980 } /* namespace gl */ 981 } /* namespace mozilla */ 982 983 #endif /* GLLIBRARYEGL_H_ */