diff options
author | dec05eba <dec05eba@protonmail.com> | 2024-02-09 00:38:23 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2024-02-09 00:38:23 +0100 |
commit | ac73d9cb13ea7e4694b6b013de426cefddae4ca7 (patch) | |
tree | 28ea2dcea83e1d5717110b00b4349f09c8af0f3b | |
parent | 3eb7bae12c9fe50913a57656d2b324d4da18c30a (diff) |
Remove wayland capture (wlroots)
-rwxr-xr-x | build.sh | 9 | ||||
-rw-r--r-- | external/wlr-export-dmabuf-unstable-v1.xml | 203 | ||||
-rw-r--r-- | include/egl.h | 18 | ||||
-rw-r--r-- | src/capture/kms_cuda.c | 117 | ||||
-rw-r--r-- | src/capture/kms_vaapi.c | 194 | ||||
-rw-r--r-- | src/egl.c | 146 | ||||
-rw-r--r-- | src/main.cpp | 28 | ||||
-rw-r--r-- | src/utils.c | 3 |
8 files changed, 121 insertions, 597 deletions
@@ -9,11 +9,6 @@ CXX=${CXX:-g++} opts="-O2 -g0 -DNDEBUG -Wall -Wextra -Wshadow" [ -n "$DEBUG" ] && opts="-O0 -g3 -Wall -Wextra -Wshadow"; -build_wayland_protocol() { - wayland-scanner private-code external/wlr-export-dmabuf-unstable-v1.xml external/wlr-export-dmabuf-unstable-v1-protocol.c - wayland-scanner client-header external/wlr-export-dmabuf-unstable-v1.xml external/wlr-export-dmabuf-unstable-v1-client-protocol.h -} - build_gsr_kms_server() { # TODO: -fcf-protection=full, not supported on arm extra_opts="-fstack-protector-all" @@ -44,14 +39,12 @@ build_gsr() { $CC -c src/color_conversion.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 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 sound.o main.o $libs $opts } -build_wayland_protocol build_gsr_kms_server build_gsr echo "Successfully built gpu-screen-recorder" diff --git a/external/wlr-export-dmabuf-unstable-v1.xml b/external/wlr-export-dmabuf-unstable-v1.xml deleted file mode 100644 index 2614065..0000000 --- a/external/wlr-export-dmabuf-unstable-v1.xml +++ /dev/null @@ -1,203 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<protocol name="wlr_export_dmabuf_unstable_v1"> - <copyright> - Copyright © 2018 Rostislav Pehlivanov - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the "Software"), - to deal in the Software without restriction, including without limitation - the rights to use, copy, modify, merge, publish, distribute, sublicense, - and/or sell copies of the Software, and to permit persons to whom the - Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice (including the next - paragraph) shall be included in all copies or substantial portions of the - Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. - </copyright> - - <description summary="a protocol for low overhead screen content capturing"> - An interface to capture surfaces in an efficient way by exporting DMA-BUFs. - - Warning! The protocol described in this file is experimental and - backward incompatible changes may be made. Backward compatible changes - may be added together with the corresponding interface version bump. - Backward incompatible changes are done by bumping the version number in - the protocol and interface names and resetting the interface version. - Once the protocol is to be declared stable, the 'z' prefix and the - version number in the protocol and interface names are removed and the - interface version number is reset. - </description> - - <interface name="zwlr_export_dmabuf_manager_v1" version="1"> - <description summary="manager to inform clients and begin capturing"> - This object is a manager with which to start capturing from sources. - </description> - - <request name="capture_output"> - <description summary="capture a frame from an output"> - Capture the next frame of a an entire output. - </description> - <arg name="frame" type="new_id" interface="zwlr_export_dmabuf_frame_v1"/> - <arg name="overlay_cursor" type="int" - summary="include custom client hardware cursor on top of the frame"/> - <arg name="output" type="object" interface="wl_output"/> - </request> - - <request name="destroy" type="destructor"> - <description summary="destroy the manager"> - All objects created by the manager will still remain valid, until their - appropriate destroy request has been called. - </description> - </request> - </interface> - - <interface name="zwlr_export_dmabuf_frame_v1" version="1"> - <description summary="a DMA-BUF frame"> - This object represents a single DMA-BUF frame. - - If the capture is successful, the compositor will first send a "frame" - event, followed by one or several "object". When the frame is available - for readout, the "ready" event is sent. - - If the capture failed, the "cancel" event is sent. This can happen anytime - before the "ready" event. - - Once either a "ready" or a "cancel" event is received, the client should - destroy the frame. Once an "object" event is received, the client is - responsible for closing the associated file descriptor. - - All frames are read-only and may not be written into or altered. - </description> - - <enum name="flags"> - <description summary="frame flags"> - Special flags that should be respected by the client. - </description> - <entry name="transient" value="0x1" - summary="clients should copy frame before processing"/> - </enum> - - <event name="frame"> - <description summary="a frame description"> - Main event supplying the client with information about the frame. If the - capture didn't fail, this event is always emitted first before any other - events. - - This event is followed by a number of "object" as specified by the - "num_objects" argument. - </description> - <arg name="width" type="uint" - summary="frame width in pixels"/> - <arg name="height" type="uint" - summary="frame height in pixels"/> - <arg name="offset_x" type="uint" - summary="crop offset for the x axis"/> - <arg name="offset_y" type="uint" - summary="crop offset for the y axis"/> - <arg name="buffer_flags" type="uint" - summary="flags which indicate properties (invert, interlacing), - has the same values as zwp_linux_buffer_params_v1:flags"/> - <arg name="flags" type="uint" enum="flags" - summary="indicates special frame features"/> - <arg name="format" type="uint" - summary="format of the frame (DRM_FORMAT_*)"/> - <arg name="mod_high" type="uint" - summary="drm format modifier, high"/> - <arg name="mod_low" type="uint" - summary="drm format modifier, low"/> - <arg name="num_objects" type="uint" - summary="indicates how many objects (FDs) the frame has (max 4)"/> - </event> - - <event name="object"> - <description summary="an object description"> - Event which serves to supply the client with the file descriptors - containing the data for each object. - - After receiving this event, the client must always close the file - descriptor as soon as they're done with it and even if the frame fails. - </description> - <arg name="index" type="uint" - summary="index of the current object"/> - <arg name="fd" type="fd" - summary="fd of the current object"/> - <arg name="size" type="uint" - summary="size in bytes for the current object"/> - <arg name="offset" type="uint" - summary="starting point for the data in the object's fd"/> - <arg name="stride" type="uint" - summary="line size in bytes"/> - <arg name="plane_index" type="uint" - summary="index of the the plane the data in the object applies to"/> - </event> - - <event name="ready"> - <description summary="indicates frame is available for reading"> - This event is sent as soon as the frame is presented, indicating it is - available for reading. This event includes the time at which - presentation happened at. - - The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, - each component being an unsigned 32-bit value. Whole seconds are in - tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, - and the additional fractional part in tv_nsec as nanoseconds. Hence, - for valid timestamps tv_nsec must be in [0, 999999999]. The seconds part - may have an arbitrary offset at start. - - After receiving this event, the client should destroy this object. - </description> - <arg name="tv_sec_hi" type="uint" - summary="high 32 bits of the seconds part of the timestamp"/> - <arg name="tv_sec_lo" type="uint" - summary="low 32 bits of the seconds part of the timestamp"/> - <arg name="tv_nsec" type="uint" - summary="nanoseconds part of the timestamp"/> - </event> - - <enum name="cancel_reason"> - <description summary="cancel reason"> - Indicates reason for cancelling the frame. - </description> - <entry name="temporary" value="0" - summary="temporary error, source will produce more frames"/> - <entry name="permanent" value="1" - summary="fatal error, source will not produce frames"/> - <entry name="resizing" value="2" - summary="temporary error, source will produce more frames"/> - </enum> - - <event name="cancel"> - <description summary="indicates the frame is no longer valid"> - If the capture failed or if the frame is no longer valid after the - "frame" event has been emitted, this event will be used to inform the - client to scrap the frame. - - If the failure is temporary, the client may capture again the same - source. If the failure is permanent, any further attempts to capture the - same source will fail again. - - After receiving this event, the client should destroy this object. - </description> - <arg name="reason" type="uint" enum="cancel_reason" - summary="indicates a reason for cancelling this frame capture"/> - </event> - - <request name="destroy" type="destructor"> - <description summary="delete this object, used or not"> - Unreferences the frame. This request must be called as soon as its no - longer used. - - It can be called at any time by the client. The client will still have - to close any FDs it has been given. - </description> - </request> - </interface> -</protocol>
\ No newline at end of file diff --git a/include/egl.h b/include/egl.h index a747bdb..b8513fd 100644 --- a/include/egl.h +++ b/include/egl.h @@ -128,12 +128,8 @@ typedef struct { void *registry; void *surface; void *compositor; - void *export_manager; - void *current_frame; - void *frame_callback; gsr_wayland_output outputs[GSR_MAX_OUTPUTS]; int num_outputs; - gsr_wayland_output *output_to_capture; } gsr_wayland; typedef struct { @@ -148,16 +144,6 @@ typedef struct { gsr_wayland wayland; char card_path[128]; - int fd; - uint32_t x; - uint32_t y; - uint32_t width; - uint32_t height; - uint32_t pitch; - uint32_t offset; - uint32_t pixel_format; - uint64_t modifier; - int32_t (*eglGetError)(void); EGLDisplay (*eglGetDisplay)(EGLNativeDisplayType display_id); unsigned int (*eglInitialize)(EGLDisplay dpy, int32_t *major, int32_t *minor); @@ -234,10 +220,6 @@ typedef struct { bool gsr_egl_load(gsr_egl *self, Display *dpy, bool wayland); void gsr_egl_unload(gsr_egl *self); -/* wayland protocol capture, does not include kms capture */ -bool gsr_egl_supports_wayland_capture(const gsr_egl *self); -bool gsr_egl_start_capture(gsr_egl *self, const char *monitor_to_capture); void gsr_egl_update(gsr_egl *self); -void gsr_egl_cleanup_frame(gsr_egl *self); #endif /* GSR_EGL_H */ diff --git a/src/capture/kms_cuda.c b/src/capture/kms_cuda.c index a7e991b..f5b96a8 100644 --- a/src/capture/kms_cuda.c +++ b/src/capture/kms_cuda.c @@ -37,8 +37,6 @@ typedef struct { gsr_kms_client kms_client; gsr_kms_response kms_response; - gsr_kms_response_fd wayland_kms_data; - bool using_wayland_capture; vec2i capture_pos; vec2i capture_size; @@ -144,32 +142,24 @@ static int gsr_capture_kms_cuda_start(gsr_capture *cap, AVCodecContext *video_co gsr_monitor monitor; cap_kms->monitor_id.num_connector_ids = 0; - if(gsr_egl_start_capture(cap_kms->params.egl, cap_kms->params.display_to_capture)) { - if(!get_monitor_by_name(cap_kms->params.egl, GSR_CONNECTION_WAYLAND, cap_kms->params.display_to_capture, &monitor)) { - fprintf(stderr, "gsr error: gsr_capture_kms_cuda_start: failed to find monitor by name \"%s\"\n", cap_kms->params.display_to_capture); - gsr_capture_kms_cuda_stop(cap, video_codec_context); - return -1; - } - cap_kms->using_wayland_capture = true; - } else { - int kms_init_res = gsr_kms_client_init(&cap_kms->kms_client, cap_kms->params.egl->card_path); - if(kms_init_res != 0) { - gsr_capture_kms_cuda_stop(cap, video_codec_context); - return kms_init_res; - } - MonitorCallbackUserdata monitor_callback_userdata = { - cap_kms, - cap_kms->params.display_to_capture, strlen(cap_kms->params.display_to_capture), - 0 - }; - for_each_active_monitor_output(cap_kms->params.egl, GSR_CONNECTION_DRM, monitor_callback, &monitor_callback_userdata); + int kms_init_res = gsr_kms_client_init(&cap_kms->kms_client, cap_kms->params.egl->card_path); + if(kms_init_res != 0) { + gsr_capture_kms_cuda_stop(cap, video_codec_context); + return kms_init_res; + } - if(!get_monitor_by_name(cap_kms->params.egl, GSR_CONNECTION_DRM, cap_kms->params.display_to_capture, &monitor)) { - fprintf(stderr, "gsr error: gsr_capture_kms_cuda_start: failed to find monitor by name \"%s\"\n", cap_kms->params.display_to_capture); - gsr_capture_kms_cuda_stop(cap, video_codec_context); - return -1; - } + MonitorCallbackUserdata monitor_callback_userdata = { + cap_kms, + cap_kms->params.display_to_capture, strlen(cap_kms->params.display_to_capture), + 0 + }; + for_each_active_monitor_output(cap_kms->params.egl, GSR_CONNECTION_DRM, monitor_callback, &monitor_callback_userdata); + + if(!get_monitor_by_name(cap_kms->params.egl, GSR_CONNECTION_DRM, cap_kms->params.display_to_capture, &monitor)) { + fprintf(stderr, "gsr error: gsr_capture_kms_cuda_start: failed to find monitor by name \"%s\"\n", cap_kms->params.display_to_capture); + gsr_capture_kms_cuda_stop(cap, video_codec_context); + return -1; } cap_kms->capture_pos = monitor.pos; @@ -407,62 +397,37 @@ static int gsr_capture_kms_cuda_capture(gsr_capture *cap, AVFrame *frame) { gsr_kms_response_fd *drm_fd = NULL; gsr_kms_response_fd *cursor_drm_fd = NULL; bool capture_is_combined_plane = false; - if(cap_kms->using_wayland_capture) { - gsr_egl_update(cap_kms->params.egl); - cap_kms->wayland_kms_data.fd = cap_kms->params.egl->fd; - cap_kms->wayland_kms_data.width = cap_kms->params.egl->width; - cap_kms->wayland_kms_data.height = cap_kms->params.egl->height; - cap_kms->wayland_kms_data.pitch = cap_kms->params.egl->pitch; - cap_kms->wayland_kms_data.offset = cap_kms->params.egl->offset; - cap_kms->wayland_kms_data.pixel_format = cap_kms->params.egl->pixel_format; - cap_kms->wayland_kms_data.modifier = cap_kms->params.egl->modifier; - cap_kms->wayland_kms_data.connector_id = 0; - cap_kms->wayland_kms_data.is_combined_plane = false; - cap_kms->wayland_kms_data.is_cursor = false; - cap_kms->wayland_kms_data.x = cap_kms->wayland_kms_data.x; // TODO: Use these - cap_kms->wayland_kms_data.y = cap_kms->wayland_kms_data.y; - cap_kms->wayland_kms_data.src_w = cap_kms->wayland_kms_data.width; - cap_kms->wayland_kms_data.src_h = cap_kms->wayland_kms_data.height; - - cap_kms->capture_pos.x = cap_kms->wayland_kms_data.x; - cap_kms->capture_pos.y = cap_kms->wayland_kms_data.y; - - if(cap_kms->wayland_kms_data.fd <= 0) - return -1; - - drm_fd = &cap_kms->wayland_kms_data; - } else { - if(gsr_kms_client_get_kms(&cap_kms->kms_client, &cap_kms->kms_response) != 0) { - fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_capture: failed to get kms, error: %d (%s)\n", cap_kms->kms_response.result, cap_kms->kms_response.err_msg); - return -1; - } - if(cap_kms->kms_response.num_fds == 0) { - static bool error_shown = false; - if(!error_shown) { - error_shown = true; - fprintf(stderr, "gsr error: no drm found, capture will fail\n"); - } - return -1; - } + if(gsr_kms_client_get_kms(&cap_kms->kms_client, &cap_kms->kms_response) != 0) { + fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_capture: failed to get kms, error: %d (%s)\n", cap_kms->kms_response.result, cap_kms->kms_response.err_msg); + return -1; + } - for(int i = 0; i < cap_kms->monitor_id.num_connector_ids; ++i) { - drm_fd = find_drm_by_connector_id(&cap_kms->kms_response, cap_kms->monitor_id.connector_ids[i]); - if(drm_fd) - break; + if(cap_kms->kms_response.num_fds == 0) { + static bool error_shown = false; + if(!error_shown) { + error_shown = true; + fprintf(stderr, "gsr error: no drm found, capture will fail\n"); } + return -1; + } - // Will never happen on wayland unless the target monitor has been disconnected - if(!drm_fd) { - drm_fd = find_first_combined_drm(&cap_kms->kms_response); - if(!drm_fd) - drm_fd = find_largest_drm(&cap_kms->kms_response); - capture_is_combined_plane = true; - } + for(int i = 0; i < cap_kms->monitor_id.num_connector_ids; ++i) { + drm_fd = find_drm_by_connector_id(&cap_kms->kms_response, cap_kms->monitor_id.connector_ids[i]); + if(drm_fd) + break; + } - cursor_drm_fd = find_cursor_drm(&cap_kms->kms_response); + // Will never happen on wayland unless the target monitor has been disconnected + if(!drm_fd) { + drm_fd = find_first_combined_drm(&cap_kms->kms_response); + if(!drm_fd) + drm_fd = find_largest_drm(&cap_kms->kms_response); + capture_is_combined_plane = true; } + cursor_drm_fd = find_cursor_drm(&cap_kms->kms_response); + if(!drm_fd) return -1; @@ -551,8 +516,6 @@ static void gsr_capture_kms_cuda_capture_end(gsr_capture *cap, AVFrame *frame) { (void)frame; gsr_capture_kms_cuda *cap_kms = cap->priv; - gsr_egl_cleanup_frame(cap_kms->params.egl); - for(int i = 0; i < cap_kms->kms_response.num_fds; ++i) { if(cap_kms->kms_response.fds[i].fd > 0) close(cap_kms->kms_response.fds[i].fd); diff --git a/src/capture/kms_vaapi.c b/src/capture/kms_vaapi.c index b463050..28527cf 100644 --- a/src/capture/kms_vaapi.c +++ b/src/capture/kms_vaapi.c @@ -29,8 +29,6 @@ typedef struct { gsr_kms_client kms_client; gsr_kms_response kms_response; - gsr_kms_response_fd wayland_kms_data; - bool using_wayland_capture; vec2i capture_pos; vec2i capture_size; @@ -138,32 +136,24 @@ static int gsr_capture_kms_vaapi_start(gsr_capture *cap, AVCodecContext *video_c gsr_monitor monitor; cap_kms->monitor_id.num_connector_ids = 0; - if(gsr_egl_start_capture(cap_kms->params.egl, cap_kms->params.display_to_capture)) { - if(!get_monitor_by_name(cap_kms->params.egl, GSR_CONNECTION_WAYLAND, cap_kms->params.display_to_capture, &monitor)) { - fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_start: failed to find monitor by name \"%s\"\n", cap_kms->params.display_to_capture); - gsr_capture_kms_vaapi_stop(cap, video_codec_context); - return -1; - } - cap_kms->using_wayland_capture = true; - } else { - int kms_init_res = gsr_kms_client_init(&cap_kms->kms_client, cap_kms->params.egl->card_path); - if(kms_init_res != 0) { - gsr_capture_kms_vaapi_stop(cap, video_codec_context); - return kms_init_res; - } - MonitorCallbackUserdata monitor_callback_userdata = { - cap_kms, - cap_kms->params.display_to_capture, strlen(cap_kms->params.display_to_capture), - 0, - }; - for_each_active_monitor_output(cap_kms->params.egl, GSR_CONNECTION_DRM, monitor_callback, &monitor_callback_userdata); + int kms_init_res = gsr_kms_client_init(&cap_kms->kms_client, cap_kms->params.egl->card_path); + if(kms_init_res != 0) { + gsr_capture_kms_vaapi_stop(cap, video_codec_context); + return kms_init_res; + } - if(!get_monitor_by_name(cap_kms->params.egl, GSR_CONNECTION_DRM, cap_kms->params.display_to_capture, &monitor)) { - fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_start: failed to find monitor by name \"%s\"\n", cap_kms->params.display_to_capture); - gsr_capture_kms_vaapi_stop(cap, video_codec_context); - return -1; - } + MonitorCallbackUserdata monitor_callback_userdata = { + cap_kms, + cap_kms->params.display_to_capture, strlen(cap_kms->params.display_to_capture), + 0, + }; + for_each_active_monitor_output(cap_kms->params.egl, GSR_CONNECTION_DRM, monitor_callback, &monitor_callback_userdata); + + if(!get_monitor_by_name(cap_kms->params.egl, GSR_CONNECTION_DRM, cap_kms->params.display_to_capture, &monitor)) { + fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_start: failed to find monitor by name \"%s\"\n", cap_kms->params.display_to_capture); + gsr_capture_kms_vaapi_stop(cap, video_codec_context); + return -1; } cap_kms->capture_pos = monitor.pos; @@ -398,26 +388,6 @@ static gsr_kms_response_fd* find_cursor_drm(gsr_kms_response *kms_response) { return NULL; } -static void copy_wayland_surface_data_to_drm_buffer(gsr_capture_kms_vaapi *cap_kms) { - cap_kms->wayland_kms_data.fd = cap_kms->params.egl->fd; - cap_kms->wayland_kms_data.width = cap_kms->params.egl->width; - cap_kms->wayland_kms_data.height = cap_kms->params.egl->height; - cap_kms->wayland_kms_data.pitch = cap_kms->params.egl->pitch; - cap_kms->wayland_kms_data.offset = cap_kms->params.egl->offset; - cap_kms->wayland_kms_data.pixel_format = cap_kms->params.egl->pixel_format; - cap_kms->wayland_kms_data.modifier = cap_kms->params.egl->modifier; - cap_kms->wayland_kms_data.connector_id = 0; - cap_kms->wayland_kms_data.is_combined_plane = false; - cap_kms->wayland_kms_data.is_cursor = false; - cap_kms->wayland_kms_data.x = cap_kms->wayland_kms_data.x; // TODO: Use these - cap_kms->wayland_kms_data.y = cap_kms->wayland_kms_data.y; - cap_kms->wayland_kms_data.src_w = cap_kms->wayland_kms_data.width; - cap_kms->wayland_kms_data.src_h = cap_kms->wayland_kms_data.height; - - cap_kms->capture_pos.x = cap_kms->wayland_kms_data.x; - cap_kms->capture_pos.y = cap_kms->wayland_kms_data.y; -} - #define HDMI_STATIC_METADATA_TYPE1 0 #define HDMI_EOTF_SMPTE_ST2084 2 @@ -471,46 +441,37 @@ static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) { gsr_kms_response_fd *drm_fd = NULL; gsr_kms_response_fd *cursor_drm_fd = NULL; bool capture_is_combined_plane = false; - if(cap_kms->using_wayland_capture) { - gsr_egl_update(cap_kms->params.egl); - copy_wayland_surface_data_to_drm_buffer(cap_kms); - - if(cap_kms->wayland_kms_data.fd <= 0) - return -1; - - drm_fd = &cap_kms->wayland_kms_data; - } else { - if(gsr_kms_client_get_kms(&cap_kms->kms_client, &cap_kms->kms_response) != 0) { - fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_capture: failed to get kms, error: %d (%s)\n", cap_kms->kms_response.result, cap_kms->kms_response.err_msg); - return -1; - } - if(cap_kms->kms_response.num_fds == 0) { - static bool error_shown = false; - if(!error_shown) { - error_shown = true; - fprintf(stderr, "gsr error: no drm found, capture will fail\n"); - } - return -1; - } + if(gsr_kms_client_get_kms(&cap_kms->kms_client, &cap_kms->kms_response) != 0) { + fprintf(stderr, "gsr error: gsr_capture_kms_vaapi_capture: failed to get kms, error: %d (%s)\n", cap_kms->kms_response.result, cap_kms->kms_response.err_msg); + return -1; + } - for(int i = 0; i < cap_kms->monitor_id.num_connector_ids; ++i) { - drm_fd = find_drm_by_connector_id(&cap_kms->kms_response, cap_kms->monitor_id.connector_ids[i]); - if(drm_fd) - break; + if(cap_kms->kms_response.num_fds == 0) { + static bool error_shown = false; + if(!error_shown) { + error_shown = true; + fprintf(stderr, "gsr error: no drm found, capture will fail\n"); } + return -1; + } - // Will never happen on wayland unless the target monitor has been disconnected - if(!drm_fd) { - drm_fd = find_first_combined_drm(&cap_kms->kms_response); - if(!drm_fd) - drm_fd = find_largest_drm(&cap_kms->kms_response); - capture_is_combined_plane = true; - } + for(int i = 0; i < cap_kms->monitor_id.num_connector_ids; ++i) { + drm_fd = find_drm_by_connector_id(&cap_kms->kms_response, cap_kms->monitor_id.connector_ids[i]); + if(drm_fd) + break; + } - cursor_drm_fd = find_cursor_drm(&cap_kms->kms_response); + // Will never happen on wayland unless the target monitor has been disconnected + if(!drm_fd) { + drm_fd = find_first_combined_drm(&cap_kms->kms_response); + if(!drm_fd) + drm_fd = find_largest_drm(&cap_kms->kms_response); + capture_is_combined_plane = true; } + cursor_drm_fd = find_cursor_drm(&cap_kms->kms_response); + if(!drm_fd) return -1; @@ -559,47 +520,40 @@ static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) { vec2i capture_pos = cap_kms->capture_pos; - if(cap_kms->using_wayland_capture) { - gsr_color_conversion_draw(&cap_kms->color_conversion, cap_kms->input_texture, - (vec2i){0, 0}, cap_kms->capture_size, - (vec2i){0, 0}, cap_kms->capture_size, + if(!capture_is_combined_plane) + capture_pos = (vec2i){drm_fd->x, drm_fd->y}; + + float texture_rotation = 0.0f; + + gsr_color_conversion_draw(&cap_kms->color_conversion, cap_kms->input_texture, + (vec2i){0, 0}, cap_kms->capture_size, + capture_pos, cap_kms->capture_size, + texture_rotation, false); + + if(cursor_drm_fd) { + const intptr_t img_attr_cursor[] = { + EGL_LINUX_DRM_FOURCC_EXT, cursor_drm_fd->pixel_format, + EGL_WIDTH, cursor_drm_fd->width, + EGL_HEIGHT, cursor_drm_fd->height, + EGL_DMA_BUF_PLANE0_FD_EXT, cursor_drm_fd->fd, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, cursor_drm_fd->offset, + EGL_DMA_BUF_PLANE0_PITCH_EXT, cursor_drm_fd->pitch, + EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, cursor_drm_fd->modifier & 0xFFFFFFFFULL, + EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, cursor_drm_fd->modifier >> 32ULL, + EGL_NONE + }; + + EGLImage cursor_image = cap_kms->params.egl->eglCreateImage(cap_kms->params.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr_cursor); + cap_kms->params.egl->glBindTexture(GL_TEXTURE_2D, cap_kms->cursor_texture); + cap_kms->params.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, cursor_image); + cap_kms->params.egl->eglDestroyImage(cap_kms->params.egl->egl_display, cursor_image); + cap_kms->params.egl->glBindTexture(GL_TEXTURE_2D, 0); + + vec2i cursor_size = {cursor_drm_fd->width, cursor_drm_fd->height}; + gsr_color_conversion_draw(&cap_kms->color_conversion, cap_kms->cursor_texture, + (vec2i){cursor_drm_fd->x, cursor_drm_fd->y}, cursor_size, + (vec2i){0, 0}, cursor_size, 0.0f, false); - } else { - if(!capture_is_combined_plane) - capture_pos = (vec2i){drm_fd->x, drm_fd->y}; - - float texture_rotation = 0.0f; - - gsr_color_conversion_draw(&cap_kms->color_conversion, cap_kms->input_texture, - (vec2i){0, 0}, cap_kms->capture_size, - capture_pos, cap_kms->capture_size, - texture_rotation, false); - - if(cursor_drm_fd) { - const intptr_t img_attr_cursor[] = { - EGL_LINUX_DRM_FOURCC_EXT, cursor_drm_fd->pixel_format, - EGL_WIDTH, cursor_drm_fd->width, - EGL_HEIGHT, cursor_drm_fd->height, - EGL_DMA_BUF_PLANE0_FD_EXT, cursor_drm_fd->fd, - EGL_DMA_BUF_PLANE0_OFFSET_EXT, cursor_drm_fd->offset, - EGL_DMA_BUF_PLANE0_PITCH_EXT, cursor_drm_fd->pitch, - EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, cursor_drm_fd->modifier & 0xFFFFFFFFULL, - EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, cursor_drm_fd->modifier >> 32ULL, - EGL_NONE - }; - - EGLImage cursor_image = cap_kms->params.egl->eglCreateImage(cap_kms->params.egl->egl_display, 0, EGL_LINUX_DMA_BUF_EXT, NULL, img_attr_cursor); - cap_kms->params.egl->glBindTexture(GL_TEXTURE_2D, cap_kms->cursor_texture); - cap_kms->params.egl->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, cursor_image); - cap_kms->params.egl->eglDestroyImage(cap_kms->params.egl->egl_display, cursor_image); - cap_kms->params.egl->glBindTexture(GL_TEXTURE_2D, 0); - - vec2i cursor_size = {cursor_drm_fd->width, cursor_drm_fd->height}; - gsr_color_conversion_draw(&cap_kms->color_conversion, cap_kms->cursor_texture, - (vec2i){cursor_drm_fd->x, cursor_drm_fd->y}, cursor_size, - (vec2i){0, 0}, cursor_size, - 0.0f, false); - } } cap_kms->params.egl->eglSwapBuffers(cap_kms->params.egl->egl_display, cap_kms->params.egl->egl_surface); @@ -613,8 +567,6 @@ static void gsr_capture_kms_vaapi_capture_end(gsr_capture *cap, AVFrame *frame) (void)frame; gsr_capture_kms_vaapi *cap_kms = cap->priv; - gsr_egl_cleanup_frame(cap_kms->params.egl); - for(int i = 0; i < cap_kms->kms_response.num_fds; ++i) { if(cap_kms->kms_response.fds[i].fd > 0) close(cap_kms->kms_response.fds[i].fd); @@ -8,7 +8,6 @@ #include <wayland-client.h> #include <wayland-egl.h> -#include "../external/wlr-export-dmabuf-unstable-v1-client-protocol.h" #include <unistd.h> #include <sys/capability.h> @@ -105,12 +104,6 @@ static void registry_add_object(void *data, struct wl_registry *registry, uint32 .name = NULL, }; wl_output_add_listener(gsr_output->output, &output_listener, gsr_output); - } else if(strcmp(interface, zwlr_export_dmabuf_manager_v1_interface.name) == 0) { - if(egl->wayland.export_manager) { - zwlr_export_dmabuf_manager_v1_destroy(egl->wayland.export_manager); - egl->wayland.export_manager = NULL; - } - egl->wayland.export_manager = wl_registry_bind(registry, name, &zwlr_export_dmabuf_manager_v1_interface, 1); } } @@ -125,88 +118,6 @@ static struct wl_registry_listener registry_listener = { .global_remove = registry_remove_object, }; -static void frame_capture_output(gsr_egl *egl); - -static void frame_start(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, - uint32_t width, uint32_t height, uint32_t offset_x, uint32_t offset_y, - uint32_t buffer_flags, uint32_t flags, uint32_t format, - uint32_t mod_high, uint32_t mod_low, uint32_t num_objects) { - (void)buffer_flags; - (void)flags; - (void)num_objects; - gsr_egl *egl = data; - //fprintf(stderr, "frame start %p, width: %u, height: %u, offset x: %u, offset y: %u, format: %u, num objects: %u\n", (void*)frame, width, height, offset_x, offset_y, format, num_objects); - egl->x = offset_x; - egl->y = offset_y; - egl->width = width; - egl->height = height; - egl->pixel_format = format; - egl->modifier = ((uint64_t)mod_high << 32) | (uint64_t)mod_low; - egl->wayland.current_frame = frame; -} - -static void frame_object(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, - uint32_t index, int32_t fd, uint32_t size, uint32_t offset, - uint32_t stride, uint32_t plane_index) { - // TODO: What if we get multiple objects? then we get multiple fd per frame - (void)frame; - (void)index; - (void)size; - (void)plane_index; - gsr_egl *egl = data; - if(egl->fd > 0) { - close(egl->fd); - egl->fd = 0; - } - egl->fd = fd; - egl->pitch = stride; - egl->offset = offset; - //fprintf(stderr, "new frame %p, fd: %d, index: %u, size: %u, offset: %u, stride: %u, plane_index: %u\n", (void*)frame, fd, index, size, offset, stride, plane_index); -} - -static void frame_ready(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, uint32_t tv_sec_hi, uint32_t tv_sec_lo, uint32_t tv_nsec) { - (void)frame; - (void)tv_sec_hi; - (void)tv_sec_lo; - (void)tv_nsec; - frame_capture_output(data); -} - -static void frame_cancel(void *data, struct zwlr_export_dmabuf_frame_v1 *frame, uint32_t reason) { - (void)frame; - (void)reason; - frame_capture_output(data); -} - -static const struct zwlr_export_dmabuf_frame_v1_listener frame_listener = { - .frame = frame_start, - .object = frame_object, - .ready = frame_ready, - .cancel = frame_cancel, -}; - -static void frame_capture_output(gsr_egl *egl) { - assert(egl->wayland.output_to_capture); - bool with_cursor = true; - - if(egl->wayland.frame_callback) { - zwlr_export_dmabuf_frame_v1_destroy(egl->wayland.frame_callback); - egl->wayland.frame_callback = NULL; - } - - egl->wayland.frame_callback = zwlr_export_dmabuf_manager_v1_capture_output(egl->wayland.export_manager, with_cursor, egl->wayland.output_to_capture->output); - zwlr_export_dmabuf_frame_v1_add_listener(egl->wayland.frame_callback, &frame_listener, egl); -} - -static gsr_wayland_output* get_wayland_output_by_name(gsr_egl *egl, const char *name) { - assert(name); - for(int i = 0; i < egl->wayland.num_outputs; ++i) { - if(egl->wayland.outputs[i].name && strcmp(egl->wayland.outputs[i].name, name) == 0) - return &egl->wayland.outputs[i]; - } - return NULL; -} - static void reset_cap_nice(void) { cap_t caps = cap_get_proc(); if(!caps) @@ -492,18 +403,6 @@ void gsr_egl_unload(gsr_egl *self) { self->x11.window = None; } - gsr_egl_cleanup_frame(self); - - if(self->wayland.frame_callback) { - zwlr_export_dmabuf_frame_v1_destroy(self->wayland.frame_callback); - self->wayland.frame_callback = NULL; - } - - if(self->wayland.export_manager) { - zwlr_export_dmabuf_manager_v1_destroy(self->wayland.export_manager); - self->wayland.export_manager = NULL; - } - if(self->wayland.window) { wl_egl_window_destroy(self->wayland.window); self->wayland.window = NULL; @@ -555,36 +454,6 @@ void gsr_egl_unload(gsr_egl *self) { memset(self, 0, sizeof(gsr_egl)); } -bool gsr_egl_supports_wayland_capture(const gsr_egl *self) { - // TODO: wlroots capture is broken right now (black screen) on amd and multiple monitors - // so it has to be disabled right now. Find out why it happens and fix it. - (void)self; - return false; - //return !!self->wayland.export_manager && self->wayland.num_outputs > 0; -} - -bool gsr_egl_start_capture(gsr_egl *self, const char *monitor_to_capture) { - assert(monitor_to_capture); - if(!monitor_to_capture) - return false; - - if(!self->wayland.dpy) - return false; - - if(!gsr_egl_supports_wayland_capture(self)) - return false; - - if(self->wayland.frame_callback) - return false; - - self->wayland.output_to_capture = get_wayland_output_by_name(self, monitor_to_capture); - if(!self->wayland.output_to_capture) - return false; - - frame_capture_output(self); - return true; -} - void gsr_egl_update(gsr_egl *self) { if(!self->wayland.dpy) return; @@ -592,18 +461,3 @@ void gsr_egl_update(gsr_egl *self) { // TODO: pselect on wl_display_get_fd before doing dispatch wl_display_dispatch(self->wayland.dpy); } - -void gsr_egl_cleanup_frame(gsr_egl *self) { - if(!self->wayland.dpy) - return; - - if(self->fd > 0) { - close(self->fd); - self->fd = 0; - } - - if(self->wayland.current_frame) { - //zwlr_export_dmabuf_frame_v1_destroy(self->wayland.current_frame); - self->wayland.current_frame = NULL; - } -} diff --git a/src/main.cpp b/src/main.cpp index 29da47f..4a04206 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1437,11 +1437,7 @@ static gsr_capture* create_capture_impl(const char *window_str, const char *scre if(strcmp(window_str, "screen") == 0) { FirstOutputCallback first_output; first_output.output_name = NULL; - if(gsr_egl_supports_wayland_capture(&egl)) { - for_each_active_monitor_output(&egl, GSR_CONNECTION_WAYLAND, get_first_output, &first_output); - } else { - for_each_active_monitor_output(&egl, GSR_CONNECTION_DRM, get_first_output, &first_output); - } + for_each_active_monitor_output(&egl, GSR_CONNECTION_DRM, get_first_output, &first_output); if(first_output.output_name) { window_str = first_output.output_name; @@ -1450,22 +1446,12 @@ static gsr_capture* create_capture_impl(const char *window_str, const char *scre } } - if(gsr_egl_supports_wayland_capture(&egl)) { - gsr_monitor gmon; - if(!get_monitor_by_name(&egl, GSR_CONNECTION_WAYLAND, window_str, &gmon)) { - fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str); - fprintf(stderr, " \"screen\"\n"); - for_each_active_monitor_output(&egl, GSR_CONNECTION_WAYLAND, monitor_output_callback_print, NULL); - _exit(1); - } - } else { - gsr_monitor gmon; - if(!get_monitor_by_name(&egl, GSR_CONNECTION_DRM, window_str, &gmon)) { - fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str); - fprintf(stderr, " \"screen\"\n"); - for_each_active_monitor_output(&egl, GSR_CONNECTION_DRM, monitor_output_callback_print, NULL); - _exit(1); - } + gsr_monitor gmon; + if(!get_monitor_by_name(&egl, GSR_CONNECTION_DRM, window_str, &gmon)) { + fprintf(stderr, "gsr error: display \"%s\" not found, expected one of:\n", window_str); + fprintf(stderr, " \"screen\"\n"); + for_each_active_monitor_output(&egl, GSR_CONNECTION_DRM, monitor_output_callback_print, NULL); + _exit(1); } } else { if(strcmp(window_str, "screen") != 0 && strcmp(window_str, "screen-direct") != 0 && strcmp(window_str, "screen-direct-force") != 0) { diff --git a/src/utils.c b/src/utils.c index 902f082..8316fa4 100644 --- a/src/utils.c +++ b/src/utils.c @@ -100,9 +100,6 @@ static bool connector_get_property_by_name(int drmfd, drmModeConnectorPtr props, } static void for_each_active_monitor_output_wayland(const gsr_egl *egl, active_monitor_callback callback, void *userdata) { - if(!gsr_egl_supports_wayland_capture(egl)) - return; - for(int i = 0; i < egl->wayland.num_outputs; ++i) { if(!egl->wayland.outputs[i].name) continue; |