Use dri card matching current egl context

This commit is contained in:
dec05eba
2024-03-10 22:51:41 +01:00
parent 1690381bb2
commit 877465a702
6 changed files with 77 additions and 46 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -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);
}
}

View File

@@ -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)
int fd = open(card_path, O_RDONLY);
if(fd == -1)
return false;
ver = drmGetVersion(fd);
if(!ver || strstr(ver->name, "nouveau"))
goto next;
drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
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;
ver = drmGetVersion(fd);
if(!ver || strstr(ver->name, "nouveau"))
goto next;
if(plane->fb_id)
found_screen_card = true;
drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
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;
drmModeFreePlane(plane);
if(found_screen_card)
break;
}
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;