aboutsummaryrefslogtreecommitdiff
path: root/src/egl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl.c')
-rw-r--r--src/egl.c149
1 files changed, 92 insertions, 57 deletions
diff --git a/src/egl.c b/src/egl.c
index 249fe53..bcb1663 100644
--- a/src/egl.c
+++ b/src/egl.c
@@ -9,7 +9,6 @@
#include <dlfcn.h>
#include <assert.h>
#include <unistd.h>
-#include <sys/capability.h>
// TODO: rename gsr_egl to something else since this includes both egl and glx and in the future maybe vulkan too
@@ -29,43 +28,23 @@
#define GLX_DEPTH_SIZE 12
#define GLX_RGBA_TYPE 0x8014
-#define GLX_CONTEXT_PRIORITY_LEVEL_EXT 0x3100
-#define GLX_CONTEXT_PRIORITY_HIGH_EXT 0x3101
-#define GLX_CONTEXT_PRIORITY_MEDIUM_EXT 0x3102
-#define GLX_CONTEXT_PRIORITY_LOW_EXT 0x3103
-
-static void reset_cap_nice(void) {
- cap_t caps = cap_get_proc();
- if(!caps)
- return;
-
- const cap_value_t cap_to_remove = CAP_SYS_NICE;
- cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_to_remove, CAP_CLEAR);
- cap_set_flag(caps, CAP_PERMITTED, 1, &cap_to_remove, CAP_CLEAR);
- cap_set_proc(caps);
- cap_free(caps);
-}
-
// TODO: Create egl context without surface (in other words, x11/wayland agnostic, doesn't require x11/wayland dependency)
static bool gsr_egl_create_window(gsr_egl *self) {
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,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_NONE, EGL_NONE
};
const int32_t ctxattr[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
- //EGL_CONTEXT_PRIORITY_LEVEL_IMG, EGL_CONTEXT_PRIORITY_HIGH_IMG, /* requires cap_sys_nice, ignored otherwise */
EGL_NONE, EGL_NONE
};
- // TODO: Use EGL_OPENGL_ES_API as amd requires that for external texture, but that breaks software encoding
- self->eglBindAPI(EGL_OPENGL_API);
+ self->eglBindAPI(EGL_OPENGL_ES_API);
self->egl_display = self->eglGetDisplay((EGLNativeDisplayType)gsr_window_get_display(self->window));
if(!self->egl_display) {
@@ -100,11 +79,9 @@ static bool gsr_egl_create_window(gsr_egl *self) {
goto fail;
}
- reset_cap_nice();
return true;
fail:
- reset_cap_nice();
gsr_egl_unload(self);
return false;
}
@@ -225,6 +202,14 @@ static bool gsr_egl_proc_load_egl(gsr_egl *self) {
self->eglQueryDeviceStringEXT = (FUNC_eglQueryDeviceStringEXT)self->eglGetProcAddress("eglQueryDeviceStringEXT");
self->eglQueryDmaBufModifiersEXT = (FUNC_eglQueryDmaBufModifiersEXT)self->eglGetProcAddress("eglQueryDmaBufModifiersEXT");
+ self->glCreateMemoryObjectsEXT = (FUNC_glCreateMemoryObjectsEXT)self->eglGetProcAddress("glCreateMemoryObjectsEXT");
+ self->glImportMemoryFdEXT = (FUNC_glImportMemoryFdEXT)self->eglGetProcAddress("glImportMemoryFdEXT");
+ self->glIsMemoryObjectEXT = (FUNC_glIsMemoryObjectEXT)self->eglGetProcAddress("glIsMemoryObjectEXT");
+ self->glTexStorageMem2DEXT = (FUNC_glTexStorageMem2DEXT)self->eglGetProcAddress("glTexStorageMem2DEXT");
+ self->glBufferStorageMemEXT = (FUNC_glBufferStorageMemEXT)self->eglGetProcAddress("glBufferStorageMemEXT");
+ self->glNamedBufferStorageMemEXT = (FUNC_glNamedBufferStorageMemEXT)self->eglGetProcAddress("glNamedBufferStorageMemEXT");
+ self->glMemoryObjectParameterivEXT = (FUNC_glMemoryObjectParameterivEXT)self->eglGetProcAddress("glMemoryObjectParameterivEXT");
+
if(!self->eglExportDMABUFImageQueryMESA) {
fprintf(stderr, "gsr error: gsr_egl_load failed: could not find eglExportDMABUFImageQueryMESA\n");
return false;
@@ -283,15 +268,22 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
{ (void**)&self->glClearColor, "glClearColor" },
{ (void**)&self->glGenTextures, "glGenTextures" },
{ (void**)&self->glDeleteTextures, "glDeleteTextures" },
+ { (void**)&self->glActiveTexture, "glActiveTexture" },
{ (void**)&self->glBindTexture, "glBindTexture" },
+ { (void**)&self->glBindImageTexture, "glBindImageTexture" },
{ (void**)&self->glTexParameteri, "glTexParameteri" },
{ (void**)&self->glTexParameteriv, "glTexParameteriv" },
+ { (void**)&self->glTexParameterfv, "glTexParameterfv" },
{ (void**)&self->glGetTexLevelParameteriv, "glGetTexLevelParameteriv" },
{ (void**)&self->glTexImage2D, "glTexImage2D" },
+ { (void**)&self->glTexSubImage2D, "glTexSubImage2D" },
+ { (void**)&self->glTexStorage2D, "glTexStorage2D" },
{ (void**)&self->glGetTexImage, "glGetTexImage" },
{ (void**)&self->glGenFramebuffers, "glGenFramebuffers" },
{ (void**)&self->glBindFramebuffer, "glBindFramebuffer" },
{ (void**)&self->glDeleteFramebuffers, "glDeleteFramebuffers" },
+ { (void**)&self->glDispatchCompute, "glDispatchCompute" },
+ { (void**)&self->glMemoryBarrier, "glMemoryBarrier" },
{ (void**)&self->glViewport, "glViewport" },
{ (void**)&self->glFramebufferTexture2D, "glFramebufferTexture2D" },
{ (void**)&self->glDrawBuffers, "glDrawBuffers" },
@@ -324,14 +316,19 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
{ (void**)&self->glEnable, "glEnable" },
{ (void**)&self->glDisable, "glDisable" },
{ (void**)&self->glBlendFunc, "glBlendFunc" },
+ { (void**)&self->glPixelStorei, "glPixelStorei" },
{ (void**)&self->glGetUniformLocation, "glGetUniformLocation" },
{ (void**)&self->glUniform1f, "glUniform1f" },
{ (void**)&self->glUniform2f, "glUniform2f" },
+ { (void**)&self->glUniform1i, "glUniform1i" },
+ { (void**)&self->glUniform2i, "glUniform2i" },
+ { (void**)&self->glUniformMatrix2fv, "glUniformMatrix2fv" },
{ (void**)&self->glDebugMessageCallback, "glDebugMessageCallback" },
{ (void**)&self->glScissor, "glScissor" },
{ (void**)&self->glReadPixels, "glReadPixels" },
{ (void**)&self->glMapBuffer, "glMapBuffer" },
{ (void**)&self->glUnmapBuffer, "glUnmapBuffer" },
+ { (void**)&self->glGetIntegerv, "glGetIntegerv" },
{ NULL, NULL }
};
@@ -344,25 +341,56 @@ static bool gsr_egl_load_gl(gsr_egl *self, void *library) {
return true;
}
-// #define GL_DEBUG_TYPE_ERROR 0x824C
-// static void debug_callback( unsigned int source,
-// unsigned int type,
-// unsigned int id,
-// unsigned int severity,
-// int length,
-// const char* message,
-// const void* userParam )
-// {
-// (void)source;
-// (void)id;
-// (void)length;
-// (void)userParam;
-// fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n",
-// ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ),
-// type, severity, message );
-// }
-
-bool gsr_egl_load(gsr_egl *self, gsr_window *window, bool is_monitor_capture) {
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+static void debug_callback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, const void* userParam) {
+ (void)source;
+ (void)id;
+ (void)length;
+ (void)userParam;
+ if(severity != GL_DEBUG_SEVERITY_NOTIFICATION)
+ fprintf(stderr, "gsr info: gl callback: %s type = 0x%x, severity = 0x%x, message = %s\n", type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "", type, severity, message);
+}
+
+/* TODO: check for glx swap control extension string (GLX_EXT_swap_control, etc) */
+static void set_vertical_sync_enabled(gsr_egl *egl, int enabled) {
+ int result = 0;
+
+ if(egl->glXSwapIntervalEXT) {
+ assert(gsr_window_get_display_server(egl->window) == GSR_DISPLAY_SERVER_X11);
+ Display *display = gsr_window_get_display(egl->window);
+ const Window window = (Window)gsr_window_get_window(egl->window);
+ egl->glXSwapIntervalEXT(display, window, enabled ? 1 : 0);
+ } else if(egl->glXSwapIntervalMESA) {
+ result = egl->glXSwapIntervalMESA(enabled ? 1 : 0);
+ } else if(egl->glXSwapIntervalSGI) {
+ result = egl->glXSwapIntervalSGI(enabled ? 1 : 0);
+ } else {
+ static int warned = 0;
+ if (!warned) {
+ warned = 1;
+ fprintf(stderr, "gsr warning: setting vertical sync not supported\n");
+ }
+ }
+
+ if(result != 0)
+ fprintf(stderr, "gsr warning: setting vertical sync failed\n");
+}
+
+static void gsr_egl_disable_vsync(gsr_egl *self) {
+ switch(self->context_type) {
+ case GSR_GL_CONTEXT_TYPE_EGL: {
+ self->eglSwapInterval(self->egl_display, 0);
+ break;
+ }
+ case GSR_GL_CONTEXT_TYPE_GLX: {
+ set_vertical_sync_enabled(self, 0);
+ break;
+ }
+ }
+}
+
+bool gsr_egl_load(gsr_egl *self, gsr_window *window, bool is_monitor_capture, bool enable_debug) {
memset(self, 0, sizeof(gsr_egl));
self->context_type = GSR_GL_CONTEXT_TYPE_EGL;
self->window = window;
@@ -417,9 +445,24 @@ bool gsr_egl_load(gsr_egl *self, gsr_window *window, bool is_monitor_capture) {
self->glEnable(GL_BLEND);
self->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ self->glPixelStorei(GL_PACK_ALIGNMENT, 1);
+ self->glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ if(enable_debug) {
+ self->glEnable(GL_DEBUG_OUTPUT);
+ self->glDebugMessageCallback(debug_callback, NULL);
+ }
+
+ gsr_egl_disable_vsync(self);
- //self->glEnable(GL_DEBUG_OUTPUT);
- //self->glDebugMessageCallback(debug_callback, NULL);
+ if(self->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA) {
+ /* This fixes nvenc codecs unable to load on openSUSE tumbleweed because of a cuda error. Don't ask me why */
+ const bool inside_flatpak = getenv("FLATPAK_ID") != NULL;
+ if(inside_flatpak)
+ system("flatpak-spawn --host -- sh -c 'grep -q openSUSE /etc/os-release && nvidia-smi -f /dev/null'");
+ else
+ system("sh -c 'grep -q openSUSE /etc/os-release && nvidia-smi -f /dev/null'");
+ }
return true;
@@ -473,15 +516,7 @@ void gsr_egl_unload(gsr_egl *self) {
}
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(gsr_window_get_display_server(self->window) == GSR_DISPLAY_SERVER_X11) {
- Display *display = gsr_window_get_display(self->window);
- const Window window = (Window)gsr_window_get_window(self->window);
- self->glXSwapBuffers(display, window);
- }
+ self->glFlush();
+ // TODO: Use the minimal barrier required
+ self->glMemoryBarrier(GL_ALL_BARRIER_BITS); // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
}