From 877465a702adae8b320b7c6ea8c3c0f2795eb2d0 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sun, 10 Mar 2024 22:51:41 +0100 Subject: Use dri card matching current egl context --- README.md | 3 +++ include/egl.h | 7 ++++++ include/utils.h | 2 +- src/egl.c | 9 +++++++ src/main.cpp | 18 ++++++------- src/utils.c | 78 +++++++++++++++++++++++++++++++++------------------------ 6 files changed, 74 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 447b4d3..64af599 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,9 @@ This is an issue on some intel integrated gpus on wayland caused by power saving This can happen if your video player is missing the H264/HEVC video codecs. Either install the codecs or use mpv. ## I get stutter in the video Try recording to an SSD and make sure it's not using NTFS file system. Also record in variable framerate format. +## I get a black screen when recording +This can happen if you use software such as prime-run to run GPU Screen Recorder. Such software should not be used to run GPU Screen Recorder. +GPU Screen Recorder needs to run on the same GPU that you use to display your monitors graphics to work. # Donations If you want to donate you can donate via bitcoin or monero. diff --git a/include/egl.h b/include/egl.h index a0a44d0..1e9e0aa 100644 --- a/include/egl.h +++ b/include/egl.h @@ -68,6 +68,8 @@ typedef void(*__GLXextFuncPtr)(void); #define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 #define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 #define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#define EGL_DEVICE_EXT 0x322C +#define EGL_DRM_DEVICE_FILE_EXT 0x3233 #define GL_FLOAT 0x1406 #define GL_FALSE 0 @@ -127,6 +129,8 @@ typedef void (*FUNC_glXSwapIntervalEXT)(Display * dpy, GLXDrawable drawable, int typedef int (*FUNC_glXSwapIntervalMESA)(unsigned int interval); typedef int (*FUNC_glXSwapIntervalSGI)(int interval); typedef void (*GLDEBUGPROC)(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char *message, const void *userParam); +typedef int (*FUNC_eglQueryDisplayAttribEXT)(EGLDisplay dpy, int32_t attribute, intptr_t *value); +typedef const char* (*FUNC_eglQueryDeviceStringEXT)(void *device, int32_t name); #define GSR_MAX_OUTPUTS 32 @@ -170,6 +174,7 @@ struct gsr_egl { EGLDisplay egl_display; EGLSurface egl_surface; EGLContext egl_context; + const char *dri_card_path; void *glx_context; void *glx_fb_config; @@ -200,6 +205,8 @@ struct gsr_egl { FUNC_eglExportDMABUFImageQueryMESA eglExportDMABUFImageQueryMESA; FUNC_eglExportDMABUFImageMESA eglExportDMABUFImageMESA; FUNC_glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES; + FUNC_eglQueryDisplayAttribEXT eglQueryDisplayAttribEXT; + FUNC_eglQueryDeviceStringEXT eglQueryDeviceStringEXT; __GLXextFuncPtr (*glXGetProcAddress)(const unsigned char *procName); GLXFBConfig* (*glXChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems); diff --git a/include/utils.h b/include/utils.h index cb3bd6b..74fdd59 100644 --- a/include/utils.h +++ b/include/utils.h @@ -37,7 +37,7 @@ gsr_monitor_rotation drm_monitor_get_display_server_rotation(const gsr_egl *egl, bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info); /* |output| should be at least 128 bytes in size */ -bool gsr_get_valid_card_path(char *output); +bool gsr_get_valid_card_path(gsr_egl *egl, char *output); /* |render_path| should be at least 128 bytes in size */ bool gsr_card_path_get_render_path(const char *card_path, char *render_path); diff --git a/src/egl.c b/src/egl.c index 884a7a6..5f6da48 100644 --- a/src/egl.c +++ b/src/egl.c @@ -355,6 +355,8 @@ static bool gsr_egl_proc_load_egl(gsr_egl *self) { self->eglExportDMABUFImageQueryMESA = (FUNC_eglExportDMABUFImageQueryMESA)self->eglGetProcAddress("eglExportDMABUFImageQueryMESA"); self->eglExportDMABUFImageMESA = (FUNC_eglExportDMABUFImageMESA)self->eglGetProcAddress("eglExportDMABUFImageMESA"); self->glEGLImageTargetTexture2DOES = (FUNC_glEGLImageTargetTexture2DOES)self->eglGetProcAddress("glEGLImageTargetTexture2DOES"); + self->eglQueryDisplayAttribEXT = (FUNC_eglQueryDisplayAttribEXT)self->eglGetProcAddress("eglQueryDisplayAttribEXT"); + self->eglQueryDeviceStringEXT = (FUNC_eglQueryDeviceStringEXT)self->eglGetProcAddress("eglQueryDeviceStringEXT"); if(!self->glEGLImageTargetTexture2DOES) { fprintf(stderr, "gsr error: gsr_egl_load failed: could not find glEGLImageTargetTexture2DOES\n"); @@ -521,9 +523,16 @@ bool gsr_egl_load(gsr_egl *self, Display *dpy, bool wayland, bool is_monitor_cap if(!gl_get_gpu_info(self, &self->gpu_info)) goto fail; + if(self->eglQueryDisplayAttribEXT && self->eglQueryDeviceStringEXT) { + intptr_t device = 0; + if(self->eglQueryDisplayAttribEXT(self->egl_display, EGL_DEVICE_EXT, &device) && device) + self->dri_card_path = self->eglQueryDeviceStringEXT((void*)device, EGL_DRM_DEVICE_FILE_EXT); + } + /* Nvfbc requires glx */ if(!wayland && is_monitor_capture && self->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA) { self->context_type = GSR_GL_CONTEXT_TYPE_GLX; + self->dri_card_path = NULL; if(!gsr_egl_switch_to_glx_context(self)) goto fail; } diff --git a/src/main.cpp b/src/main.cpp index 867e80a..6efa735 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -441,7 +441,7 @@ static AVCodecContext *create_video_codec_context(AVPixelFormat pix_fmt, //codec_context->compression_level = 2; } - av_opt_set(codec_context->priv_data, "bsf", "hevc_metadata=colour_primaries=9:transfer_characteristics=16:matrix_coefficients=9", 0); + //av_opt_set(codec_context->priv_data, "bsf", "hevc_metadata=colour_primaries=9:transfer_characteristics=16:matrix_coefficients=9", 0); //codec_context->rc_max_rate = codec_context->bit_rate; //codec_context->rc_min_rate = codec_context->bit_rate; @@ -1376,16 +1376,12 @@ static void list_supported_video_codecs() { _exit(1); } - gsr_egl_unload(&egl); - if(dpy) - XCloseDisplay(dpy); - char card_path[128]; card_path[0] = '\0'; if(wayland || egl.gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA) { // TODO: Allow specifying another card, and in other places - if(!gsr_get_valid_card_path(card_path)) { - fprintf(stderr, "Error: no /dev/dri/cardX device found\n"); + if(!gsr_get_valid_card_path(&egl, card_path)) { + fprintf(stderr, "Error: no /dev/dri/cardX device found. If you are using prime-run then run without it\n"); _exit(2); } } @@ -1401,6 +1397,10 @@ static void list_supported_video_codecs() { puts("av1"); fflush(stdout); + + gsr_egl_unload(&egl); + if(dpy) + XCloseDisplay(dpy); } static gsr_capture* create_capture_impl(const char *window_str, const char *screen_region, bool wayland, gsr_gpu_info gpu_inf, gsr_egl &egl, int fps, bool overclock, VideoCodec video_codec, gsr_color_range color_range) { @@ -1877,8 +1877,8 @@ int main(int argc, char **argv) { egl.card_path[0] = '\0'; if(wayland || egl.gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA) { // TODO: Allow specifying another card, and in other places - if(!gsr_get_valid_card_path(egl.card_path)) { - fprintf(stderr, "Error: no /dev/dri/cardX device found\n"); + if(!gsr_get_valid_card_path(&egl, egl.card_path)) { + fprintf(stderr, "Error: no /dev/dri/cardX device found. If you are using prime-run then run without it\n"); _exit(2); } } diff --git a/src/utils.c b/src/utils.c index c342f6e..45e58a6 100644 --- a/src/utils.c +++ b/src/utils.c @@ -370,47 +370,59 @@ bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info) { return supported; } -bool gsr_get_valid_card_path(char *output) { - for(int i = 0; i < 10; ++i) { - drmVersion *ver = NULL; - drmModePlaneResPtr planes = NULL; - bool found_screen_card = false; +static bool try_card_has_valid_plane(const char *card_path) { + drmVersion *ver = NULL; + drmModePlaneResPtr planes = NULL; + bool found_screen_card = false; - sprintf(output, DRM_DEV_NAME, DRM_DIR_NAME, i); - int fd = open(output, O_RDONLY); - if(fd == -1) - continue; + int fd = open(card_path, O_RDONLY); + if(fd == -1) + return false; - ver = drmGetVersion(fd); - if(!ver || strstr(ver->name, "nouveau")) - goto next; + ver = drmGetVersion(fd); + if(!ver || strstr(ver->name, "nouveau")) + goto next; - drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); + drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1); - planes = drmModeGetPlaneResources(fd); - if(!planes) - goto next; + planes = drmModeGetPlaneResources(fd); + if(!planes) + goto next; - for(uint32_t j = 0; j < planes->count_planes; ++j) { - drmModePlanePtr plane = drmModeGetPlane(fd, planes->planes[j]); - if(!plane) - continue; - - if(plane->fb_id) - found_screen_card = true; + for(uint32_t j = 0; j < planes->count_planes; ++j) { + drmModePlanePtr plane = drmModeGetPlane(fd, planes->planes[j]); + if(!plane) + continue; - drmModeFreePlane(plane); - if(found_screen_card) - break; - } + if(plane->fb_id) + found_screen_card = true; - next: - if(planes) - drmModeFreePlaneResources(planes); - if(ver) - drmFreeVersion(ver); - close(fd); + drmModeFreePlane(plane); if(found_screen_card) + break; + } + + next: + if(planes) + drmModeFreePlaneResources(planes); + if(ver) + drmFreeVersion(ver); + close(fd); + if(found_screen_card) + return true; + + return false; +} + +bool gsr_get_valid_card_path(gsr_egl *egl, char *output) { + if(egl->dri_card_path) { + strncpy(output, egl->dri_card_path, 128); + return try_card_has_valid_plane(output); + } + + for(int i = 0; i < 10; ++i) { + snprintf(output, 128, DRM_DEV_NAME, DRM_DIR_NAME, i); + if(try_card_has_valid_plane(output)) return true; } return false; -- cgit v1.2.3