106
									
								
								src/egl_override.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/egl_override.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,106 @@ | ||||
| #define _GNU_SOURCE | ||||
| #include <EGL/egl.h> | ||||
| #include <dlfcn.h> | ||||
| #include <pthread.h> | ||||
| #include <stdbool.h> | ||||
| #include <stddef.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| // Some drivers expose EGL_EXT_create_context_robustness, which wlroots | ||||
| // consumes to request EGL_LOSE_CONTEXT_ON_RESET_EXT. Monado rejects sharing | ||||
| // contexts with mismatched reset notification strategies, so hide that | ||||
| // extension from wlroots by overriding eglQueryString. | ||||
|  | ||||
| typedef const char *(*eglQueryStringFn)(EGLDisplay display, EGLint name); | ||||
|  | ||||
| static const char *strip_extension(const char *exts, const char *target) | ||||
| { | ||||
|     if (!exts || !target || *target == '\0') { | ||||
|         return exts; | ||||
|     } | ||||
|  | ||||
|     size_t target_len = strlen(target); | ||||
|     const char *found = strstr(exts, target); | ||||
|     if (!found) { | ||||
|         return exts; | ||||
|     } | ||||
|  | ||||
|     char *copy = strdup(exts); | ||||
|     if (!copy) { | ||||
|         return exts; | ||||
|     } | ||||
|  | ||||
|     char *start = strstr(copy, target); | ||||
|     while (start) { | ||||
|         char *end = start + target_len; | ||||
|  | ||||
|         // Trim leading spaces before the target substring. | ||||
|         while (start > copy && start[-1] == ' ') { | ||||
|             start--; | ||||
|         } | ||||
|  | ||||
|         // Skip trailing spaces after the target substring. | ||||
|         while (*end == ' ') { | ||||
|             end++; | ||||
|         } | ||||
|  | ||||
|         memmove(start, end, strlen(end) + 1); | ||||
|         start = strstr(start, target); | ||||
|     } | ||||
|  | ||||
|     // Collapse duplicate spaces introduced by removals. | ||||
|     char *dst = copy; | ||||
|     bool prev_space = false; | ||||
|     for (char *src = copy; *src; ++src) { | ||||
|         if (*src == ' ') { | ||||
|             if (prev_space) { | ||||
|                 continue; | ||||
|             } | ||||
|             prev_space = true; | ||||
|         } else { | ||||
|             prev_space = false; | ||||
|         } | ||||
|         *dst++ = *src; | ||||
|     } | ||||
|     // Trim any trailing space left at the end. | ||||
|     if (dst > copy && dst[-1] == ' ') { | ||||
|         --dst; | ||||
|     } | ||||
|     *dst = '\0'; | ||||
|  | ||||
|     return copy; | ||||
| } | ||||
|  | ||||
| const char *eglQueryString(EGLDisplay display, EGLint name) | ||||
| { | ||||
|     static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; | ||||
|     static eglQueryStringFn real_eglQueryString = NULL; | ||||
|     static const char *cached_extensions = NULL; | ||||
|  | ||||
|     if (!real_eglQueryString) { | ||||
|         real_eglQueryString = (eglQueryStringFn)dlsym(RTLD_NEXT, "eglQueryString"); | ||||
|         if (!real_eglQueryString) { | ||||
|             fprintf(stderr, "lunarwm: failed to resolve real eglQueryString\n"); | ||||
|             return NULL; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const char *result = real_eglQueryString(display, name); | ||||
|     if (name != EGL_EXTENSIONS || result == NULL) { | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     pthread_mutex_lock(&mutex); | ||||
|     if (cached_extensions == NULL) { | ||||
|         cached_extensions = strip_extension(result, "EGL_EXT_create_context_robustness"); | ||||
|         if (cached_extensions == result) { | ||||
|             cached_extensions = strdup(result); | ||||
|         } | ||||
|     } | ||||
|     const char *filtered = cached_extensions; | ||||
|     pthread_mutex_unlock(&mutex); | ||||
|  | ||||
|     return filtered; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user