mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-04-20 00:45:49 +09:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2290f0641c | ||
|
|
f9e93467b2 | ||
|
|
7d7f986668 | ||
|
|
1b957d5b40 | ||
|
|
8ad6a1f4cb | ||
|
|
0cf0a9abf5 | ||
|
|
bc58e382b7 |
@@ -88,7 +88,7 @@ These are the dependencies needed to build GPU Screen Recorder:
|
|||||||
* wayland (wayland-client, wayland-egl, wayland-scanner)
|
* wayland (wayland-client, wayland-egl, wayland-scanner)
|
||||||
|
|
||||||
## Runtime dependencies
|
## Runtime dependencies
|
||||||
* libglvnd (which provides libgl, libglx and libegl) is needed. Your system needs to support at least OpenGL ES 3.1
|
* libglvnd (which provides libgl, libglx and libegl) is needed. Your system needs to support at least OpenGL ES 3.0 (released in 2012)
|
||||||
|
|
||||||
There are also additional dependencies needed at runtime depending on your GPU vendor:
|
There are also additional dependencies needed at runtime depending on your GPU vendor:
|
||||||
|
|
||||||
@@ -98,7 +98,7 @@ There are also additional dependencies needed at runtime depending on your GPU v
|
|||||||
|
|
||||||
### Intel
|
### Intel
|
||||||
* mesa
|
* mesa
|
||||||
* vaapi (intel-media-driver/libva-intel-driver/linux-firmware, depending on which intel iGPU you have)
|
* vaapi (intel-media-driver/libva-intel-driver/linux-firmware-intel, depending on which intel iGPU you have)
|
||||||
|
|
||||||
### NVIDIA
|
### NVIDIA
|
||||||
* cuda runtime (libcuda.so.1) (libnvidia-compute)
|
* cuda runtime (libcuda.so.1) (libnvidia-compute)
|
||||||
|
|||||||
2
TODO
2
TODO
@@ -304,3 +304,5 @@ Allow medium, high, very_high and ultra quality for -bm cbr. If that is used the
|
|||||||
Maybe remove shader compute code. It doesn't seem necessary anymore now that glSwapBuffer/glFinish isn't used. dbus server isn't needed anymore either, the code can be moved back to the gpu screen recorder process.
|
Maybe remove shader compute code. It doesn't seem necessary anymore now that glSwapBuffer/glFinish isn't used. dbus server isn't needed anymore either, the code can be moved back to the gpu screen recorder process.
|
||||||
|
|
||||||
Add proper check if opengl functions are supported. dlsym for the symbol will return a no-op function if it's not supported, so it silently fails if used.
|
Add proper check if opengl functions are supported. dlsym for the symbol will return a no-op function if it's not supported, so it silently fails if used.
|
||||||
|
|
||||||
|
Colors are offset to bottom left by 1 pixel or so on steam deck in landscape mode.
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ typedef void(*__GLXextFuncPtr)(void);
|
|||||||
#define EGL_OPENGL_ES_API 0x30A0
|
#define EGL_OPENGL_ES_API 0x30A0
|
||||||
#define EGL_OPENGL_BIT 0x0008
|
#define EGL_OPENGL_BIT 0x0008
|
||||||
#define EGL_OPENGL_ES_BIT 0x0001
|
#define EGL_OPENGL_ES_BIT 0x0001
|
||||||
|
#define EGL_OPENGL_ES2_BIT 0x0004
|
||||||
|
#define EGL_OPENGL_ES3_BIT 0x00000040
|
||||||
#define EGL_NONE 0x3038
|
#define EGL_NONE 0x3038
|
||||||
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
#define EGL_CONTEXT_CLIENT_VERSION 0x3098
|
||||||
#define EGL_BACK_BUFFER 0x3084
|
#define EGL_BACK_BUFFER 0x3084
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include <spa/param/video/format.h>
|
#include <spa/param/video/format.h>
|
||||||
|
|
||||||
#define GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS 1024
|
#define GSR_PIPEWIRE_VIDEO_MAX_MODIFIERS 1024
|
||||||
#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 12
|
#define GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS 6
|
||||||
#define GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES 4
|
#define GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES 4
|
||||||
|
|
||||||
typedef struct gsr_egl gsr_egl;
|
typedef struct gsr_egl gsr_egl;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
project('gpu-screen-recorder', ['c', 'cpp'], version : '5.5.9', default_options : ['warning_level=2'])
|
project('gpu-screen-recorder', ['c', 'cpp'], version : '5.5.10', default_options : ['warning_level=2'])
|
||||||
|
|
||||||
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
|
add_project_arguments('-Wshadow', language : ['c', 'cpp'])
|
||||||
if get_option('buildtype') == 'debug'
|
if get_option('buildtype') == 'debug'
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "gpu-screen-recorder"
|
name = "gpu-screen-recorder"
|
||||||
type = "executable"
|
type = "executable"
|
||||||
version = "5.5.9"
|
version = "5.5.10"
|
||||||
platforms = ["posix"]
|
platforms = ["posix"]
|
||||||
|
|
||||||
[config]
|
[config]
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
#include <libavutil/mastering_display_metadata.h>
|
#include <libavutil/mastering_display_metadata.h>
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ typedef struct {
|
|||||||
vec2i capture_size;
|
vec2i capture_size;
|
||||||
gsr_pipewire_video_dmabuf_data dmabuf_data[GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES];
|
gsr_pipewire_video_dmabuf_data dmabuf_data[GSR_PIPEWIRE_VIDEO_DMABUF_MAX_PLANES];
|
||||||
int num_dmabuf_data;
|
int num_dmabuf_data;
|
||||||
|
|
||||||
|
gsr_pipewire_video_region region;
|
||||||
|
gsr_pipewire_video_region cursor_region;
|
||||||
|
uint32_t pipewire_fourcc;
|
||||||
|
uint64_t pipewire_modifiers;
|
||||||
|
bool using_external_image;
|
||||||
} gsr_capture_portal;
|
} gsr_capture_portal;
|
||||||
|
|
||||||
static void gsr_capture_portal_cleanup_plane_fds(gsr_capture_portal *self) {
|
static void gsr_capture_portal_cleanup_plane_fds(gsr_capture_portal *self) {
|
||||||
@@ -216,19 +222,13 @@ static int gsr_capture_portal_setup_dbus(gsr_capture_portal *self, int *pipewire
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool gsr_capture_portal_get_frame_dimensions(gsr_capture_portal *self) {
|
static bool gsr_capture_portal_get_frame_dimensions(gsr_capture_portal *self) {
|
||||||
gsr_pipewire_video_region region = {0, 0, 0, 0};
|
|
||||||
gsr_pipewire_video_region cursor_region = {0, 0, 0, 0};
|
|
||||||
fprintf(stderr, "gsr info: gsr_capture_portal_start: waiting for pipewire negotiation\n");
|
fprintf(stderr, "gsr info: gsr_capture_portal_start: waiting for pipewire negotiation\n");
|
||||||
|
|
||||||
const double start_time = clock_get_monotonic_seconds();
|
const double start_time = clock_get_monotonic_seconds();
|
||||||
while(clock_get_monotonic_seconds() - start_time < 5.0) {
|
while(clock_get_monotonic_seconds() - start_time < 5.0) {
|
||||||
bool uses_external_image = false;
|
if(gsr_pipewire_video_map_texture(&self->pipewire, self->texture_map, &self->region, &self->cursor_region, self->dmabuf_data, &self->num_dmabuf_data, &self->pipewire_fourcc, &self->pipewire_modifiers, &self->using_external_image)) {
|
||||||
uint32_t fourcc = 0;
|
self->capture_size.x = self->region.width;
|
||||||
uint64_t modifiers = 0;
|
self->capture_size.y = self->region.height;
|
||||||
if(gsr_pipewire_video_map_texture(&self->pipewire, self->texture_map, ®ion, &cursor_region, self->dmabuf_data, &self->num_dmabuf_data, &fourcc, &modifiers, &uses_external_image)) {
|
|
||||||
gsr_capture_portal_cleanup_plane_fds(self);
|
|
||||||
self->capture_size.x = region.width;
|
|
||||||
self->capture_size.y = region.height;
|
|
||||||
fprintf(stderr, "gsr info: gsr_capture_portal_start: pipewire negotiation finished\n");
|
fprintf(stderr, "gsr info: gsr_capture_portal_start: pipewire negotiation finished\n");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -300,20 +300,17 @@ static int gsr_capture_portal_capture(gsr_capture *cap, gsr_capture_metadata *ca
|
|||||||
(void)color_conversion;
|
(void)color_conversion;
|
||||||
gsr_capture_portal *self = cap->priv;
|
gsr_capture_portal *self = cap->priv;
|
||||||
|
|
||||||
/* TODO: Handle formats other than RGB(a) */
|
/* TODO: Handle formats other than RGB(A) */
|
||||||
gsr_pipewire_video_region region = {0, 0, 0, 0};
|
if(self->num_dmabuf_data == 0) {
|
||||||
gsr_pipewire_video_region cursor_region = {0, 0, 0, 0};
|
if(gsr_pipewire_video_map_texture(&self->pipewire, self->texture_map, &self->region, &self->cursor_region, self->dmabuf_data, &self->num_dmabuf_data, &self->pipewire_fourcc, &self->pipewire_modifiers, &self->using_external_image)) {
|
||||||
uint32_t pipewire_fourcc = 0;
|
if(self->region.width != self->capture_size.x || self->region.height != self->capture_size.y) {
|
||||||
uint64_t pipewire_modifiers = 0;
|
self->capture_size.x = self->region.width;
|
||||||
bool using_external_image = false;
|
self->capture_size.y = self->region.height;
|
||||||
if(gsr_pipewire_video_map_texture(&self->pipewire, self->texture_map, ®ion, &cursor_region, self->dmabuf_data, &self->num_dmabuf_data, &pipewire_fourcc, &pipewire_modifiers, &using_external_image)) {
|
gsr_color_conversion_clear(color_conversion);
|
||||||
if(region.width != self->capture_size.x || region.height != self->capture_size.y) {
|
}
|
||||||
self->capture_size.x = region.width;
|
} else {
|
||||||
self->capture_size.y = region.height;
|
return -1;
|
||||||
gsr_color_conversion_clear(color_conversion);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool is_scaled = self->params.output_resolution.x > 0 && self->params.output_resolution.y > 0;
|
const bool is_scaled = self->params.output_resolution.x > 0 && self->params.output_resolution.y > 0;
|
||||||
@@ -327,27 +324,27 @@ static int gsr_capture_portal_capture(gsr_capture *cap, gsr_capture_metadata *ca
|
|||||||
|
|
||||||
// TODO: Handle region crop
|
// TODO: Handle region crop
|
||||||
|
|
||||||
gsr_color_conversion_draw(color_conversion, using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id,
|
gsr_color_conversion_draw(color_conversion, self->using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id,
|
||||||
target_pos, output_size,
|
target_pos, output_size,
|
||||||
(vec2i){region.x, region.y}, self->capture_size, self->capture_size,
|
(vec2i){self->region.x, self->region.y}, self->capture_size, self->capture_size,
|
||||||
GSR_ROT_0, GSR_SOURCE_COLOR_RGB, using_external_image, false);
|
GSR_ROT_0, GSR_SOURCE_COLOR_RGB, self->using_external_image, false);
|
||||||
|
|
||||||
if(self->params.record_cursor && self->texture_map.cursor_texture_id > 0 && cursor_region.width > 0) {
|
if(self->params.record_cursor && self->texture_map.cursor_texture_id > 0 && self->cursor_region.width > 0) {
|
||||||
const vec2d scale = {
|
const vec2d scale = {
|
||||||
self->capture_size.x == 0 ? 0 : (double)output_size.x / (double)self->capture_size.x,
|
self->capture_size.x == 0 ? 0 : (double)output_size.x / (double)self->capture_size.x,
|
||||||
self->capture_size.y == 0 ? 0 : (double)output_size.y / (double)self->capture_size.y
|
self->capture_size.y == 0 ? 0 : (double)output_size.y / (double)self->capture_size.y
|
||||||
};
|
};
|
||||||
|
|
||||||
const vec2i cursor_pos = {
|
const vec2i cursor_pos = {
|
||||||
target_pos.x + (cursor_region.x * scale.x),
|
target_pos.x + (self->cursor_region.x * scale.x),
|
||||||
target_pos.y + (cursor_region.y * scale.y)
|
target_pos.y + (self->cursor_region.y * scale.y)
|
||||||
};
|
};
|
||||||
|
|
||||||
self->params.egl->glEnable(GL_SCISSOR_TEST);
|
self->params.egl->glEnable(GL_SCISSOR_TEST);
|
||||||
self->params.egl->glScissor(target_pos.x, target_pos.y, output_size.x, output_size.y);
|
self->params.egl->glScissor(target_pos.x, target_pos.y, output_size.x, output_size.y);
|
||||||
gsr_color_conversion_draw(color_conversion, self->texture_map.cursor_texture_id,
|
gsr_color_conversion_draw(color_conversion, self->texture_map.cursor_texture_id,
|
||||||
(vec2i){cursor_pos.x, cursor_pos.y}, (vec2i){cursor_region.width * scale.x, cursor_region.height * scale.y},
|
(vec2i){cursor_pos.x, cursor_pos.y}, (vec2i){self->cursor_region.width * scale.x, self->cursor_region.height * scale.y},
|
||||||
(vec2i){0, 0}, (vec2i){cursor_region.width, cursor_region.height}, (vec2i){cursor_region.width, cursor_region.height},
|
(vec2i){0, 0}, (vec2i){self->cursor_region.width, self->cursor_region.height}, (vec2i){self->cursor_region.width, self->cursor_region.height},
|
||||||
GSR_ROT_0, GSR_SOURCE_COLOR_RGB, false, true);
|
GSR_ROT_0, GSR_SOURCE_COLOR_RGB, false, true);
|
||||||
self->params.egl->glDisable(GL_SCISSOR_TEST);
|
self->params.egl->glDisable(GL_SCISSOR_TEST);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ static bool gsr_egl_create_window(gsr_egl *self) {
|
|||||||
|
|
||||||
const int32_t attr[] = {
|
const int32_t attr[] = {
|
||||||
EGL_BUFFER_SIZE, 24,
|
EGL_BUFFER_SIZE, 24,
|
||||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
|
||||||
EGL_NONE, EGL_NONE
|
EGL_NONE, EGL_NONE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <spa/param/video/format-utils.h>
|
#include <spa/param/video/format-utils.h>
|
||||||
#include <spa/debug/types.h>
|
#include <spa/debug/types.h>
|
||||||
|
|
||||||
#include <libdrm/drm_fourcc.h>
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -346,17 +346,17 @@ static int64_t spa_video_format_to_drm_format(const enum spa_video_format format
|
|||||||
switch(format) {
|
switch(format) {
|
||||||
case SPA_VIDEO_FORMAT_RGBx: return DRM_FORMAT_XBGR8888;
|
case SPA_VIDEO_FORMAT_RGBx: return DRM_FORMAT_XBGR8888;
|
||||||
case SPA_VIDEO_FORMAT_BGRx: return DRM_FORMAT_XRGB8888;
|
case SPA_VIDEO_FORMAT_BGRx: return DRM_FORMAT_XRGB8888;
|
||||||
case SPA_VIDEO_FORMAT_RGBA: return DRM_FORMAT_ABGR8888;
|
// case SPA_VIDEO_FORMAT_RGBA: return DRM_FORMAT_ABGR8888;
|
||||||
case SPA_VIDEO_FORMAT_BGRA: return DRM_FORMAT_ARGB8888;
|
//case SPA_VIDEO_FORMAT_BGRA: return DRM_FORMAT_ARGB8888;
|
||||||
case SPA_VIDEO_FORMAT_RGB: return DRM_FORMAT_XBGR8888;
|
case SPA_VIDEO_FORMAT_RGB: return DRM_FORMAT_XBGR8888;
|
||||||
case SPA_VIDEO_FORMAT_BGR: return DRM_FORMAT_XRGB8888;
|
case SPA_VIDEO_FORMAT_BGR: return DRM_FORMAT_XRGB8888;
|
||||||
case SPA_VIDEO_FORMAT_ARGB: return DRM_FORMAT_XRGB8888;
|
//case SPA_VIDEO_FORMAT_ARGB: return DRM_FORMAT_XRGB8888;
|
||||||
case SPA_VIDEO_FORMAT_ABGR: return DRM_FORMAT_XRGB8888;
|
//case SPA_VIDEO_FORMAT_ABGR: return DRM_FORMAT_XRGB8888;
|
||||||
#if PW_CHECK_VERSION(0, 3, 41)
|
#if PW_CHECK_VERSION(0, 3, 41)
|
||||||
case SPA_VIDEO_FORMAT_xRGB_210LE: return DRM_FORMAT_XRGB2101010;
|
case SPA_VIDEO_FORMAT_xRGB_210LE: return DRM_FORMAT_XRGB2101010;
|
||||||
case SPA_VIDEO_FORMAT_xBGR_210LE: return DRM_FORMAT_XBGR2101010;
|
case SPA_VIDEO_FORMAT_xBGR_210LE: return DRM_FORMAT_XBGR2101010;
|
||||||
case SPA_VIDEO_FORMAT_ARGB_210LE: return DRM_FORMAT_ARGB2101010;
|
// case SPA_VIDEO_FORMAT_ARGB_210LE: return DRM_FORMAT_ARGB2101010;
|
||||||
case SPA_VIDEO_FORMAT_ABGR_210LE: return DRM_FORMAT_ABGR2101010;
|
// case SPA_VIDEO_FORMAT_ABGR_210LE: return DRM_FORMAT_ABGR2101010;
|
||||||
#endif
|
#endif
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
@@ -366,23 +366,23 @@ static int64_t spa_video_format_to_drm_format(const enum spa_video_format format
|
|||||||
#if PW_CHECK_VERSION(0, 3, 41)
|
#if PW_CHECK_VERSION(0, 3, 41)
|
||||||
#define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS
|
#define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS
|
||||||
#else
|
#else
|
||||||
#define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS 8
|
#define GSR_PIPEWIRE_VIDEO_NUM_VIDEO_FORMATS 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const enum spa_video_format video_formats[GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS] = {
|
static const enum spa_video_format video_formats[GSR_PIPEWIRE_VIDEO_MAX_VIDEO_FORMATS] = {
|
||||||
SPA_VIDEO_FORMAT_BGRA,
|
// SPA_VIDEO_FORMAT_BGRA,
|
||||||
SPA_VIDEO_FORMAT_BGRx,
|
SPA_VIDEO_FORMAT_BGRx,
|
||||||
SPA_VIDEO_FORMAT_BGR,
|
SPA_VIDEO_FORMAT_BGR,
|
||||||
SPA_VIDEO_FORMAT_RGBx,
|
SPA_VIDEO_FORMAT_RGBx,
|
||||||
SPA_VIDEO_FORMAT_RGBA,
|
// SPA_VIDEO_FORMAT_RGBA,
|
||||||
SPA_VIDEO_FORMAT_RGB,
|
SPA_VIDEO_FORMAT_RGB,
|
||||||
SPA_VIDEO_FORMAT_ARGB,
|
// SPA_VIDEO_FORMAT_ARGB,
|
||||||
SPA_VIDEO_FORMAT_ABGR,
|
// SPA_VIDEO_FORMAT_ABGR,
|
||||||
#if PW_CHECK_VERSION(0, 3, 41)
|
#if PW_CHECK_VERSION(0, 3, 41)
|
||||||
SPA_VIDEO_FORMAT_xRGB_210LE,
|
SPA_VIDEO_FORMAT_xRGB_210LE,
|
||||||
SPA_VIDEO_FORMAT_xBGR_210LE,
|
SPA_VIDEO_FORMAT_xBGR_210LE,
|
||||||
SPA_VIDEO_FORMAT_ARGB_210LE,
|
// SPA_VIDEO_FORMAT_ARGB_210LE,
|
||||||
SPA_VIDEO_FORMAT_ABGR_210LE
|
// SPA_VIDEO_FORMAT_ABGR_210LE
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user