mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-05-07 15:19:55 +09:00
Allow prime-run capture on laptop with external gpu when the iGPU
doesn't have any monitor to capture. Fix prime-run desktop portal capture broken (fallback to external texture). Fallback to external texture in kms capture.
This commit is contained in:
@@ -15,8 +15,7 @@
|
||||
typedef struct {
|
||||
gsr_capture_portal_params params;
|
||||
|
||||
unsigned int input_texture_id;
|
||||
unsigned int cursor_texture_id;
|
||||
gsr_texture_map texture_map;
|
||||
|
||||
gsr_dbus dbus;
|
||||
char *session_handle;
|
||||
@@ -38,14 +37,19 @@ static void gsr_capture_portal_cleanup_plane_fds(gsr_capture_portal *self) {
|
||||
}
|
||||
|
||||
static void gsr_capture_portal_stop(gsr_capture_portal *self) {
|
||||
if(self->input_texture_id) {
|
||||
self->params.egl->glDeleteTextures(1, &self->input_texture_id);
|
||||
self->input_texture_id = 0;
|
||||
if(self->texture_map.texture_id) {
|
||||
self->params.egl->glDeleteTextures(1, &self->texture_map.texture_id);
|
||||
self->texture_map.texture_id = 0;
|
||||
}
|
||||
|
||||
if(self->cursor_texture_id) {
|
||||
self->params.egl->glDeleteTextures(1, &self->cursor_texture_id);
|
||||
self->cursor_texture_id = 0;
|
||||
if(self->texture_map.external_texture_id) {
|
||||
self->params.egl->glDeleteTextures(1, &self->texture_map.external_texture_id);
|
||||
self->texture_map.external_texture_id = 0;
|
||||
}
|
||||
|
||||
if(self->texture_map.cursor_texture_id) {
|
||||
self->params.egl->glDeleteTextures(1, &self->texture_map.cursor_texture_id);
|
||||
self->texture_map.cursor_texture_id = 0;
|
||||
}
|
||||
|
||||
gsr_capture_portal_cleanup_plane_fds(self);
|
||||
@@ -61,16 +65,24 @@ static void gsr_capture_portal_stop(gsr_capture_portal *self) {
|
||||
}
|
||||
|
||||
static void gsr_capture_portal_create_input_textures(gsr_capture_portal *self) {
|
||||
self->params.egl->glGenTextures(1, &self->input_texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, self->input_texture_id);
|
||||
self->params.egl->glGenTextures(1, &self->texture_map.texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, self->texture_map.texture_id);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
self->params.egl->glGenTextures(1, &self->cursor_texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, self->cursor_texture_id);
|
||||
self->params.egl->glGenTextures(1, &self->texture_map.external_texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, self->texture_map.external_texture_id);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
|
||||
|
||||
self->params.egl->glGenTextures(1, &self->texture_map.cursor_texture_id);
|
||||
self->params.egl->glBindTexture(GL_TEXTURE_2D, self->texture_map.cursor_texture_id);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
self->params.egl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
@@ -224,7 +236,8 @@ static bool gsr_capture_portal_get_frame_dimensions(gsr_capture_portal *self) {
|
||||
|
||||
const double start_time = clock_get_monotonic_seconds();
|
||||
while(clock_get_monotonic_seconds() - start_time < 5.0) {
|
||||
if(gsr_pipewire_map_texture(&self->pipewire, self->input_texture_id, self->cursor_texture_id, ®ion, &cursor_region, self->plane_fds, &self->num_plane_fds)) {
|
||||
bool uses_external_image = false;
|
||||
if(gsr_pipewire_map_texture(&self->pipewire, self->texture_map, ®ion, &cursor_region, self->plane_fds, &self->num_plane_fds, &uses_external_image)) {
|
||||
gsr_capture_portal_cleanup_plane_fds(self);
|
||||
self->capture_size.x = region.width;
|
||||
self->capture_size.y = region.height;
|
||||
@@ -304,7 +317,8 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo
|
||||
/* TODO: Handle formats other than RGB(a) */
|
||||
gsr_pipewire_region region = {0, 0, 0, 0};
|
||||
gsr_pipewire_region cursor_region = {0, 0, 0, 0};
|
||||
if(gsr_pipewire_map_texture(&self->pipewire, self->input_texture_id, self->cursor_texture_id, ®ion, &cursor_region, self->plane_fds, &self->num_plane_fds)) {
|
||||
bool using_external_image = false;
|
||||
if(gsr_pipewire_map_texture(&self->pipewire, self->texture_map, ®ion, &cursor_region, self->plane_fds, &self->num_plane_fds, &using_external_image)) {
|
||||
if(region.width != self->capture_size.x || region.height != self->capture_size.y) {
|
||||
gsr_color_conversion_clear(color_conversion);
|
||||
self->capture_size.x = region.width;
|
||||
@@ -315,10 +329,10 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo
|
||||
const int target_x = max_int(0, frame->width / 2 - self->capture_size.x / 2);
|
||||
const int target_y = max_int(0, frame->height / 2 - self->capture_size.y / 2);
|
||||
|
||||
gsr_color_conversion_draw(color_conversion, self->input_texture_id,
|
||||
gsr_color_conversion_draw(color_conversion, using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id,
|
||||
(vec2i){target_x, target_y}, self->capture_size,
|
||||
(vec2i){region.x, region.y}, self->capture_size,
|
||||
0.0f, false);
|
||||
0.0f, using_external_image);
|
||||
|
||||
if(self->params.record_cursor) {
|
||||
const vec2i cursor_pos = {
|
||||
@@ -328,7 +342,7 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo
|
||||
|
||||
self->params.egl->glEnable(GL_SCISSOR_TEST);
|
||||
self->params.egl->glScissor(target_x, target_y, self->capture_size.x, self->capture_size.y);
|
||||
gsr_color_conversion_draw(color_conversion, self->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, cursor_region.height},
|
||||
(vec2i){0, 0}, (vec2i){cursor_region.width, cursor_region.height},
|
||||
0.0f, false);
|
||||
@@ -359,10 +373,10 @@ static gsr_source_color gsr_capture_portal_get_source_color(gsr_capture *cap) {
|
||||
return GSR_SOURCE_COLOR_RGB;
|
||||
}
|
||||
|
||||
// static bool gsr_capture_portal_uses_external_image(gsr_capture *cap) {
|
||||
// gsr_capture_portal *cap_portal = cap->priv;
|
||||
// return cap_portal->params.egl->gpu_info.vendor == GSR_GPU_VENDOR_NVIDIA;
|
||||
// }
|
||||
static bool gsr_capture_portal_uses_external_image(gsr_capture *cap) {
|
||||
(void)cap;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gsr_capture_portal_destroy(gsr_capture *cap, AVCodecContext *video_codec_context) {
|
||||
(void)video_codec_context;
|
||||
@@ -400,7 +414,7 @@ gsr_capture* gsr_capture_portal_create(const gsr_capture_portal_params *params)
|
||||
.capture = gsr_capture_portal_capture,
|
||||
.capture_end = gsr_capture_portal_capture_end,
|
||||
.get_source_color = gsr_capture_portal_get_source_color,
|
||||
.uses_external_image = NULL,
|
||||
.uses_external_image = gsr_capture_portal_uses_external_image,
|
||||
.destroy = gsr_capture_portal_destroy,
|
||||
.priv = cap_portal
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user