mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 17:17:16 +09:00
Use dri card matching current egl context
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
18
src/main.cpp
18
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);
|
||||
}
|
||||
}
|
||||
|
||||
84
src/utils.c
84
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)
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user