aboutsummaryrefslogtreecommitdiff
path: root/src/egl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl.c')
-rw-r--r--src/egl.c144
1 files changed, 114 insertions, 30 deletions
diff --git a/src/egl.c b/src/egl.c
index ec9ad07..87c2b84 100644
--- a/src/egl.c
+++ b/src/egl.c
@@ -1,18 +1,19 @@
#include "../include/egl.h"
#include "../include/library_loader.h"
#include "../include/utils.h"
+
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <assert.h>
+#include <unistd.h>
+#include <sys/capability.h>
#include <wayland-client.h>
#include <wayland-egl.h>
-#include <unistd.h>
-#include <sys/capability.h>
-// TODO: rename gsr_egl to something else since this includes both egl and eglx and in the future maybe vulkan too
+// TODO: rename gsr_egl to something else since this includes both egl and glx and in the future maybe vulkan too
// TODO: Move this shit to a separate wayland file, and have a separate file for x11.
@@ -93,7 +94,7 @@ static void registry_add_object(void *data, struct wl_registry *registry, uint32
}
if(egl->wayland.num_outputs == GSR_MAX_OUTPUTS) {
- fprintf(stderr, "gsr warning: reached maximum outputs (32), ignoring output %u\n", name);
+ fprintf(stderr, "gsr warning: reached maximum outputs (%d), ignoring output %u\n", GSR_MAX_OUTPUTS, name);
return;
}
@@ -134,21 +135,42 @@ static void reset_cap_nice(void) {
cap_free(caps);
}
-#define GLX_DRAWABLE_TYPE 0x8010
-#define GLX_RENDER_TYPE 0x8011
-#define GLX_RGBA_BIT 0x00000001
-#define GLX_WINDOW_BIT 0x00000001
-#define GLX_PIXMAP_BIT 0x00000002
+static void store_x11_monitor(const gsr_monitor *monitor, void *userdata) {
+ gsr_egl *egl = userdata;
+ if(egl->x11.num_outputs == GSR_MAX_OUTPUTS) {
+ fprintf(stderr, "gsr warning: reached maximum outputs (%d), ignoring output %s\n", GSR_MAX_OUTPUTS, monitor->name);
+ return;
+ }
+
+ char *monitor_name = strdup(monitor->name);
+ if(!monitor_name)
+ return;
+
+ const int index = egl->x11.num_outputs;
+ egl->x11.outputs[index].name = monitor_name;
+ egl->x11.outputs[index].pos = monitor->pos;
+ egl->x11.outputs[index].size = monitor->size;
+ egl->x11.outputs[index].connector_id = monitor->connector_id;
+ egl->x11.outputs[index].rotation = monitor->rotation;
+ egl->x11.outputs[index].monitor_identifier = monitor->monitor_identifier;
+ ++egl->x11.num_outputs;
+}
+
+#define GLX_DRAWABLE_TYPE 0x8010
+#define GLX_RENDER_TYPE 0x8011
+#define GLX_RGBA_BIT 0x00000001
+#define GLX_WINDOW_BIT 0x00000001
+#define GLX_PIXMAP_BIT 0x00000002
#define GLX_BIND_TO_TEXTURE_RGBA_EXT 0x20D1
#define GLX_BIND_TO_TEXTURE_TARGETS_EXT 0x20D3
#define GLX_TEXTURE_2D_BIT_EXT 0x00000002
-#define GLX_DOUBLEBUFFER 5
-#define GLX_RED_SIZE 8
-#define GLX_GREEN_SIZE 9
-#define GLX_BLUE_SIZE 10
-#define GLX_ALPHA_SIZE 11
-#define GLX_DEPTH_SIZE 12
-#define GLX_RGBA_TYPE 0x8014
+#define GLX_DOUBLEBUFFER 5
+#define GLX_RED_SIZE 8
+#define GLX_GREEN_SIZE 9
+#define GLX_BLUE_SIZE 10
+#define GLX_ALPHA_SIZE 11
+#define GLX_DEPTH_SIZE 12
+#define GLX_RGBA_TYPE 0x8014
#define GLX_CONTEXT_PRIORITY_LEVEL_EXT 0x3100
#define GLX_CONTEXT_PRIORITY_HIGH_EXT 0x3101
@@ -185,6 +207,7 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) {
EGLConfig ecfg;
int32_t num_config = 0;
+ // TODO: Use EGL_OPENGL_ES_BIT as amd requires that for external texture, but that breaks software encoding
const int32_t attr[] = {
EGL_BUFFER_SIZE, 24,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
@@ -226,6 +249,7 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) {
}
}
+ // TODO: Use EGL_OPENGL_ES_API as amd requires that for external texture, but that breaks software encoding
self->eglBindAPI(EGL_OPENGL_API);
self->egl_display = self->eglGetDisplay(self->wayland.dpy ? (EGLNativeDisplayType)self->wayland.dpy : (EGLNativeDisplayType)self->x11.dpy);
@@ -238,12 +262,12 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) {
fprintf(stderr, "gsr error: gsr_egl_create_window failed: eglInitialize failed\n");
goto fail;
}
-
+
if(!self->eglChooseConfig(self->egl_display, attr, &ecfg, 1, &num_config) || num_config != 1) {
fprintf(stderr, "gsr error: gsr_egl_create_window failed: failed to find a matching config\n");
goto fail;
}
-
+
self->egl_context = self->eglCreateContext(self->egl_display, ecfg, NULL, ctxattr);
if(!self->egl_context) {
fprintf(stderr, "gsr error: gsr_egl_create_window failed: failed to create egl context\n");
@@ -251,6 +275,7 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) {
}
if(wayland) {
+ // TODO: Error check?
self->wayland.surface = wl_compositor_create_surface(self->wayland.compositor);
self->wayland.window = wl_egl_window_create(self->wayland.surface, 16, 16);
self->egl_surface = self->eglCreateWindowSurface(self->egl_display, ecfg, (EGLNativeWindowType)self->wayland.window, NULL);
@@ -268,6 +293,11 @@ static bool gsr_egl_create_window(gsr_egl *self, bool wayland) {
goto fail;
}
+ if(!wayland) {
+ self->x11.num_outputs = 0;
+ for_each_active_monitor_output_x11_not_cached(self->x11.dpy, store_x11_monitor, self);
+ }
+
reset_cap_nice();
return true;
@@ -363,6 +393,17 @@ static bool gsr_egl_proc_load_egl(gsr_egl *self) {
self->glEGLImageTargetTexture2DOES = (FUNC_glEGLImageTargetTexture2DOES)self->eglGetProcAddress("glEGLImageTargetTexture2DOES");
self->eglQueryDisplayAttribEXT = (FUNC_eglQueryDisplayAttribEXT)self->eglGetProcAddress("eglQueryDisplayAttribEXT");
self->eglQueryDeviceStringEXT = (FUNC_eglQueryDeviceStringEXT)self->eglGetProcAddress("eglQueryDeviceStringEXT");
+ self->eglQueryDmaBufModifiersEXT = (FUNC_eglQueryDmaBufModifiersEXT)self->eglGetProcAddress("eglQueryDmaBufModifiersEXT");
+
+ if(!self->eglExportDMABUFImageQueryMESA) {
+ fprintf(stderr, "gsr error: gsr_egl_load failed: could not find eglExportDMABUFImageQueryMESA\n");
+ return false;
+ }
+
+ if(!self->eglExportDMABUFImageMESA) {
+ fprintf(stderr, "gsr error: gsr_egl_load failed: could not find eglExportDMABUFImageMESA\n");
+ return false;
+ }
if(!self->glEGLImageTargetTexture2DOES) {
fprintf(stderr, "gsr error: gsr_egl_load failed: could not find glEGLImageTargetTexture2DOES\n");
@@ -417,9 +458,7 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
{ (void**)&self->glTexParameteriv, "glTexParameteriv" },
{ (void**)&self->glGetTexLevelParameteriv, "glGetTexLevelParameteriv" },
{ (void**)&self->glTexImage2D, "glTexImage2D" },
- { (void**)&self->glCopyImageSubData, "glCopyImageSubData" },
{ (void**)&self->glGetTexImage, "glGetTexImage" },
- { (void**)&self->glClearTexImage, "glClearTexImage" },
{ (void**)&self->glGenFramebuffers, "glGenFramebuffers" },
{ (void**)&self->glBindFramebuffer, "glBindFramebuffer" },
{ (void**)&self->glDeleteFramebuffers, "glDeleteFramebuffers" },
@@ -460,6 +499,9 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
{ (void**)&self->glUniform2f, "glUniform2f" },
{ (void**)&self->glDebugMessageCallback, "glDebugMessageCallback" },
{ (void**)&self->glScissor, "glScissor" },
+ { (void**)&self->glReadPixels, "glReadPixels" },
+ { (void**)&self->glMapBuffer, "glMapBuffer" },
+ { (void**)&self->glUnmapBuffer, "glUnmapBuffer" },
{ NULL, NULL }
};
@@ -503,10 +545,6 @@ bool gsr_egl_load(gsr_egl *self, Display *dpy, bool wayland, bool is_monitor_cap
}
self->glx_library = dlopen("libGLX.so.0", RTLD_LAZY);
- if(!self->glx_library) {
- fprintf(stderr, "gsr error: gsr_egl_load: failed to load libGLX.so.0, error: %s\n", dlerror());
- goto fail;
- }
self->gl_library = dlopen("libGL.so.1", RTLD_LAZY);
if(!self->egl_library) {
@@ -517,7 +555,8 @@ bool gsr_egl_load(gsr_egl *self, Display *dpy, bool wayland, bool is_monitor_cap
if(!gsr_egl_load_egl(self, self->egl_library))
goto fail;
- if(!gsr_egl_load_glx(self, self->glx_library))
+ /* In some distros (alpine for example libGLX doesn't exist, but libGL can be used instead) */
+ if(!gsr_egl_load_glx(self, self->glx_library ? self->glx_library : self->gl_library))
goto fail;
if(!gsr_egl_load_gl(self, self->gl_library))
@@ -588,6 +627,14 @@ void gsr_egl_unload(gsr_egl *self) {
self->x11.window = None;
}
+ for(int i = 0; i < self->x11.num_outputs; ++i) {
+ if(self->x11.outputs[i].name) {
+ free(self->x11.outputs[i].name);
+ self->x11.outputs[i].name = NULL;
+ }
+ }
+ self->x11.num_outputs = 0;
+
if(self->wayland.window) {
wl_egl_window_destroy(self->wayland.window);
self->wayland.window = NULL;
@@ -644,10 +691,47 @@ void gsr_egl_unload(gsr_egl *self) {
memset(self, 0, sizeof(gsr_egl));
}
-void gsr_egl_update(gsr_egl *self) {
- if(!self->wayland.dpy)
- return;
+bool gsr_egl_process_event(gsr_egl *self) {
+ switch(gsr_egl_get_display_server(self)) {
+ case GSR_DISPLAY_SERVER_X11: {
+ if(XPending(self->x11.dpy)) {
+ XNextEvent(self->x11.dpy, &self->x11.xev);
+ return true;
+ }
+ return false;
+ }
+ case GSR_DISPLAY_SERVER_WAYLAND: {
+ // TODO: pselect on wl_display_get_fd before doing dispatch
+ const bool events_available = wl_display_dispatch_pending(self->wayland.dpy) > 0;
+ wl_display_flush(self->wayland.dpy);
+ return events_available;
+ }
+ }
+ return false;
+}
+
+void gsr_egl_swap_buffers(gsr_egl *self) {
+ /* This uses less cpu than swap buffer on nvidia */
+ // TODO: Do these and remove swap
+ //self->glFlush();
+ //self->glFinish();
+ if(self->egl_display) {
+ self->eglSwapBuffers(self->egl_display, self->egl_surface);
+ } else if(self->x11.window) {
+ self->glXSwapBuffers(self->x11.dpy, self->x11.window);
+ }
+}
- // TODO: pselect on wl_display_get_fd before doing dispatch
- wl_display_dispatch(self->wayland.dpy);
+gsr_display_server gsr_egl_get_display_server(const gsr_egl *self) {
+ if(self->wayland.dpy)
+ return GSR_DISPLAY_SERVER_WAYLAND;
+ else
+ return GSR_DISPLAY_SERVER_X11;
+}
+
+XEvent* gsr_egl_get_event_data(gsr_egl *self) {
+ if(gsr_egl_get_display_server(self) == GSR_DISPLAY_SERVER_X11)
+ return &self->x11.xev;
+ else
+ return NULL;
}