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 "GLTypes.h" 13 #include "mozilla/EnumTypeTraits.h" 14 #include "mozilla/Maybe.h" 15 #include "mozilla/RefPtr.h" 16 #include "nsISupports.h" 17 #include "prlink.h" 18 19 #include <bitset> 20 #include <memory> 21 #include <unordered_map> 22 23 #ifdef MOZ_WIDGET_ANDROID 24 # include "mozilla/ProfilerLabels.h" 25 #endif 26 27 #if defined(MOZ_X11) 28 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)mozilla::DefaultXDisplay()) 29 #else 30 # define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) 31 #endif 32 33 struct ID3D11Device; 34 35 extern "C" { 36 struct AHardwareBuffer; 37 } 38 39 namespace angle { 40 class Platform; 41 } 42 43 namespace mozilla { 44 45 namespace gfx { 46 class DataSourceSurface; 47 } 48 49 namespace gl { 50 51 class SymbolLoader; 52 53 PRLibrary* LoadApitraceLibrary(); 54 55 void BeforeEGLCall(const char* funcName); 56 void AfterEGLCall(const char* funcName); 57 58 class EglDisplay; 59 /** 60 * Known GL extensions that can be queried by 61 * IsExtensionSupported. The results of this are cached, and as 62 * such it's safe to use this even in performance critical code. 63 * If you add to this array, remember to add to the string names 64 * in GLLibraryEGL.cpp. 65 */ 66 enum class EGLLibExtension { 67 ANDROID_get_native_client_buffer, 68 ANGLE_device_creation, 69 ANGLE_device_creation_d3d11, 70 ANGLE_platform_angle, 71 ANGLE_platform_angle_d3d, 72 EXT_device_query, 73 Max 74 }; 75 76 /** 77 * Known GL extensions that can be queried by 78 * IsExtensionSupported. The results of this are cached, and as 79 * such it's safe to use this even in performance critical code. 80 * If you add to this array, remember to add to the string names 81 * in GLLibraryEGL.cpp. 82 */ 83 enum class EGLExtension { 84 KHR_image_base, 85 KHR_image_pixmap, 86 KHR_gl_texture_2D_image, 87 ANGLE_surface_d3d_texture_2d_share_handle, 88 EXT_create_context_robustness, 89 KHR_image, 90 KHR_fence_sync, 91 KHR_wait_sync, 92 ANDROID_native_fence_sync, 93 EGL_ANDROID_image_crop, 94 ANGLE_d3d_share_handle_client_buffer, 95 KHR_create_context, 96 KHR_stream, 97 KHR_stream_consumer_gltexture, 98 NV_stream_consumer_gltexture_yuv, 99 ANGLE_stream_producer_d3d_texture, 100 KHR_surfaceless_context, 101 KHR_create_context_no_error, 102 MOZ_create_context_provoking_vertex_dont_care, 103 EXT_swap_buffers_with_damage, 104 KHR_swap_buffers_with_damage, 105 EXT_buffer_age, 106 KHR_partial_update, 107 NV_robustness_video_memory_purge, 108 Max 109 }; 110 111 // - 112 113 class GLLibraryEGL final { 114 friend class EglDisplay; 115 116 public: 117 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GLLibraryEGL) 118 119 private: 120 PRLibrary* mEGLLibrary = nullptr; 121 PRLibrary* mGLLibrary = nullptr; 122 bool mIsANGLE = false; 123 std::bitset<UnderlyingValue(EGLLibExtension::Max)> mAvailableExtensions; 124 std::weak_ptr<EglDisplay> mDefaultDisplay; 125 std::unordered_map<EGLDisplay, std::weak_ptr<EglDisplay>> mActiveDisplays; 126 127 public: 128 static RefPtr<GLLibraryEGL> Create(nsACString* const out_failureId); 129 130 private: 131 ~GLLibraryEGL() = default; 132 133 bool Init(nsACString* const out_failureId); 134 void InitLibExtensions(); 135 136 public: 137 Maybe<SymbolLoader> GetSymbolLoader() const; 138 139 std::shared_ptr<EglDisplay> CreateDisplay(bool forceAccel, 140 nsACString* const out_failureId); 141 std::shared_ptr<EglDisplay> CreateDisplay(ID3D11Device*); 142 std::shared_ptr<EglDisplay> DefaultDisplay(nsACString* const out_failureId); 143 IsExtensionSupported(EGLLibExtension aKnownExtension)144 bool IsExtensionSupported(EGLLibExtension aKnownExtension) const { 145 return mAvailableExtensions[UnderlyingValue(aKnownExtension)]; 146 } 147 MarkExtensionUnsupported(EGLLibExtension aKnownExtension)148 void MarkExtensionUnsupported(EGLLibExtension aKnownExtension) { 149 mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false; 150 } 151 IsANGLE()152 bool IsANGLE() const { return mIsANGLE; } 153 154 // - 155 // PFN wrappers 156 157 #ifdef MOZ_WIDGET_ANDROID 158 # define PROFILE_CALL AUTO_PROFILER_LABEL(__func__, GRAPHICS); 159 #else 160 # define PROFILE_CALL 161 #endif 162 163 #ifndef MOZ_FUNCTION_NAME 164 # ifdef __GNUC__ 165 # define MOZ_FUNCTION_NAME __PRETTY_FUNCTION__ 166 # elif defined(_MSC_VER) 167 # define MOZ_FUNCTION_NAME __FUNCTION__ 168 # else 169 # define MOZ_FUNCTION_NAME \ 170 __func__ // defined in C99, supported in various C++ compilers. Just raw 171 // function name. 172 # endif 173 #endif 174 175 #ifdef DEBUG 176 # define BEFORE_CALL BeforeEGLCall(MOZ_FUNCTION_NAME); 177 # define AFTER_CALL AfterEGLCall(MOZ_FUNCTION_NAME); 178 #else 179 # define BEFORE_CALL 180 # define AFTER_CALL 181 #endif 182 183 #define WRAP(X) \ 184 PROFILE_CALL \ 185 BEFORE_CALL \ 186 const auto ret = mSymbols.X; \ 187 AFTER_CALL \ 188 return ret 189 190 public: fGetDisplay(void * display_id)191 EGLDisplay fGetDisplay(void* display_id) const { 192 WRAP(fGetDisplay(display_id)); 193 } 194 fGetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)195 EGLDisplay fGetPlatformDisplay(EGLenum platform, void* native_display, 196 const EGLAttrib* attrib_list) const { 197 WRAP(fGetPlatformDisplay(platform, native_display, attrib_list)); 198 } 199 fGetCurrentSurface(EGLint id)200 EGLSurface fGetCurrentSurface(EGLint id) const { 201 WRAP(fGetCurrentSurface(id)); 202 } 203 fGetCurrentContext()204 EGLContext fGetCurrentContext() const { WRAP(fGetCurrentContext()); } 205 fBindAPI(EGLenum api)206 EGLBoolean fBindAPI(EGLenum api) const { WRAP(fBindAPI(api)); } 207 fGetError()208 EGLint fGetError() const { WRAP(fGetError()); } 209 fWaitNative(EGLint engine)210 EGLBoolean fWaitNative(EGLint engine) const { WRAP(fWaitNative(engine)); } 211 fGetProcAddress(const char * procname)212 EGLCastToRelevantPtr fGetProcAddress(const char* procname) const { 213 WRAP(fGetProcAddress(procname)); 214 } 215 216 // ANGLE_device_creation fCreateDeviceANGLE(EGLint device_type,void * native_device,const EGLAttrib * attrib_list)217 EGLDeviceEXT fCreateDeviceANGLE(EGLint device_type, void* native_device, 218 const EGLAttrib* attrib_list) const { 219 WRAP(fCreateDeviceANGLE(device_type, native_device, attrib_list)); 220 } 221 fReleaseDeviceANGLE(EGLDeviceEXT device)222 EGLBoolean fReleaseDeviceANGLE(EGLDeviceEXT device) { 223 WRAP(fReleaseDeviceANGLE(device)); 224 } 225 226 // ANDROID_get_native_client_buffer fGetNativeClientBufferANDROID(const struct AHardwareBuffer * buffer)227 EGLClientBuffer fGetNativeClientBufferANDROID( 228 const struct AHardwareBuffer* buffer) { 229 WRAP(fGetNativeClientBufferANDROID(buffer)); 230 } 231 232 private: fTerminate(EGLDisplay display)233 EGLBoolean fTerminate(EGLDisplay display) const { WRAP(fTerminate(display)); } 234 fMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)235 EGLBoolean fMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, 236 EGLContext ctx) const { 237 WRAP(fMakeCurrent(dpy, draw, read, ctx)); 238 } 239 fDestroyContext(EGLDisplay dpy,EGLContext ctx)240 EGLBoolean fDestroyContext(EGLDisplay dpy, EGLContext ctx) const { 241 WRAP(fDestroyContext(dpy, ctx)); 242 } 243 fCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)244 EGLContext fCreateContext(EGLDisplay dpy, EGLConfig config, 245 EGLContext share_context, 246 const EGLint* attrib_list) const { 247 WRAP(fCreateContext(dpy, config, share_context, attrib_list)); 248 } 249 fDestroySurface(EGLDisplay dpy,EGLSurface surface)250 EGLBoolean fDestroySurface(EGLDisplay dpy, EGLSurface surface) const { 251 WRAP(fDestroySurface(dpy, surface)); 252 } 253 254 public: fCreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)255 EGLSurface fCreateWindowSurface(EGLDisplay dpy, EGLConfig config, 256 EGLNativeWindowType win, 257 const EGLint* attrib_list) const { 258 WRAP(fCreateWindowSurface(dpy, config, win, attrib_list)); 259 } 260 261 private: fCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)262 EGLSurface fCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, 263 const EGLint* attrib_list) const { 264 WRAP(fCreatePbufferSurface(dpy, config, attrib_list)); 265 } 266 fCreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)267 EGLSurface fCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, 268 EGLClientBuffer buffer, 269 EGLConfig config, 270 const EGLint* attrib_list) const { 271 WRAP(fCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, 272 attrib_list)); 273 } 274 fCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)275 EGLSurface fCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, 276 EGLNativePixmapType pixmap, 277 const EGLint* attrib_list) const { 278 WRAP(fCreatePixmapSurface(dpy, config, pixmap, attrib_list)); 279 } 280 fInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)281 EGLBoolean fInitialize(EGLDisplay dpy, EGLint* major, EGLint* minor) const { 282 WRAP(fInitialize(dpy, major, minor)); 283 } 284 fChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)285 EGLBoolean fChooseConfig(EGLDisplay dpy, const EGLint* attrib_list, 286 EGLConfig* configs, EGLint config_size, 287 EGLint* num_config) const { 288 WRAP(fChooseConfig(dpy, attrib_list, configs, config_size, num_config)); 289 } 290 fGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)291 EGLBoolean fGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 292 EGLint attribute, EGLint* value) const { 293 WRAP(fGetConfigAttrib(dpy, config, attribute, value)); 294 } 295 fGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)296 EGLBoolean fGetConfigs(EGLDisplay dpy, EGLConfig* configs, EGLint config_size, 297 EGLint* num_config) const { 298 WRAP(fGetConfigs(dpy, configs, config_size, num_config)); 299 } 300 fSwapBuffers(EGLDisplay dpy,EGLSurface surface)301 EGLBoolean fSwapBuffers(EGLDisplay dpy, EGLSurface surface) const { 302 WRAP(fSwapBuffers(dpy, surface)); 303 } 304 fCopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)305 EGLBoolean fCopyBuffers(EGLDisplay dpy, EGLSurface surface, 306 EGLNativePixmapType target) const { 307 WRAP(fCopyBuffers(dpy, surface, target)); 308 } 309 310 public: fQueryString(EGLDisplay dpy,EGLint name)311 const GLubyte* fQueryString(EGLDisplay dpy, EGLint name) const { 312 WRAP(fQueryString(dpy, name)); 313 } 314 315 private: fQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)316 EGLBoolean fQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, 317 EGLint* value) const { 318 WRAP(fQueryContext(dpy, ctx, attribute, value)); 319 } 320 fBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)321 EGLBoolean fBindTexImage(EGLDisplay dpy, EGLSurface surface, 322 EGLint buffer) const { 323 WRAP(fBindTexImage(dpy, surface, buffer)); 324 } 325 fReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)326 EGLBoolean fReleaseTexImage(EGLDisplay dpy, EGLSurface surface, 327 EGLint buffer) const { 328 WRAP(fReleaseTexImage(dpy, surface, buffer)); 329 } 330 fSwapInterval(EGLDisplay dpy,EGLint interval)331 EGLBoolean fSwapInterval(EGLDisplay dpy, EGLint interval) const { 332 WRAP(fSwapInterval(dpy, interval)); 333 } 334 fCreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)335 EGLImage fCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, 336 EGLClientBuffer buffer, 337 const EGLint* attrib_list) const { 338 WRAP(fCreateImageKHR(dpy, ctx, target, buffer, attrib_list)); 339 } 340 fDestroyImage(EGLDisplay dpy,EGLImage image)341 EGLBoolean fDestroyImage(EGLDisplay dpy, EGLImage image) const { 342 WRAP(fDestroyImageKHR(dpy, image)); 343 } 344 fQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)345 EGLBoolean fQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, 346 EGLint* value) const { 347 WRAP(fQuerySurface(dpy, surface, attribute, value)); 348 } 349 fQuerySurfacePointerANGLE(EGLDisplay dpy,EGLSurface surface,EGLint attribute,void ** value)350 EGLBoolean fQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, 351 EGLint attribute, void** value) const { 352 WRAP(fQuerySurfacePointerANGLE(dpy, surface, attribute, value)); 353 } 354 fCreateSync(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)355 EGLSync fCreateSync(EGLDisplay dpy, EGLenum type, 356 const EGLint* attrib_list) const { 357 WRAP(fCreateSyncKHR(dpy, type, attrib_list)); 358 } 359 fDestroySync(EGLDisplay dpy,EGLSync sync)360 EGLBoolean fDestroySync(EGLDisplay dpy, EGLSync sync) const { 361 WRAP(fDestroySyncKHR(dpy, sync)); 362 } 363 fClientWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)364 EGLint fClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, 365 EGLTime timeout) const { 366 WRAP(fClientWaitSyncKHR(dpy, sync, flags, timeout)); 367 } 368 fGetSyncAttrib(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLint * value)369 EGLBoolean fGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, 370 EGLint* value) const { 371 WRAP(fGetSyncAttribKHR(dpy, sync, attribute, value)); 372 } 373 fWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags)374 EGLint fWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) const { 375 WRAP(fWaitSyncKHR(dpy, sync, flags)); 376 } 377 fDupNativeFenceFDANDROID(EGLDisplay dpy,EGLSync sync)378 EGLint fDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) const { 379 WRAP(fDupNativeFenceFDANDROID(dpy, sync)); 380 } 381 382 // KHR_stream fCreateStreamKHR(EGLDisplay dpy,const EGLint * attrib_list)383 EGLStreamKHR fCreateStreamKHR(EGLDisplay dpy, 384 const EGLint* attrib_list) const { 385 WRAP(fCreateStreamKHR(dpy, attrib_list)); 386 } 387 fDestroyStreamKHR(EGLDisplay dpy,EGLStreamKHR stream)388 EGLBoolean fDestroyStreamKHR(EGLDisplay dpy, EGLStreamKHR stream) const { 389 WRAP(fDestroyStreamKHR(dpy, stream)); 390 } 391 fQueryStreamKHR(EGLDisplay dpy,EGLStreamKHR stream,EGLenum attribute,EGLint * value)392 EGLBoolean fQueryStreamKHR(EGLDisplay dpy, EGLStreamKHR stream, 393 EGLenum attribute, EGLint* value) const { 394 WRAP(fQueryStreamKHR(dpy, stream, attribute, value)); 395 } 396 397 // KHR_stream_consumer_gltexture fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy,EGLStreamKHR stream)398 EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLDisplay dpy, 399 EGLStreamKHR stream) const { 400 WRAP(fStreamConsumerGLTextureExternalKHR(dpy, stream)); 401 } 402 fStreamConsumerAcquireKHR(EGLDisplay dpy,EGLStreamKHR stream)403 EGLBoolean fStreamConsumerAcquireKHR(EGLDisplay dpy, 404 EGLStreamKHR stream) const { 405 WRAP(fStreamConsumerAcquireKHR(dpy, stream)); 406 } 407 fStreamConsumerReleaseKHR(EGLDisplay dpy,EGLStreamKHR stream)408 EGLBoolean fStreamConsumerReleaseKHR(EGLDisplay dpy, 409 EGLStreamKHR stream) const { 410 WRAP(fStreamConsumerReleaseKHR(dpy, stream)); 411 } 412 413 // EXT_device_query fQueryDisplayAttribEXT(EGLDisplay dpy,EGLint attribute,EGLAttrib * value)414 EGLBoolean fQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, 415 EGLAttrib* value) const { 416 WRAP(fQueryDisplayAttribEXT(dpy, attribute, value)); 417 } 418 419 public: fQueryDeviceAttribEXT(EGLDeviceEXT device,EGLint attribute,EGLAttrib * value)420 EGLBoolean fQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, 421 EGLAttrib* value) const { 422 WRAP(fQueryDeviceAttribEXT(device, attribute, value)); 423 } 424 425 private: 426 // NV_stream_consumer_gltexture_yuv fStreamConsumerGLTextureExternalAttribsNV(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)427 EGLBoolean fStreamConsumerGLTextureExternalAttribsNV( 428 EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const { 429 WRAP(fStreamConsumerGLTextureExternalAttribsNV(dpy, stream, attrib_list)); 430 } 431 432 // ANGLE_stream_producer_d3d_texture fCreateStreamProducerD3DTextureANGLE(EGLDisplay dpy,EGLStreamKHR stream,const EGLAttrib * attrib_list)433 EGLBoolean fCreateStreamProducerD3DTextureANGLE( 434 EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list) const { 435 WRAP(fCreateStreamProducerD3DTextureANGLE(dpy, stream, attrib_list)); 436 } 437 fStreamPostD3DTextureANGLE(EGLDisplay dpy,EGLStreamKHR stream,void * texture,const EGLAttrib * attrib_list)438 EGLBoolean fStreamPostD3DTextureANGLE(EGLDisplay dpy, EGLStreamKHR stream, 439 void* texture, 440 const EGLAttrib* attrib_list) const { 441 WRAP(fStreamPostD3DTextureANGLE(dpy, stream, texture, attrib_list)); 442 } 443 444 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage fSwapBuffersWithDamage(EGLDisplay dpy,EGLSurface surface,const EGLint * rects,EGLint n_rects)445 EGLBoolean fSwapBuffersWithDamage(EGLDisplay dpy, EGLSurface surface, 446 const EGLint* rects, EGLint n_rects) { 447 WRAP(fSwapBuffersWithDamage(dpy, surface, rects, n_rects)); 448 } 449 450 // EGL_KHR_partial_update fSetDamageRegion(EGLDisplay dpy,EGLSurface surface,const EGLint * rects,EGLint n_rects)451 EGLBoolean fSetDamageRegion(EGLDisplay dpy, EGLSurface surface, 452 const EGLint* rects, EGLint n_rects) { 453 WRAP(fSetDamageRegion(dpy, surface, rects, n_rects)); 454 } 455 456 #undef WRAP 457 #undef PROFILE_CALL 458 #undef BEFORE_CALL 459 #undef AFTER_CALL 460 #undef MOZ_FUNCTION_NAME 461 462 //// 463 464 private: 465 struct { 466 EGLCastToRelevantPtr(GLAPIENTRY* fGetProcAddress)(const char* procname); 467 EGLDisplay(GLAPIENTRY* fGetDisplay)(void* display_id); 468 EGLDisplay(GLAPIENTRY* fGetPlatformDisplay)(EGLenum platform, 469 void* native_display, 470 const EGLAttrib* attrib_list); 471 EGLBoolean(GLAPIENTRY* fTerminate)(EGLDisplay dpy); 472 EGLSurface(GLAPIENTRY* fGetCurrentSurface)(EGLint); 473 EGLContext(GLAPIENTRY* fGetCurrentContext)(void); 474 EGLBoolean(GLAPIENTRY* fMakeCurrent)(EGLDisplay dpy, EGLSurface draw, 475 EGLSurface read, EGLContext ctx); 476 EGLBoolean(GLAPIENTRY* fDestroyContext)(EGLDisplay dpy, EGLContext ctx); 477 EGLContext(GLAPIENTRY* fCreateContext)(EGLDisplay dpy, EGLConfig config, 478 EGLContext share_context, 479 const EGLint* attrib_list); 480 EGLBoolean(GLAPIENTRY* fDestroySurface)(EGLDisplay dpy, EGLSurface surface); 481 EGLSurface(GLAPIENTRY* fCreateWindowSurface)(EGLDisplay dpy, 482 EGLConfig config, 483 EGLNativeWindowType win, 484 const EGLint* attrib_list); 485 EGLSurface(GLAPIENTRY* fCreatePbufferSurface)(EGLDisplay dpy, 486 EGLConfig config, 487 const EGLint* attrib_list); 488 EGLSurface(GLAPIENTRY* fCreatePbufferFromClientBuffer)( 489 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 490 EGLConfig config, const EGLint* attrib_list); 491 EGLSurface(GLAPIENTRY* fCreatePixmapSurface)(EGLDisplay dpy, 492 EGLConfig config, 493 EGLNativePixmapType pixmap, 494 const EGLint* attrib_list); 495 EGLBoolean(GLAPIENTRY* fBindAPI)(EGLenum api); 496 EGLBoolean(GLAPIENTRY* fInitialize)(EGLDisplay dpy, EGLint* major, 497 EGLint* minor); 498 EGLBoolean(GLAPIENTRY* fChooseConfig)(EGLDisplay dpy, 499 const EGLint* attrib_list, 500 EGLConfig* configs, 501 EGLint config_size, 502 EGLint* num_config); 503 EGLint(GLAPIENTRY* fGetError)(void); 504 EGLBoolean(GLAPIENTRY* fGetConfigAttrib)(EGLDisplay dpy, EGLConfig config, 505 EGLint attribute, EGLint* value); 506 EGLBoolean(GLAPIENTRY* fGetConfigs)(EGLDisplay dpy, EGLConfig* configs, 507 EGLint config_size, EGLint* num_config); 508 EGLBoolean(GLAPIENTRY* fWaitNative)(EGLint engine); 509 EGLBoolean(GLAPIENTRY* fSwapBuffers)(EGLDisplay dpy, EGLSurface surface); 510 EGLBoolean(GLAPIENTRY* fCopyBuffers)(EGLDisplay dpy, EGLSurface surface, 511 EGLNativePixmapType target); 512 const GLubyte*(GLAPIENTRY* fQueryString)(EGLDisplay, EGLint name); 513 EGLBoolean(GLAPIENTRY* fQueryContext)(EGLDisplay dpy, EGLContext ctx, 514 EGLint attribute, EGLint* value); 515 EGLBoolean(GLAPIENTRY* fBindTexImage)(EGLDisplay, EGLSurface surface, 516 EGLint buffer); 517 EGLBoolean(GLAPIENTRY* fReleaseTexImage)(EGLDisplay, EGLSurface surface, 518 EGLint buffer); 519 EGLBoolean(GLAPIENTRY* fSwapInterval)(EGLDisplay dpy, EGLint interval); 520 EGLImage(GLAPIENTRY* fCreateImageKHR)(EGLDisplay dpy, EGLContext ctx, 521 EGLenum target, 522 EGLClientBuffer buffer, 523 const EGLint* attrib_list); 524 EGLBoolean(GLAPIENTRY* fDestroyImageKHR)(EGLDisplay dpy, EGLImage image); 525 EGLBoolean(GLAPIENTRY* fQuerySurface)(EGLDisplay dpy, EGLSurface surface, 526 EGLint attribute, EGLint* value); 527 EGLBoolean(GLAPIENTRY* fQuerySurfacePointerANGLE)(EGLDisplay dpy, 528 EGLSurface surface, 529 EGLint attribute, 530 void** value); 531 EGLSync(GLAPIENTRY* fCreateSyncKHR)(EGLDisplay dpy, EGLenum type, 532 const EGLint* attrib_list); 533 EGLBoolean(GLAPIENTRY* fDestroySyncKHR)(EGLDisplay dpy, EGLSync sync); 534 EGLint(GLAPIENTRY* fClientWaitSyncKHR)(EGLDisplay dpy, EGLSync sync, 535 EGLint flags, EGLTime timeout); 536 EGLBoolean(GLAPIENTRY* fGetSyncAttribKHR)(EGLDisplay dpy, EGLSync sync, 537 EGLint attribute, EGLint* value); 538 EGLint(GLAPIENTRY* fWaitSyncKHR)(EGLDisplay dpy, EGLSync sync, 539 EGLint flags); 540 EGLint(GLAPIENTRY* fDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync); 541 // KHR_stream 542 EGLStreamKHR(GLAPIENTRY* fCreateStreamKHR)(EGLDisplay dpy, 543 const EGLint* attrib_list); 544 EGLBoolean(GLAPIENTRY* fDestroyStreamKHR)(EGLDisplay dpy, 545 EGLStreamKHR stream); 546 EGLBoolean(GLAPIENTRY* fQueryStreamKHR)(EGLDisplay dpy, EGLStreamKHR stream, 547 EGLenum attribute, EGLint* value); 548 // KHR_stream_consumer_gltexture 549 EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalKHR)( 550 EGLDisplay dpy, EGLStreamKHR stream); 551 EGLBoolean(GLAPIENTRY* fStreamConsumerAcquireKHR)(EGLDisplay dpy, 552 EGLStreamKHR stream); 553 EGLBoolean(GLAPIENTRY* fStreamConsumerReleaseKHR)(EGLDisplay dpy, 554 EGLStreamKHR stream); 555 // EXT_device_query 556 EGLBoolean(GLAPIENTRY* fQueryDisplayAttribEXT)(EGLDisplay dpy, 557 EGLint attribute, 558 EGLAttrib* value); 559 EGLBoolean(GLAPIENTRY* fQueryDeviceAttribEXT)(EGLDeviceEXT device, 560 EGLint attribute, 561 EGLAttrib* value); 562 // NV_stream_consumer_gltexture_yuv 563 EGLBoolean(GLAPIENTRY* fStreamConsumerGLTextureExternalAttribsNV)( 564 EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list); 565 // ANGLE_stream_producer_d3d_texture 566 EGLBoolean(GLAPIENTRY* fCreateStreamProducerD3DTextureANGLE)( 567 EGLDisplay dpy, EGLStreamKHR stream, const EGLAttrib* attrib_list); 568 EGLBoolean(GLAPIENTRY* fStreamPostD3DTextureANGLE)( 569 EGLDisplay dpy, EGLStreamKHR stream, void* texture, 570 const EGLAttrib* attrib_list); 571 // ANGLE_device_creation 572 EGLDeviceEXT(GLAPIENTRY* fCreateDeviceANGLE)(EGLint device_type, 573 void* native_device, 574 const EGLAttrib* attrib_list); 575 EGLBoolean(GLAPIENTRY* fReleaseDeviceANGLE)(EGLDeviceEXT device); 576 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage 577 EGLBoolean(GLAPIENTRY* fSwapBuffersWithDamage)(EGLDisplay dpy, 578 EGLSurface surface, 579 const EGLint* rects, 580 EGLint n_rects); 581 // EGL_KHR_partial_update 582 EGLBoolean(GLAPIENTRY* fSetDamageRegion)(EGLDisplay dpy, EGLSurface surface, 583 const EGLint* rects, 584 EGLint n_rects); 585 EGLClientBuffer(GLAPIENTRY* fGetNativeClientBufferANDROID)( 586 const struct AHardwareBuffer* buffer); 587 } mSymbols = {}; 588 }; 589 590 class EglDisplay final { 591 public: 592 const RefPtr<GLLibraryEGL> mLib; 593 const EGLDisplay mDisplay; 594 const bool mIsWARP; 595 596 private: 597 std::bitset<UnderlyingValue(EGLExtension::Max)> mAvailableExtensions; 598 599 struct PrivateUseOnly final {}; 600 601 public: 602 static std::shared_ptr<EglDisplay> Create(GLLibraryEGL&, EGLDisplay, 603 bool isWarp); 604 605 // Only `public` for make_shared. 606 EglDisplay(const PrivateUseOnly&, GLLibraryEGL&, EGLDisplay, bool isWarp); 607 608 public: 609 ~EglDisplay(); 610 IsExtensionSupported(EGLExtension aKnownExtension)611 bool IsExtensionSupported(EGLExtension aKnownExtension) const { 612 return mAvailableExtensions[UnderlyingValue(aKnownExtension)]; 613 } 614 MarkExtensionUnsupported(EGLExtension aKnownExtension)615 void MarkExtensionUnsupported(EGLExtension aKnownExtension) { 616 mAvailableExtensions[UnderlyingValue(aKnownExtension)] = false; 617 } 618 619 void DumpEGLConfig(EGLConfig) const; 620 void DumpEGLConfigs() const; 621 622 void Shutdown(); 623 624 // - 625 HasKHRImageBase()626 bool HasKHRImageBase() const { 627 return IsExtensionSupported(EGLExtension::KHR_image) || 628 IsExtensionSupported(EGLExtension::KHR_image_base); 629 } 630 HasKHRImagePixmap()631 bool HasKHRImagePixmap() const { 632 return IsExtensionSupported(EGLExtension::KHR_image) || 633 IsExtensionSupported(EGLExtension::KHR_image_pixmap); 634 } 635 636 // - 637 fTerminate()638 EGLBoolean fTerminate() { return mLib->fTerminate(mDisplay); } 639 fMakeCurrent(EGLSurface draw,EGLSurface read,EGLContext ctx)640 EGLBoolean fMakeCurrent(EGLSurface draw, EGLSurface read, 641 EGLContext ctx) const { 642 return mLib->fMakeCurrent(mDisplay, draw, read, ctx); 643 } 644 fDestroyContext(EGLContext ctx)645 EGLBoolean fDestroyContext(EGLContext ctx) const { 646 return mLib->fDestroyContext(mDisplay, ctx); 647 } 648 fCreateContext(EGLConfig config,EGLContext share_context,const EGLint * attrib_list)649 EGLContext fCreateContext(EGLConfig config, EGLContext share_context, 650 const EGLint* attrib_list) const { 651 return mLib->fCreateContext(mDisplay, config, share_context, attrib_list); 652 } 653 fDestroySurface(EGLSurface surface)654 EGLBoolean fDestroySurface(EGLSurface surface) const { 655 return mLib->fDestroySurface(mDisplay, surface); 656 } 657 fCreateWindowSurface(EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)658 EGLSurface fCreateWindowSurface(EGLConfig config, EGLNativeWindowType win, 659 const EGLint* attrib_list) const { 660 return mLib->fCreateWindowSurface(mDisplay, config, win, attrib_list); 661 } 662 fCreatePbufferSurface(EGLConfig config,const EGLint * attrib_list)663 EGLSurface fCreatePbufferSurface(EGLConfig config, 664 const EGLint* attrib_list) const { 665 return mLib->fCreatePbufferSurface(mDisplay, config, attrib_list); 666 } 667 fCreatePbufferFromClientBuffer(EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)668 EGLSurface fCreatePbufferFromClientBuffer(EGLenum buftype, 669 EGLClientBuffer buffer, 670 EGLConfig config, 671 const EGLint* attrib_list) const { 672 return mLib->fCreatePbufferFromClientBuffer(mDisplay, buftype, buffer, 673 config, attrib_list); 674 } 675 fChooseConfig(const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)676 EGLBoolean fChooseConfig(const EGLint* attrib_list, EGLConfig* configs, 677 EGLint config_size, EGLint* num_config) const { 678 return mLib->fChooseConfig(mDisplay, attrib_list, configs, config_size, 679 num_config); 680 } 681 fGetConfigAttrib(EGLConfig config,EGLint attribute,EGLint * value)682 EGLBoolean fGetConfigAttrib(EGLConfig config, EGLint attribute, 683 EGLint* value) const { 684 return mLib->fGetConfigAttrib(mDisplay, config, attribute, value); 685 } 686 fGetConfigs(EGLConfig * configs,EGLint config_size,EGLint * num_config)687 EGLBoolean fGetConfigs(EGLConfig* configs, EGLint config_size, 688 EGLint* num_config) const { 689 return mLib->fGetConfigs(mDisplay, configs, config_size, num_config); 690 } 691 fSwapBuffers(EGLSurface surface)692 EGLBoolean fSwapBuffers(EGLSurface surface) const { 693 return mLib->fSwapBuffers(mDisplay, surface); 694 } 695 fBindTexImage(EGLSurface surface,EGLint buffer)696 EGLBoolean fBindTexImage(EGLSurface surface, EGLint buffer) const { 697 return mLib->fBindTexImage(mDisplay, surface, buffer); 698 } 699 fReleaseTexImage(EGLSurface surface,EGLint buffer)700 EGLBoolean fReleaseTexImage(EGLSurface surface, EGLint buffer) const { 701 return mLib->fReleaseTexImage(mDisplay, surface, buffer); 702 } 703 fSwapInterval(EGLint interval)704 EGLBoolean fSwapInterval(EGLint interval) const { 705 return mLib->fSwapInterval(mDisplay, interval); 706 } 707 fCreateImage(EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attribList)708 EGLImage fCreateImage(EGLContext ctx, EGLenum target, EGLClientBuffer buffer, 709 const EGLint* attribList) const { 710 MOZ_ASSERT(HasKHRImageBase()); 711 return mLib->fCreateImage(mDisplay, ctx, target, buffer, attribList); 712 } 713 fDestroyImage(EGLImage image)714 EGLBoolean fDestroyImage(EGLImage image) const { 715 MOZ_ASSERT(HasKHRImageBase()); 716 return mLib->fDestroyImage(mDisplay, image); 717 } 718 fQuerySurface(EGLSurface surface,EGLint attribute,EGLint * value)719 EGLBoolean fQuerySurface(EGLSurface surface, EGLint attribute, 720 EGLint* value) const { 721 return mLib->fQuerySurface(mDisplay, surface, attribute, value); 722 } 723 fQuerySurfacePointerANGLE(EGLSurface surface,EGLint attribute,void ** value)724 EGLBoolean fQuerySurfacePointerANGLE(EGLSurface surface, EGLint attribute, 725 void** value) const { 726 MOZ_ASSERT(IsExtensionSupported( 727 EGLExtension::ANGLE_surface_d3d_texture_2d_share_handle)); 728 return mLib->fQuerySurfacePointerANGLE(mDisplay, surface, attribute, value); 729 } 730 fCreateSync(EGLenum type,const EGLint * attrib_list)731 EGLSync fCreateSync(EGLenum type, const EGLint* attrib_list) const { 732 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 733 return mLib->fCreateSync(mDisplay, type, attrib_list); 734 } 735 fDestroySync(EGLSync sync)736 EGLBoolean fDestroySync(EGLSync sync) const { 737 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 738 return mLib->fDestroySync(mDisplay, sync); 739 } 740 fClientWaitSync(EGLSync sync,EGLint flags,EGLTime timeout)741 EGLint fClientWaitSync(EGLSync sync, EGLint flags, EGLTime timeout) const { 742 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 743 return mLib->fClientWaitSync(mDisplay, sync, flags, timeout); 744 } 745 fGetSyncAttrib(EGLSync sync,EGLint attribute,EGLint * value)746 EGLBoolean fGetSyncAttrib(EGLSync sync, EGLint attribute, 747 EGLint* value) const { 748 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_fence_sync)); 749 return mLib->fGetSyncAttrib(mDisplay, sync, attribute, value); 750 } 751 fWaitSync(EGLSync sync,EGLint flags)752 EGLint fWaitSync(EGLSync sync, EGLint flags) const { 753 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_wait_sync)); 754 return mLib->fWaitSync(mDisplay, sync, flags); 755 } 756 fDupNativeFenceFDANDROID(EGLSync sync)757 EGLint fDupNativeFenceFDANDROID(EGLSync sync) const { 758 MOZ_ASSERT(IsExtensionSupported(EGLExtension::ANDROID_native_fence_sync)); 759 return mLib->fDupNativeFenceFDANDROID(mDisplay, sync); 760 } 761 762 // EXT_device_query fQueryDisplayAttribEXT(EGLint attribute,EGLAttrib * value)763 EGLBoolean fQueryDisplayAttribEXT(EGLint attribute, EGLAttrib* value) const { 764 MOZ_ASSERT(mLib->IsExtensionSupported(EGLLibExtension::EXT_device_query)); 765 return mLib->fQueryDisplayAttribEXT(mDisplay, attribute, value); 766 } 767 768 // KHR_stream fCreateStreamKHR(const EGLint * attrib_list)769 EGLStreamKHR fCreateStreamKHR(const EGLint* attrib_list) const { 770 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream)); 771 return mLib->fCreateStreamKHR(mDisplay, attrib_list); 772 } 773 fDestroyStreamKHR(EGLStreamKHR stream)774 EGLBoolean fDestroyStreamKHR(EGLStreamKHR stream) const { 775 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream)); 776 return mLib->fDestroyStreamKHR(mDisplay, stream); 777 } 778 fQueryStreamKHR(EGLStreamKHR stream,EGLenum attribute,EGLint * value)779 EGLBoolean fQueryStreamKHR(EGLStreamKHR stream, EGLenum attribute, 780 EGLint* value) const { 781 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_stream)); 782 return mLib->fQueryStreamKHR(mDisplay, stream, attribute, value); 783 } 784 785 // KHR_stream_consumer_gltexture fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream)786 EGLBoolean fStreamConsumerGLTextureExternalKHR(EGLStreamKHR stream) const { 787 MOZ_ASSERT( 788 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture)); 789 return mLib->fStreamConsumerGLTextureExternalKHR(mDisplay, stream); 790 } 791 fStreamConsumerAcquireKHR(EGLStreamKHR stream)792 EGLBoolean fStreamConsumerAcquireKHR(EGLStreamKHR stream) const { 793 MOZ_ASSERT( 794 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture)); 795 return mLib->fStreamConsumerAcquireKHR(mDisplay, stream); 796 } 797 fStreamConsumerReleaseKHR(EGLStreamKHR stream)798 EGLBoolean fStreamConsumerReleaseKHR(EGLStreamKHR stream) const { 799 MOZ_ASSERT( 800 IsExtensionSupported(EGLExtension::KHR_stream_consumer_gltexture)); 801 return mLib->fStreamConsumerReleaseKHR(mDisplay, stream); 802 } 803 804 // NV_stream_consumer_gltexture_yuv fStreamConsumerGLTextureExternalAttribsNV(EGLStreamKHR stream,const EGLAttrib * attrib_list)805 EGLBoolean fStreamConsumerGLTextureExternalAttribsNV( 806 EGLStreamKHR stream, const EGLAttrib* attrib_list) const { 807 MOZ_ASSERT( 808 IsExtensionSupported(EGLExtension::NV_stream_consumer_gltexture_yuv)); 809 return mLib->fStreamConsumerGLTextureExternalAttribsNV(mDisplay, stream, 810 attrib_list); 811 } 812 813 // ANGLE_stream_producer_d3d_texture fCreateStreamProducerD3DTextureANGLE(EGLStreamKHR stream,const EGLAttrib * attrib_list)814 EGLBoolean fCreateStreamProducerD3DTextureANGLE( 815 EGLStreamKHR stream, const EGLAttrib* attrib_list) const { 816 MOZ_ASSERT( 817 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture)); 818 return mLib->fCreateStreamProducerD3DTextureANGLE(mDisplay, stream, 819 attrib_list); 820 } 821 fStreamPostD3DTextureANGLE(EGLStreamKHR stream,void * texture,const EGLAttrib * attrib_list)822 EGLBoolean fStreamPostD3DTextureANGLE(EGLStreamKHR stream, void* texture, 823 const EGLAttrib* attrib_list) const { 824 MOZ_ASSERT( 825 IsExtensionSupported(EGLExtension::ANGLE_stream_producer_d3d_texture)); 826 return mLib->fStreamPostD3DTextureANGLE(mDisplay, stream, texture, 827 attrib_list); 828 } 829 830 // EGL_EXT_swap_buffers_with_damage / EGL_KHR_swap_buffers_with_damage fSwapBuffersWithDamage(EGLSurface surface,const EGLint * rects,EGLint n_rects)831 EGLBoolean fSwapBuffersWithDamage(EGLSurface surface, const EGLint* rects, 832 EGLint n_rects) { 833 MOZ_ASSERT( 834 IsExtensionSupported(EGLExtension::EXT_swap_buffers_with_damage) || 835 IsExtensionSupported(EGLExtension::KHR_swap_buffers_with_damage)); 836 return mLib->fSwapBuffersWithDamage(mDisplay, surface, rects, n_rects); 837 } 838 839 // EGL_KHR_partial_update fSetDamageRegion(EGLSurface surface,const EGLint * rects,EGLint n_rects)840 EGLBoolean fSetDamageRegion(EGLSurface surface, const EGLint* rects, 841 EGLint n_rects) { 842 MOZ_ASSERT(IsExtensionSupported(EGLExtension::KHR_partial_update)); 843 return mLib->fSetDamageRegion(mDisplay, surface, rects, n_rects); 844 } 845 }; 846 847 } /* namespace gl */ 848 } /* namespace mozilla */ 849 850 #endif /* GLLIBRARYEGL_H_ */ 851