|
20 | 20 | // Number of buffers for mailbox triple buffering |
21 | 21 | #define NUM_BUFFERS 3 |
22 | 22 |
|
23 | | -// EGLImage extension function pointers |
24 | | -typedef EGLImageKHR (*PFNEGLCREATEIMAGEKHRPROC)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); |
25 | | -typedef EGLBoolean (*PFNEGLDESTROYIMAGEKHRPROC)(EGLDisplay dpy, EGLImageKHR image); |
26 | | -typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target, GLeglImageOES image); |
27 | | - |
28 | | -// EGL_KHR_fence_sync extension function pointers |
29 | | -typedef EGLSyncKHR (*PFNEGLCREATESYNCKHRPROC)(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); |
30 | | -typedef EGLBoolean (*PFNEGLDESTROYSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync); |
31 | | -typedef EGLint (*PFNEGLCLIENTWAITSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); |
32 | | -typedef EGLint (*PFNEGLWAITSYNCKHRPROC)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); |
33 | | - |
34 | | -// Define the extension functions |
35 | | -#ifndef eglCreateImageKHR |
36 | | -static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = NULL; |
37 | | -#endif |
38 | | -#ifndef eglDestroyImageKHR |
39 | | -static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = NULL; |
40 | | -#endif |
41 | | -#ifndef glEGLImageTargetTexture2DOES |
42 | | -static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = NULL; |
43 | | -#endif |
44 | | - |
45 | | -// EGL_KHR_fence_sync extension functions |
46 | | -static PFNEGLCREATESYNCKHRPROC _eglCreateSyncKHR = NULL; |
47 | | -static PFNEGLDESTROYSYNCKHRPROC _eglDestroySyncKHR = NULL; |
48 | | -static PFNEGLCLIENTWAITSYNCKHRPROC _eglClientWaitSyncKHR = NULL; |
49 | | -static PFNEGLWAITSYNCKHRPROC _eglWaitSyncKHR = NULL; |
50 | | - |
51 | | -static void init_egl_extensions() { |
52 | | - static gboolean initialized = FALSE; |
53 | | - if (!initialized) { |
54 | | - // EGLImage extensions |
55 | | - eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR"); |
56 | | - eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR"); |
57 | | - glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES"); |
58 | | - |
59 | | - // EGL_KHR_fence_sync extensions |
60 | | - _eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC)eglGetProcAddress("eglCreateSyncKHR"); |
61 | | - _eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC)eglGetProcAddress("eglDestroySyncKHR"); |
62 | | - _eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC)eglGetProcAddress("eglClientWaitSyncKHR"); |
63 | | - _eglWaitSyncKHR = (PFNEGLWAITSYNCKHRPROC)eglGetProcAddress("eglWaitSyncKHR"); |
64 | | - |
65 | | - initialized = TRUE; |
66 | | - } |
67 | | -} |
68 | | - |
69 | 23 | // Buffer structure for mailbox triple buffering |
70 | 24 | // Each buffer has its own GPU resources |
71 | 25 | typedef struct { |
@@ -185,7 +139,7 @@ static void texture_gl_dispose(GObject* object) { |
185 | 139 | // Clean up EGLSyncKHR |
186 | 140 | EGLSyncKHR sync = buf->render_sync.load(std::memory_order_acquire); |
187 | 141 | if (sync != EGL_NO_SYNC_KHR) { |
188 | | - _eglDestroySyncKHR(egl_display, sync); |
| 142 | + eglDestroySyncKHR(egl_display, sync); |
189 | 143 | buf->render_sync.store(EGL_NO_SYNC_KHR, std::memory_order_release); |
190 | 144 | } |
191 | 145 |
|
@@ -228,7 +182,6 @@ static void texture_gl_class_init(TextureGLClass* klass) { |
228 | 182 | } |
229 | 183 |
|
230 | 184 | TextureGL* texture_gl_new(VideoOutput* video_output) { |
231 | | - init_egl_extensions(); |
232 | 185 | TextureGL* self = TEXTURE_GL(g_object_new(texture_gl_get_type(), NULL)); |
233 | 186 | self->video_output = video_output; |
234 | 187 | return self; |
@@ -270,9 +223,9 @@ void texture_gl_check_and_resize(TextureGL* self, gint64 required_width, gint64 |
270 | 223 | // Wait for any pending GPU work before destroying resources |
271 | 224 | EGLSyncKHR sync = buf->render_sync.load(std::memory_order_acquire); |
272 | 225 | if (sync != EGL_NO_SYNC_KHR) { |
273 | | - _eglClientWaitSyncKHR(egl_display, sync, |
| 226 | + eglClientWaitSyncKHR(egl_display, sync, |
274 | 227 | EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); |
275 | | - _eglDestroySyncKHR(egl_display, sync); |
| 228 | + eglDestroySyncKHR(egl_display, sync); |
276 | 229 | buf->render_sync.store(EGL_NO_SYNC_KHR, std::memory_order_release); |
277 | 230 | } |
278 | 231 |
|
@@ -363,8 +316,8 @@ gboolean texture_gl_render(TextureGL* self) { |
363 | 316 | EGLSyncKHR old_sync = back_buf->render_sync.exchange(EGL_NO_SYNC_KHR, std::memory_order_acq_rel); |
364 | 317 | if (old_sync != EGL_NO_SYNC_KHR) { |
365 | 318 | // Wait for previous GPU work to complete, then destroy the sync |
366 | | - _eglClientWaitSyncKHR(egl_display, old_sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); |
367 | | - _eglDestroySyncKHR(egl_display, old_sync); |
| 319 | + eglClientWaitSyncKHR(egl_display, old_sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); |
| 320 | + eglDestroySyncKHR(egl_display, old_sync); |
368 | 321 | } |
369 | 322 |
|
370 | 323 | gint32 required_width = self->current_width; |
@@ -394,7 +347,7 @@ gboolean texture_gl_render(TextureGL* self) { |
394 | 347 |
|
395 | 348 | // Create sync fence to mark render completion |
396 | 349 | // Consumer will use this for GPU-side synchronization |
397 | | - EGLSyncKHR new_sync = _eglCreateSyncKHR(egl_display, EGL_SYNC_FENCE_KHR, NULL); |
| 350 | + EGLSyncKHR new_sync = eglCreateSyncKHR(egl_display, EGL_SYNC_FENCE_KHR, NULL); |
398 | 351 | back_buf->render_sync.store(new_sync, std::memory_order_release); |
399 | 352 |
|
400 | 353 | return TRUE; |
@@ -485,14 +438,14 @@ gboolean texture_gl_populate_texture(FlTextureGL* texture, |
485 | 438 | if (sync != EGL_NO_SYNC_KHR) { |
486 | 439 | // Use GPU-side wait for better performance (doesn't block CPU) |
487 | 440 | // This inserts a wait into Flutter's GL command stream |
488 | | - if (_eglWaitSyncKHR != NULL) { |
489 | | - _eglWaitSyncKHR(egl_display, sync, 0); |
| 441 | + if (epoxy_has_egl_extension(egl_display, "EGL_KHR_wait_sync")) { |
| 442 | + eglWaitSyncKHR(egl_display, sync, 0); |
490 | 443 | } else { |
491 | 444 | // Fallback to CPU wait if eglWaitSyncKHR not available |
492 | | - _eglClientWaitSyncKHR(egl_display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); |
| 445 | + eglClientWaitSyncKHR(egl_display, sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, EGL_FOREVER_KHR); |
493 | 446 | } |
494 | 447 | // Destroy the sync after use (we own it now) |
495 | | - _eglDestroySyncKHR(egl_display, sync); |
| 448 | + eglDestroySyncKHR(egl_display, sync); |
496 | 449 | } |
497 | 450 |
|
498 | 451 | // Check if we need to create/recreate Flutter texture for this buffer |
|
0 commit comments