@@ -1,106 +0,0 @@
|
|||||||
#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