diff options
-rw-r--r-- | README.md | 6 | ||||
-rwxr-xr-x | build.sh | 5 | ||||
-rw-r--r-- | include/cursor.h | 30 | ||||
-rw-r--r-- | kms/server/kms_server.c | 2 | ||||
-rw-r--r-- | project.conf | 1 | ||||
-rw-r--r-- | src/cursor.c | 135 |
6 files changed, 7 insertions, 172 deletions
@@ -42,11 +42,11 @@ If you install GPU Screen Recorder flatpak, which is the gtk gui version then yo # Dependencies ## AMD -`libglvnd (which provides libgl and libegl), mesa, ffmpeg (libavcodec, libavformat, libavutil, libswresample, libavfilter), libx11, libxcomposite, libxrandr, libxfixes, libpulse, libva, libva-mesa-driver, libdrm, libcap, polkit (for pkexec), wayland-client`. +`libglvnd (which provides libgl and libegl), mesa, ffmpeg (libavcodec, libavformat, libavutil, libswresample, libavfilter), libx11, libxcomposite, libxrandr, libpulse, libva, libva-mesa-driver, libdrm, libcap, polkit (for pkexec), wayland-client`. ## Intel -`libglvnd (which provides libgl and libegl), mesa, ffmpeg (libavcodec, libavformat, libavutil, libswresample, libavfilter), libx11, libxcomposite, libxrandr, libxfixes, libpulse, libva, libva-intel-driver, libdrm, libcap, polkit (for pkexec), wayland-client`. +`libglvnd (which provides libgl and libegl), mesa, ffmpeg (libavcodec, libavformat, libavutil, libswresample, libavfilter), libx11, libxcomposite, libxrandr, libpulse, libva, libva-intel-driver, libdrm, libcap, polkit (for pkexec), wayland-client`. ## NVIDIA -`libglvnd (which provides libgl and libegl), ffmpeg (libavcodec, libavformat, libavutil, libswresample, libavfilter), libx11, libxcomposite, libxrandr, libxfixes, libpulse, cuda runtime (libcuda.so.1) (libnvidia-compute), nvenc (libnvidia-encode), libva, libdrm, libcap, polkit (for pkexec, only on wayland), wayland-client`. Additionally, you need to have `nvfbc (libnvidia-fbc1)` installed when using nvfbc and `xnvctrl (libxnvctrl0)` when using the `-oc` option. +`libglvnd (which provides libgl and libegl), ffmpeg (libavcodec, libavformat, libavutil, libswresample, libavfilter), libx11, libxcomposite, libxrandr, libpulse, cuda runtime (libcuda.so.1) (libnvidia-compute), nvenc (libnvidia-encode), libva, libdrm, libcap, polkit (for pkexec, only on wayland), wayland-client`. Additionally, you need to have `nvfbc (libnvidia-fbc1)` installed when using nvfbc and `xnvctrl (libxnvctrl0)` when using the `-oc` option. # How to use Run `gpu-screen-recorder --help` to see all options. @@ -25,7 +25,7 @@ build_gsr_kms_server() { } build_gsr() { - dependencies="libavcodec libavformat libavutil x11 xcomposite xrandr xfixes libpulse libswresample libavfilter libva libcap libdrm wayland-egl wayland-client" + dependencies="libavcodec libavformat libavutil x11 xcomposite xrandr libpulse libswresample libavfilter libva libcap libdrm wayland-egl wayland-client" includes="$(pkg-config --cflags $dependencies)" libs="$(pkg-config --libs $dependencies) -ldl -pthread -lm" $CC -c src/capture/capture.c $opts $includes @@ -42,14 +42,13 @@ build_gsr() { $CC -c src/window_texture.c $opts $includes $CC -c src/shader.c $opts $includes $CC -c src/color_conversion.c $opts $includes - $CC -c src/cursor.c $opts $includes $CC -c src/utils.c $opts $includes $CC -c src/library_loader.c $opts $includes $CC -c external/wlr-export-dmabuf-unstable-v1-protocol.c $opts $includes $CXX -c src/sound.cpp $opts $includes $CXX -c src/main.cpp $opts $includes $CXX -o gpu-screen-recorder capture.o nvfbc.o kms_client.o egl.o cuda.o xnvctrl.o overclock.o window_texture.o shader.o \ - color_conversion.o cursor.o utils.o library_loader.o xcomposite_cuda.o xcomposite_vaapi.o kms_vaapi.o kms_cuda.o wlr-export-dmabuf-unstable-v1-protocol.o sound.o main.o $libs $opts + color_conversion.o utils.o library_loader.o xcomposite_cuda.o xcomposite_vaapi.o kms_vaapi.o kms_cuda.o wlr-export-dmabuf-unstable-v1-protocol.o sound.o main.o $libs $opts } build_wayland_protocol diff --git a/include/cursor.h b/include/cursor.h deleted file mode 100644 index a189ec3..0000000 --- a/include/cursor.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef GSR_CURSOR_H -#define GSR_CURSOR_H - -#include "egl.h" -#include "vec2.h" - -#include <X11/Xlib.h> - -typedef struct { - gsr_egl *egl; - Display *display; - Window window; - int x_fixes_event_base; - - unsigned int texture_id; - vec2i size; - vec2i hotspot; - vec2i position; - - bool cursor_image_set; -} gsr_cursor; - -int gsr_cursor_init(gsr_cursor *self, gsr_egl *egl, Display *display); -void gsr_cursor_deinit(gsr_cursor *self); - -int gsr_cursor_change_window_target(gsr_cursor *self, Window window); -void gsr_cursor_update(gsr_cursor *self, XEvent *xev); -void gsr_cursor_tick(gsr_cursor *self); - -#endif /* GSR_CURSOR_H */ diff --git a/kms/server/kms_server.c b/kms/server/kms_server.c index 0ff0b03..a3b9687 100644 --- a/kms/server/kms_server.c +++ b/kms/server/kms_server.c @@ -262,6 +262,8 @@ static int kms_get_fb(gsr_drm *drm, gsr_kms_response *response, connector_to_crt response->fds[response->num_fds].modifier = drmfb->modifier; response->fds[response->num_fds].connector_id = get_connector_by_crtc_id(c2crtc_map, plane->crtc_id); response->fds[response->num_fds].is_cursor = is_cursor; + // TODO: This is not an accurate way to detect it. First of all, it always fails with multiple monitors + // on wayland as the drmfb always has multiple planes response->fds[response->num_fds].is_combined_plane = drmfb_has_multiple_handles(drmfb); if(is_cursor) { response->fds[response->num_fds].x = x; diff --git a/project.conf b/project.conf index 731f7c0..23092af 100644 --- a/project.conf +++ b/project.conf @@ -20,7 +20,6 @@ libswresample = ">=3" libavfilter = ">=5" libva = ">=1" libcap = ">=2" -xfixes = ">=2" libdrm = ">=2" wayland-egl = ">=15" wayland-client = ">=1" diff --git a/src/cursor.c b/src/cursor.c deleted file mode 100644 index 9212b55..0000000 --- a/src/cursor.c +++ /dev/null @@ -1,135 +0,0 @@ -#include "../include/cursor.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> - -#include <X11/extensions/Xfixes.h> - -static bool gsr_cursor_set_from_x11_cursor_image(gsr_cursor *self, XFixesCursorImage *x11_cursor_image) { - uint8_t *cursor_data = NULL; - uint8_t *out = NULL; - - if(!x11_cursor_image) - goto err; - - if(!x11_cursor_image->pixels) - goto err; - - self->hotspot.x = x11_cursor_image->xhot; - self->hotspot.y = x11_cursor_image->yhot; - self->egl->glBindTexture(GL_TEXTURE_2D, self->texture_id); - - self->size.x = x11_cursor_image->width; - self->size.y = x11_cursor_image->height; - const unsigned long *pixels = x11_cursor_image->pixels; - cursor_data = malloc(self->size.x * self->size.y * 4); - if(!cursor_data) - goto err; - out = cursor_data; - /* Un-premultiply alpha */ - for(int y = 0; y < self->size.y; ++y) { - for(int x = 0; x < self->size.x; ++x) { - uint32_t pixel = *pixels++; - uint8_t *in = (uint8_t*)&pixel; - uint8_t alpha = in[3]; - if(alpha == 0) - alpha = 1; - - *out++ = (unsigned)*in++ * 255/alpha; - *out++ = (unsigned)*in++ * 255/alpha; - *out++ = (unsigned)*in++ * 255/alpha; - *out++ = *in++; - } - } - - self->egl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, self->size.x, self->size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, cursor_data); - free(cursor_data); - - self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - self->egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - self->egl->glBindTexture(GL_TEXTURE_2D, 0); - XFree(x11_cursor_image); - return true; - - err: - self->egl->glBindTexture(GL_TEXTURE_2D, 0); - if(x11_cursor_image) - XFree(x11_cursor_image); - return false; -} - -int gsr_cursor_init(gsr_cursor *self, gsr_egl *egl, Display *display) { - int x_fixes_error_base = 0; - - assert(egl); - assert(display); - memset(self, 0, sizeof(*self)); - self->egl = egl; - self->display = display; - - self->x_fixes_event_base = 0; - if(!XFixesQueryExtension(self->display, &self->x_fixes_event_base, &x_fixes_error_base)) { - fprintf(stderr, "gsr error: gsr_cursor_init: your X11 server is missing the XFixes extension\n"); - gsr_cursor_deinit(self); - return -1; - } - - self->egl->glGenTextures(1, &self->texture_id); - return 0; -} - -void gsr_cursor_deinit(gsr_cursor *self) { - if(!self->egl) - return; - - if(self->texture_id) { - self->egl->glDeleteTextures(1, &self->texture_id); - self->texture_id = 0; - } - - if(self->window) { - XFixesSelectCursorInput(self->display, self->window, 0); - self->window = None; - } - - self->display = NULL; - self->egl = NULL; -} - -int gsr_cursor_change_window_target(gsr_cursor *self, Window window) { - if(self->window) - XFixesSelectCursorInput(self->display, self->window, 0); - - XFixesSelectCursorInput(self->display, window, XFixesDisplayCursorNotifyMask); - self->window = window; - self->cursor_image_set = false; - return 0; -} - -void gsr_cursor_update(gsr_cursor *self, XEvent *xev) { - if(xev->type == self->x_fixes_event_base + XFixesCursorNotify) { - XFixesCursorNotifyEvent *cursor_notify_event = (XFixesCursorNotifyEvent*)xev; - if(cursor_notify_event->subtype == XFixesDisplayCursorNotify && cursor_notify_event->window == self->window) { - self->cursor_image_set = true; - gsr_cursor_set_from_x11_cursor_image(self, XFixesGetCursorImage(self->display)); - } - } - - if(!self->cursor_image_set && self->window) { - self->cursor_image_set = true; - gsr_cursor_set_from_x11_cursor_image(self, XFixesGetCursorImage(self->display)); - } -} - -void gsr_cursor_tick(gsr_cursor *self) { - /* TODO: Use XInput2 instead. However that doesn't work when the pointer is grabbed. Maybe check for focused window change and XSelectInput PointerMask */ - Window dummy_window; - int dummy_i; - unsigned int dummy_u; - XQueryPointer(self->display, DefaultRootWindow(self->display), &dummy_window, &dummy_window, &dummy_i, &dummy_i, &self->position.x, &self->position.y, &dummy_u); -} |