From 85d59ea2c8c8e64e55247b967d1469ad92e63e6b Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 15 Aug 2024 11:13:49 +0200 Subject: HACK: portal: copy external image to internal image before render. Dont stop screencast when paused as that stops recording when window is resized --- src/capture/portal.c | 40 ++++++++++++++++++++++++++++++---------- src/pipewire.c | 11 ----------- 2 files changed, 30 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/capture/portal.c b/src/capture/portal.c index 2e34101..5d5acd7 100644 --- a/src/capture/portal.c +++ b/src/capture/portal.c @@ -16,6 +16,7 @@ typedef struct { gsr_capture_portal_params params; gsr_texture_map texture_map; + unsigned int external_intermediate_texture; gsr_dbus dbus; char *session_handle; @@ -47,6 +48,11 @@ static void gsr_capture_portal_stop(gsr_capture_portal *self) { self->texture_map.external_texture_id = 0; } + if(self->external_intermediate_texture) { + self->params.egl->glDeleteTextures(1, &self->external_intermediate_texture); + self->external_intermediate_texture = 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; @@ -318,21 +324,42 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo gsr_pipewire_region region = {0, 0, 0, 0}; gsr_pipewire_region cursor_region = {0, 0, 0, 0}; bool using_external_image = false; + bool resized = 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; self->capture_size.y = region.height; + resized = true; } } + + if(using_external_image && (self->external_intermediate_texture == 0 || resized)) { + if(self->external_intermediate_texture == 0) + self->params.egl->glGenTextures(1, &self->external_intermediate_texture); + self->params.egl->glBindTexture(GL_TEXTURE_2D, self->external_intermediate_texture); + self->params.egl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, self->capture_size.x, self->capture_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + 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); + } + + /* The image glitches a lot unless this is done. TODO: Find a proper solution */ + if(using_external_image) { + self->params.egl->glCopyImageSubData(self->texture_map.external_texture_id, GL_TEXTURE_EXTERNAL_OES, 0, 0, 0, 0, + self->external_intermediate_texture, GL_TEXTURE_2D, 0, 0, 0, 0, + self->capture_size.x, self->capture_size.y, 1); + } 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, using_external_image ? self->texture_map.external_texture_id : self->texture_map.texture_id, + gsr_color_conversion_draw(color_conversion, using_external_image ? self->external_intermediate_texture : self->texture_map.texture_id, (vec2i){target_x, target_y}, self->capture_size, (vec2i){region.x, region.y}, self->capture_size, - 0.0f, using_external_image); + 0.0f, false); if(self->params.record_cursor) { const vec2i cursor_pos = { @@ -355,13 +382,6 @@ static int gsr_capture_portal_capture(gsr_capture *cap, AVFrame *frame, gsr_colo return 0; } -static bool gsr_capture_portal_should_stop(gsr_capture *cap, bool *err) { - gsr_capture_portal *self = cap->priv; - if(err) - *err = false; - return gsr_pipewire_recording_stopped(&self->pipewire); -} - static void gsr_capture_portal_capture_end(gsr_capture *cap, AVFrame *frame) { (void)frame; gsr_capture_portal *self = cap->priv; @@ -410,7 +430,7 @@ gsr_capture* gsr_capture_portal_create(const gsr_capture_portal_params *params) *cap = (gsr_capture) { .start = gsr_capture_portal_start, .tick = NULL, - .should_stop = gsr_capture_portal_should_stop, + .should_stop = NULL, .capture = gsr_capture_portal_capture, .capture_end = gsr_capture_portal_capture_end, .get_source_color = gsr_capture_portal_get_source_color, diff --git a/src/pipewire.c b/src/pipewire.c index 03e59f4..5c38392 100644 --- a/src/pipewire.c +++ b/src/pipewire.c @@ -254,13 +254,6 @@ static void on_param_changed_cb(void *user_data, uint32_t id, const struct spa_p static void on_state_changed_cb(void *user_data, enum pw_stream_state old, enum pw_stream_state state, const char *error) { (void)old; gsr_pipewire *self = user_data; - if(state == PW_STREAM_STATE_STREAMING) - self->started = true; - - if(self->started && state == PW_STREAM_STATE_PAUSED) { - self->started = false; - self->stopped = true; - } fprintf(stderr, "gsr info: pipewire: stream %p state: \"%s\" (error: %s)\n", (void*)self->stream, pw_stream_state_as_string(state), @@ -740,7 +733,3 @@ bool gsr_pipewire_map_texture(gsr_pipewire *self, gsr_texture_map texture_map, g pthread_mutex_unlock(&self->mutex); return true; } - -bool gsr_pipewire_recording_stopped(gsr_pipewire *self) { - return self->stopped; -} -- cgit v1.2.3