mirror of
https://repo.dec05eba.com/gpu-screen-recorder
synced 2026-03-31 09:07:13 +09:00
Remove wayland capture (wlroots)
This commit is contained in:
9
build.sh
9
build.sh
@@ -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"
|
||||
|
||||
203
external/wlr-export-dmabuf-unstable-v1.xml
vendored
203
external/wlr-export-dmabuf-unstable-v1.xml
vendored
@@ -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>
|
||||
@@ -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 */
|
||||
|
||||
@@ -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,14 +142,7 @@ 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);
|
||||
@@ -170,7 +161,6 @@ static int gsr_capture_kms_cuda_start(gsr_capture *cap, AVCodecContext *video_co
|
||||
gsr_capture_kms_cuda_stop(cap, video_codec_context);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
cap_kms->capture_pos = monitor.pos;
|
||||
cap_kms->capture_size = monitor.size;
|
||||
@@ -407,31 +397,7 @@ 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;
|
||||
@@ -461,7 +427,6 @@ static int gsr_capture_kms_cuda_capture(gsr_capture *cap, AVFrame *frame) {
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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,14 +136,7 @@ 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);
|
||||
@@ -164,7 +155,6 @@ static int gsr_capture_kms_vaapi_start(gsr_capture *cap, AVCodecContext *video_c
|
||||
gsr_capture_kms_vaapi_stop(cap, video_codec_context);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
cap_kms->capture_pos = monitor.pos;
|
||||
cap_kms->capture_size = monitor.size;
|
||||
@@ -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,15 +441,7 @@ 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;
|
||||
@@ -509,7 +471,6 @@ static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) {
|
||||
}
|
||||
|
||||
cursor_drm_fd = find_cursor_drm(&cap_kms->kms_response);
|
||||
}
|
||||
|
||||
if(!drm_fd)
|
||||
return -1;
|
||||
@@ -559,12 +520,6 @@ 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,
|
||||
0.0f, false);
|
||||
} else {
|
||||
if(!capture_is_combined_plane)
|
||||
capture_pos = (vec2i){drm_fd->x, drm_fd->y};
|
||||
|
||||
@@ -600,7 +555,6 @@ static int gsr_capture_kms_vaapi_capture(gsr_capture *cap, AVFrame *frame) {
|
||||
(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);
|
||||
//cap_kms->params.egl->glFlush();
|
||||
@@ -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);
|
||||
|
||||
146
src/egl.c
146
src/egl.c
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
14
src/main.cpp
14
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);
|
||||
}
|
||||
|
||||
if(first_output.output_name) {
|
||||
window_str = first_output.output_name;
|
||||
@@ -1450,15 +1446,6 @@ 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);
|
||||
@@ -1466,7 +1453,6 @@ static gsr_capture* create_capture_impl(const char *window_str, const char *scre
|
||||
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) {
|
||||
gsr_monitor gmon;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user