diff --git a/src/stream-chooser/outputwidget.cpp b/src/stream-chooser/outputwidget.cpp index 8714132b..306809e4 100644 --- a/src/stream-chooser/outputwidget.cpp +++ b/src/stream-chooser/outputwidget.cpp @@ -23,22 +23,24 @@ static void frame_handle_presentation_time(void*, {} static void frame_handle_ready(void *data, - struct ext_image_copy_capture_frame_v1*) + struct ext_image_copy_capture_frame_v1 *frame) { WayfireChooserOutput *output = (WayfireChooserOutput*)data; + output->buffer_ready(); - output->frame_in_flight = false; + + ext_image_copy_capture_frame_v1_destroy(frame); + output->frame = nullptr; } static void frame_handle_failed(void *data, - struct ext_image_copy_capture_frame_v1 *handle, + struct ext_image_copy_capture_frame_v1 *frame, uint32_t reason) { WayfireChooserOutput *output = (WayfireChooserOutput*)data; - std::cerr << "Failed to copy frame because reason: " << reason << std::endl; - ext_image_copy_capture_frame_v1_destroy(handle); + + ext_image_copy_capture_frame_v1_destroy(frame); output->frame = nullptr; - output->frame_in_flight = false; } static const struct ext_image_copy_capture_frame_v1_listener frame_listener = { @@ -94,23 +96,6 @@ static const struct ext_image_copy_capture_session_v1_listener recording_session .stopped = session_handle_stopped, }; -static void dmabuf_created(void *data, struct zwp_linux_buffer_params_v1*, - struct wl_buffer *wl_buffer) -{ - auto output = (WayfireChooserOutput*)data; - output->buffer->buffer = wl_buffer; -} - -static void dmabuf_failed(void*, struct zwp_linux_buffer_params_v1*) -{ - std::cerr << "Failed to create dmabuf" << std::endl; -} - -static const struct zwp_linux_buffer_params_v1_listener params_listener = { - .created = dmabuf_created, - .failed = dmabuf_failed, -}; - static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, WayfireChooserOutput *output) { auto format = (output->current_buffer_format == WL_SHM_FORMAT_XRGB8888) ? @@ -118,12 +103,24 @@ static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, WayfireCh auto buffer = output->buffer; + if (buffer->gbm_fd > 0) + { + close(buffer->gbm_fd); + buffer->gbm_fd = -1; + } + if (buffer->bo) { gbm_bo_destroy(buffer->bo); buffer->bo = nullptr; } + if (buffer->buffer) + { + wl_buffer_destroy(buffer->buffer); + buffer->buffer = nullptr; + } + if (buffer->params) { zwp_linux_buffer_params_v1_destroy(buffer->params); @@ -154,14 +151,14 @@ static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, WayfireCh buffer->params = zwp_linux_dmabuf_v1_create_params(WayfireStreamChooserApp::getInstance().dmabuf); uint64_t mod = gbm_bo_get_modifier(buffer->bo); + buffer->gbm_fd = gbm_bo_get_fd(buffer->bo); zwp_linux_buffer_params_v1_add(buffer->params, - gbm_bo_get_fd(buffer->bo), 0, + buffer->gbm_fd, 0, gbm_bo_get_offset(buffer->bo, 0), gbm_bo_get_stride(buffer->bo), mod >> 32, mod & 0xffffffff); - zwp_linux_buffer_params_v1_add_listener(buffer->params, ¶ms_listener, output); - zwp_linux_buffer_params_v1_create(buffer->params, w, h, format, 0); + buffer->buffer = zwp_linux_buffer_params_v1_create_immed(buffer->params, w, h, format, 0); } void WayfireChooserOutput::start_output_source_ssession() @@ -294,9 +291,9 @@ WayfireChooserOutput::~WayfireChooserOutput() ext_image_copy_capture_session_v1_destroy(recording_session); } - if (buffer->buffer) + if (buffer->gbm_fd > 0) { - wl_buffer_destroy(buffer->buffer); + close(buffer->gbm_fd); } if (buffer->bo) @@ -304,6 +301,11 @@ WayfireChooserOutput::~WayfireChooserOutput() gbm_bo_destroy(buffer->bo); } + if (buffer->buffer) + { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->params) { zwp_linux_buffer_params_v1_destroy(buffer->params); @@ -355,11 +357,6 @@ void WayfireChooserOutput::frame_request() return; } - if (frame_in_flight) - { - return; - } - if (frame) { ext_image_copy_capture_frame_v1_destroy(frame); @@ -373,7 +370,6 @@ void WayfireChooserOutput::frame_request() ext_image_copy_capture_frame_v1_attach_buffer(buffer->frame, buffer->buffer); ext_image_copy_capture_frame_v1_damage_buffer(buffer->frame, 0, 0, buffer->width, buffer->height); ext_image_copy_capture_frame_v1_capture(buffer->frame); - frame_in_flight = true; } void WayfireChooserOutput::buffer_ready() @@ -399,10 +395,10 @@ void WayfireChooserOutput::buffer_ready() std::shared_ptr bytes = 0; size_t size = stride * buffer->height; bytes = Glib::Bytes::create((unsigned char*)data, size); + gbm_bo_unmap(buffer->bo, map_data); if (!bytes) { - gbm_bo_unmap(buffer->bo, map_data); return; } @@ -416,6 +412,4 @@ void WayfireChooserOutput::buffer_ready() auto texture = builder->build(); contents.set_paintable(texture); - - gbm_bo_unmap(buffer->bo, map_data); } diff --git a/src/stream-chooser/outputwidget.hpp b/src/stream-chooser/outputwidget.hpp index 49c92d4d..d232f038 100644 --- a/src/stream-chooser/outputwidget.hpp +++ b/src/stream-chooser/outputwidget.hpp @@ -13,6 +13,7 @@ struct output_buffer int height = 0; int stride = 0; gbm_bo *bo = nullptr; + int gbm_fd = -1; wl_buffer *buffer = nullptr; zwp_linux_buffer_params_v1 *params = nullptr; ext_image_copy_capture_frame_v1 *frame = NULL; @@ -38,7 +39,6 @@ class WayfireChooserOutput : public Gtk::Box ext_image_copy_capture_session_v1 *recording_session = NULL; std::shared_ptr buffer = nullptr; ext_image_copy_capture_frame_v1 *frame = NULL; - bool frame_in_flight = false; void print(); void frame_request(); void buffer_ready(); diff --git a/src/stream-chooser/stream-chooser.cpp b/src/stream-chooser/stream-chooser.cpp index 38f36ad6..a2cc5649 100644 --- a/src/stream-chooser/stream-chooser.cpp +++ b/src/stream-chooser/stream-chooser.cpp @@ -120,7 +120,6 @@ static void registry_add_object(void *data, wl_registry *registry, uint32_t name wl_registry_bind(registry, name, &ext_foreign_toplevel_list_v1_interface, version); - WayfireStreamChooserApp::getInstance().has_foreign_toplevel_list = true; WayfireStreamChooserApp::getInstance().set_toplevel_list(list); ext_foreign_toplevel_list_v1_add_listener(list, &toplevel_list_v1_impl, NULL); @@ -128,14 +127,12 @@ static void registry_add_object(void *data, wl_registry *registry, uint32_t name { auto manager = (ext_image_copy_capture_manager_v1*)wl_registry_bind(registry, name, &ext_image_copy_capture_manager_v1_interface, version); - WayfireStreamChooserApp::getInstance().has_image_copy_capture = true; WayfireStreamChooserApp::getInstance().set_copy_capture_manager(manager); } else if (strcmp(interface, ext_foreign_toplevel_image_capture_source_manager_v1_interface.name) == 0) { auto toplevel_capture_manager = (ext_foreign_toplevel_image_capture_source_manager_v1*)wl_registry_bind(registry, name, &ext_foreign_toplevel_image_capture_source_manager_v1_interface, version); - WayfireStreamChooserApp::getInstance().has_image_capture_source = true; WayfireStreamChooserApp::getInstance().set_toplevel_capture_manager(toplevel_capture_manager); } else if (strcmp(interface, ext_output_image_capture_source_manager_v1_interface.name) == 0) { @@ -281,24 +278,45 @@ void WayfireStreamChooserApp::activate() wl_display_roundtrip(display); wl_registry_destroy(registry); - if (!has_image_copy_capture) + bool toplevel_capture = true; + bool output_capture = true; + if (!this->manager) { std::cerr << "Compositor has not advertised ext-image-copy-capture-v1" << std::endl; + toplevel_capture = false; } - if (!has_foreign_toplevel_list) + if (!this->list) { std::cerr << "Compositor has not advertised ext-foreign-toplevel-list-v1" << std::endl; + toplevel_capture = false; } - if (!has_image_capture_source) + if (!this->output_capture_manager) { std::cerr << "Compositor has not advertised ext-image-capture-source-v1" << std::endl; + output_capture = false; } - window_label.set_sensitive(false); - window_label.set_tooltip_text("This compositor does not currently support sharing individual windows"); - notebook.set_current_page(1); + if (!this->toplevel_capture_manager) + { + std::cerr << "Compositor has not advertised ext-foreign-toplevel-image-capture-source-v1" << + std::endl; + toplevel_capture = false; + } + + if (!toplevel_capture) + { + if (!output_capture) + { + std::cerr << "No capture protocols supported, nothing to do." << std::endl; + exit(EXIT_FAILURE); + } + + window_label.set_sensitive(false); + window_label.set_tooltip_text("This compositor does not currently support sharing individual windows"); + notebook.set_current_page(1); + } /* Get output list */ auto gtkdisplay = Gdk::Display::get_default(); @@ -357,7 +375,6 @@ void WayfireStreamChooserApp::activate() window.present(); } -static bool first_toplevel = true; void WayfireStreamChooserApp::add_toplevel(ext_foreign_toplevel_handle_v1 *handle) { toplevels.emplace(handle, new WayfireChooserTopLevel(handle)); @@ -367,14 +384,6 @@ void WayfireStreamChooserApp::add_toplevel(ext_foreign_toplevel_handle_v1 *handl auto child = window_list.get_child_at_index(0); window_list.select_child(*child); } - - window_label.set_sensitive(true); - window_label.set_tooltip_text(""); - if (first_toplevel) - { - first_toplevel = false; - notebook.set_current_page(0); - } } void WayfireStreamChooserApp::remove_toplevel(WayfireChooserTopLevel *toplevel) diff --git a/src/stream-chooser/stream-chooser.hpp b/src/stream-chooser/stream-chooser.hpp index bb2b4e69..3b3801fa 100644 --- a/src/stream-chooser/stream-chooser.hpp +++ b/src/stream-chooser/stream-chooser.hpp @@ -34,9 +34,6 @@ class WayfireStreamChooserApp : public Gtk::Application public: Gtk::Notebook notebook; Gtk::FlowBox window_list, screen_list; - bool has_foreign_toplevel_list = false; - bool has_image_copy_capture = false; - bool has_image_capture_source = false; std::string drm_device_name; int drm_fd = -1; gbm_device *gbm_device_ptr = nullptr; diff --git a/src/stream-chooser/toplevelwidget.cpp b/src/stream-chooser/toplevelwidget.cpp index 875d27eb..380744e2 100644 --- a/src/stream-chooser/toplevelwidget.cpp +++ b/src/stream-chooser/toplevelwidget.cpp @@ -123,22 +123,24 @@ static void frame_handle_presentation_time(void*, {} static void frame_handle_ready(void *data, - struct ext_image_copy_capture_frame_v1*) + struct ext_image_copy_capture_frame_v1 *frame) { WayfireChooserTopLevel *toplevel = (WayfireChooserTopLevel*)data; + toplevel->buffer_ready(); - toplevel->frame_in_flight = false; + + ext_image_copy_capture_frame_v1_destroy(frame); + toplevel->frame = nullptr; } static void frame_handle_failed(void *data, - struct ext_image_copy_capture_frame_v1 *handle, + struct ext_image_copy_capture_frame_v1 *frame, uint32_t reason) { WayfireChooserTopLevel *toplevel = (WayfireChooserTopLevel*)data; - std::cerr << "Failed to copy frame because reason: " << reason << std::endl; - ext_image_copy_capture_frame_v1_destroy(handle); + + ext_image_copy_capture_frame_v1_destroy(frame); toplevel->frame = nullptr; - toplevel->frame_in_flight = false; } static const struct ext_image_copy_capture_frame_v1_listener frame_listener = { @@ -149,23 +151,6 @@ static const struct ext_image_copy_capture_frame_v1_listener frame_listener = { .failed = frame_handle_failed, }; -static void dmabuf_created(void *data, struct zwp_linux_buffer_params_v1*, - struct wl_buffer *wl_buffer) -{ - auto toplevel = (WayfireChooserTopLevel*)data; - toplevel->buffer->buffer = wl_buffer; -} - -static void dmabuf_failed(void*, struct zwp_linux_buffer_params_v1*) -{ - std::cerr << "Failed to create dmabuf" << std::endl; -} - -static const struct zwp_linux_buffer_params_v1_listener params_listener = { - .created = dmabuf_created, - .failed = dmabuf_failed, -}; - static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, WayfireChooserTopLevel *toplevel) { auto format = (toplevel->current_buffer_format == WL_SHM_FORMAT_XRGB8888) ? @@ -173,12 +158,24 @@ static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, WayfireCh auto buffer = toplevel->buffer; + if (buffer->gbm_fd > 0) + { + close(buffer->gbm_fd); + buffer->gbm_fd = -1; + } + if (buffer->bo) { gbm_bo_destroy(buffer->bo); buffer->bo = nullptr; } + if (buffer->buffer) + { + wl_buffer_destroy(buffer->buffer); + buffer->buffer = nullptr; + } + if (buffer->params) { zwp_linux_buffer_params_v1_destroy(buffer->params); @@ -209,14 +206,14 @@ static void frame_handle_linux_dmabuf(uint32_t width, uint32_t height, WayfireCh buffer->params = zwp_linux_dmabuf_v1_create_params(WayfireStreamChooserApp::getInstance().dmabuf); uint64_t mod = gbm_bo_get_modifier(buffer->bo); + buffer->gbm_fd = gbm_bo_get_fd(buffer->bo); zwp_linux_buffer_params_v1_add(buffer->params, - gbm_bo_get_fd(buffer->bo), 0, + buffer->gbm_fd, 0, gbm_bo_get_offset(buffer->bo, 0), gbm_bo_get_stride(buffer->bo), mod >> 32, mod & 0xffffffff); - zwp_linux_buffer_params_v1_add_listener(buffer->params, ¶ms_listener, toplevel); - zwp_linux_buffer_params_v1_create(buffer->params, w, h, format, 0); + buffer->buffer = zwp_linux_buffer_params_v1_create_immed(buffer->params, w, h, format, 0); } void WayfireChooserTopLevel::start_toplevel_source_ssession() @@ -265,11 +262,6 @@ void WayfireChooserTopLevel::frame_request() return; } - if (frame_in_flight) - { - return; - } - if (frame) { ext_image_copy_capture_frame_v1_destroy(frame); @@ -283,7 +275,6 @@ void WayfireChooserTopLevel::frame_request() ext_image_copy_capture_frame_v1_attach_buffer(buffer->frame, buffer->buffer); ext_image_copy_capture_frame_v1_damage_buffer(buffer->frame, 0, 0, buffer->width, buffer->height); ext_image_copy_capture_frame_v1_capture(buffer->frame); - frame_in_flight = true; } void WayfireChooserTopLevel::buffer_ready() @@ -309,10 +300,10 @@ void WayfireChooserTopLevel::buffer_ready() std::shared_ptr bytes = 0; size_t size = stride * buffer->height; bytes = Glib::Bytes::create((unsigned char*)data, size); + gbm_bo_unmap(buffer->bo, map_data); if (!bytes) { - gbm_bo_unmap(buffer->bo, map_data); return; } @@ -326,8 +317,6 @@ void WayfireChooserTopLevel::buffer_ready() auto texture = builder->build(); screenshot.set_paintable(texture); - - gbm_bo_unmap(buffer->bo, map_data); } void WayfireChooserTopLevel::stream() @@ -486,9 +475,9 @@ WayfireChooserTopLevel::~WayfireChooserTopLevel() ext_image_copy_capture_session_v1_destroy(recording_session); } - if (buffer->buffer) + if (buffer->gbm_fd > 0) { - wl_buffer_destroy(buffer->buffer); + close(buffer->gbm_fd); } if (buffer->bo) @@ -496,6 +485,11 @@ WayfireChooserTopLevel::~WayfireChooserTopLevel() gbm_bo_destroy(buffer->bo); } + if (buffer->buffer) + { + wl_buffer_destroy(buffer->buffer); + } + if (buffer->params) { zwp_linux_buffer_params_v1_destroy(buffer->params); diff --git a/src/stream-chooser/toplevelwidget.hpp b/src/stream-chooser/toplevelwidget.hpp index a4746463..3965e955 100644 --- a/src/stream-chooser/toplevelwidget.hpp +++ b/src/stream-chooser/toplevelwidget.hpp @@ -14,6 +14,7 @@ struct toplevel_buffer int height = 0; int stride = 0; gbm_bo *bo = nullptr; + int gbm_fd = -1; wl_buffer *buffer = nullptr; zwp_linux_buffer_params_v1 *params = nullptr; ext_image_copy_capture_frame_v1 *frame = NULL; @@ -47,7 +48,6 @@ class WayfireChooserTopLevel : public Gtk::Box ext_foreign_toplevel_handle_v1 *handle = nullptr; std::shared_ptr buffer = nullptr; ext_image_copy_capture_frame_v1 *frame = NULL; - bool frame_in_flight = false; WayfireChooserTopLevel(ext_foreign_toplevel_handle_v1 *handle); ~WayfireChooserTopLevel(); void commit();