mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-05-07 15:19:55 +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.
|
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
|
## 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.
|
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
|
# Donations
|
||||||
If you want to donate you can donate via bitcoin or monero.
|
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_HIGH_IMG 0x3101
|
||||||
#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
|
#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102
|
||||||
#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103
|
#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_FLOAT 0x1406
|
||||||
#define GL_FALSE 0
|
#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_glXSwapIntervalMESA)(unsigned int interval);
|
||||||
typedef int (*FUNC_glXSwapIntervalSGI)(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 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
|
#define GSR_MAX_OUTPUTS 32
|
||||||
|
|
||||||
@@ -170,6 +174,7 @@ struct gsr_egl {
|
|||||||
EGLDisplay egl_display;
|
EGLDisplay egl_display;
|
||||||
EGLSurface egl_surface;
|
EGLSurface egl_surface;
|
||||||
EGLContext egl_context;
|
EGLContext egl_context;
|
||||||
|
const char *dri_card_path;
|
||||||
|
|
||||||
void *glx_context;
|
void *glx_context;
|
||||||
void *glx_fb_config;
|
void *glx_fb_config;
|
||||||
@@ -200,6 +205,8 @@ struct gsr_egl {
|
|||||||
FUNC_eglExportDMABUFImageQueryMESA eglExportDMABUFImageQueryMESA;
|
FUNC_eglExportDMABUFImageQueryMESA eglExportDMABUFImageQueryMESA;
|
||||||
FUNC_eglExportDMABUFImageMESA eglExportDMABUFImageMESA;
|
FUNC_eglExportDMABUFImageMESA eglExportDMABUFImageMESA;
|
||||||
FUNC_glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES;
|
FUNC_glEGLImageTargetTexture2DOES glEGLImageTargetTexture2DOES;
|
||||||
|
FUNC_eglQueryDisplayAttribEXT eglQueryDisplayAttribEXT;
|
||||||
|
FUNC_eglQueryDeviceStringEXT eglQueryDeviceStringEXT;
|
||||||
|
|
||||||
__GLXextFuncPtr (*glXGetProcAddress)(const unsigned char *procName);
|
__GLXextFuncPtr (*glXGetProcAddress)(const unsigned char *procName);
|
||||||
GLXFBConfig* (*glXChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems);
|
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);
|
bool gl_get_gpu_info(gsr_egl *egl, gsr_gpu_info *info);
|
||||||
|
|
||||||
/* |output| should be at least 128 bytes in size */
|
/* |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 */
|
/* |render_path| should be at least 128 bytes in size */
|
||||||
bool gsr_card_path_get_render_path(const char *card_path, char *render_path);
|
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->eglExportDMABUFImageQueryMESA = (FUNC_eglExportDMABUFImageQueryMESA)self->eglGetProcAddress("eglExportDMABUFImageQueryMESA");
|
||||||
self->eglExportDMABUFImageMESA = (FUNC_eglExportDMABUFImageMESA)self->eglGetProcAddress("eglExportDMABUFImageMESA");
|
self->eglExportDMABUFImageMESA = (FUNC_eglExportDMABUFImageMESA)self->eglGetProcAddress("eglExportDMABUFImageMESA");
|
||||||
self->glEGLImageTargetTexture2DOES = (FUNC_glEGLImageTargetTexture2DOES)self->eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
self->glEGLImageTargetTexture2DOES = (FUNC_glEGLImageTargetTexture2DOES)self->eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||||
|
self->eglQueryDisplayAttribEXT = (FUNC_eglQueryDisplayAttribEXT)self->eglGetProcAddress("eglQueryDisplayAttribEXT");
|
||||||
|
self->eglQueryDeviceStringEXT = (FUNC_eglQueryDeviceStringEXT)self->eglGetProcAddress("eglQueryDeviceStringEXT");
|
||||||
|
|
||||||
if(!self->glEGLImageTargetTexture2DOES) {
|
if(!self->glEGLImageTargetTexture2DOES) {
|
||||||
fprintf(stderr, "gsr error: gsr_egl_load failed: could not find glEGLImageTargetTexture2DOES\n");
|
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))
|
if(!gl_get_gpu_info(self, &self->gpu_info))
|
||||||
goto fail;
|
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 */
|
/* Nvfbc requires glx */
|
||||||
if(!wayland && is_monitor_capture && self->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA) {
|
if(!wayland && is_monitor_capture && self->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA) {
|
||||||
self->context_type = GSR_GL_CONTEXT_TYPE_GLX;
|
self->context_type = GSR_GL_CONTEXT_TYPE_GLX;
|
||||||
|
self->dri_card_path = NULL;
|
||||||
if(!gsr_egl_switch_to_glx_context(self))
|
if(!gsr_egl_switch_to_glx_context(self))
|
||||||
goto fail;
|
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;
|
//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_max_rate = codec_context->bit_rate;
|
||||||
//codec_context->rc_min_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);
|
_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
gsr_egl_unload(&egl);
|
|
||||||
if(dpy)
|
|
||||||
XCloseDisplay(dpy);
|
|
||||||
|
|
||||||
char card_path[128];
|
char card_path[128];
|
||||||
card_path[0] = '\0';
|
card_path[0] = '\0';
|
||||||
if(wayland || egl.gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA) {
|
if(wayland || egl.gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA) {
|
||||||
// TODO: Allow specifying another card, and in other places
|
// TODO: Allow specifying another card, and in other places
|
||||||
if(!gsr_get_valid_card_path(card_path)) {
|
if(!gsr_get_valid_card_path(&egl, card_path)) {
|
||||||
fprintf(stderr, "Error: no /dev/dri/cardX device found\n");
|
fprintf(stderr, "Error: no /dev/dri/cardX device found. If you are using prime-run then run without it\n");
|
||||||
_exit(2);
|
_exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1401,6 +1397,10 @@ static void list_supported_video_codecs() {
|
|||||||
puts("av1");
|
puts("av1");
|
||||||
|
|
||||||
fflush(stdout);
|
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) {
|
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';
|
egl.card_path[0] = '\0';
|
||||||
if(wayland || egl.gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA) {
|
if(wayland || egl.gpu_info.vendor != GSR_GPU_VENDOR_NVIDIA) {
|
||||||
// TODO: Allow specifying another card, and in other places
|
// TODO: Allow specifying another card, and in other places
|
||||||
if(!gsr_get_valid_card_path(egl.card_path)) {
|
if(!gsr_get_valid_card_path(&egl, egl.card_path)) {
|
||||||
fprintf(stderr, "Error: no /dev/dri/cardX device found\n");
|
fprintf(stderr, "Error: no /dev/dri/cardX device found. If you are using prime-run then run without it\n");
|
||||||
_exit(2);
|
_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;
|
return supported;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gsr_get_valid_card_path(char *output) {
|
static bool try_card_has_valid_plane(const char *card_path) {
|
||||||
for(int i = 0; i < 10; ++i) {
|
drmVersion *ver = NULL;
|
||||||
drmVersion *ver = NULL;
|
drmModePlaneResPtr planes = NULL;
|
||||||
drmModePlaneResPtr planes = NULL;
|
bool found_screen_card = false;
|
||||||
bool found_screen_card = false;
|
|
||||||
|
|
||||||
sprintf(output, DRM_DEV_NAME, DRM_DIR_NAME, i);
|
int fd = open(card_path, O_RDONLY);
|
||||||
int fd = open(output, O_RDONLY);
|
if(fd == -1)
|
||||||
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;
|
continue;
|
||||||
|
|
||||||
ver = drmGetVersion(fd);
|
if(plane->fb_id)
|
||||||
if(!ver || strstr(ver->name, "nouveau"))
|
found_screen_card = true;
|
||||||
goto next;
|
|
||||||
|
|
||||||
drmSetClientCap(fd, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
|
drmModeFreePlane(plane);
|
||||||
|
|
||||||
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);
|
|
||||||
if(found_screen_card)
|
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 true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user