Skip to content

Commit 0a71c90

Browse files
committed
WIP: src/mirror/target: add generic target system (still partially hacked)
1 parent 781f55e commit 0a71c90

File tree

12 files changed

+428
-45
lines changed

12 files changed

+428
-45
lines changed

include/wlm/mirror.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <EGL/egl.h>
99
#include <wlm/transform.h>
1010
#include <wlm/mirror/backends.h>
11+
#include <wlm/mirror/target.h>
1112

1213
struct ctx;
1314
struct output_list_node;
@@ -19,7 +20,7 @@ struct fallback_backend {
1920
};
2021

2122
typedef struct ctx_mirror {
22-
struct output_list_node * current_target;
23+
wlm_mirror_target_t * current_target;
2324
struct wl_callback * frame_callback;
2425
region_t current_region;
2526
bool invert_y;

include/wlm/mirror/extcopy.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ typedef struct {
1919
mirror_backend_t header;
2020
bool use_dmabuf;
2121

22-
struct ext_image_capture_source_v1 * capture_source;
2322
struct ext_image_copy_capture_session_v1 * capture_session;
2423
struct ext_image_copy_capture_frame_v1 * capture_frame;
2524

include/wlm/mirror/target.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#ifndef WLM_MIRROR_TARGET_H_
2+
#define WLM_MIRROR_TARGET_H_
3+
4+
#include <wayland-client-protocol.h>
5+
#include <wlm/wayland.h>
6+
7+
typedef struct ctx ctx_t;
8+
9+
typedef enum {
10+
WLM_MIRROR_TARGET_TYPE_NULL = 0,
11+
WLM_MIRROR_TARGET_TYPE_OUTPUT,
12+
WLM_MIRROR_TARGET_TYPE_TOPLEVEL,
13+
} wlm_mirror_target_type_t;
14+
15+
typedef struct {
16+
wlm_mirror_target_type_t type;
17+
struct ext_image_capture_source_v1 * source;
18+
enum wl_output_transform transform;
19+
} wlm_mirror_target_t;
20+
21+
typedef struct {
22+
wlm_mirror_target_t header;
23+
output_list_node_t * output;
24+
} wlm_mirror_target_output_t;
25+
26+
typedef struct {
27+
wlm_mirror_target_t header;
28+
struct ext_foreign_toplevel_handle_v1 * toplevel;
29+
} wlm_mirror_target_toplevel_t;
30+
31+
wlm_mirror_target_t * wlm_mirror_target_parse(ctx_t * ctx, const char * target);
32+
wlm_mirror_target_t * wlm_mirror_target_find_output(ctx_t * ctx, const char * name);
33+
wlm_mirror_target_t * wlm_mirror_target_find_toplevel(ctx_t * ctx, const char * identifier);
34+
35+
// TODO: remove this
36+
wlm_mirror_target_t * wlm_mirror_target_create_output(ctx_t * ctx, output_list_node_t * output_node);
37+
38+
output_list_node_t * wlm_mirror_target_get_output_node(wlm_mirror_target_t * target);
39+
struct ext_image_capture_source_v1 * wlm_mirror_target_get_capture_source(wlm_mirror_target_t * target);
40+
enum wl_output_transform wlm_mirror_target_get_transform(wlm_mirror_target_t * target);
41+
42+
void wlm_mirror_target_destroy(wlm_mirror_target_t * target);
43+
44+
#endif

include/wlm/wayland.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <wlm/proto/wlr-screencopy-unstable-v1.h>
1313
#include <wlm/proto/ext-image-copy-capture-v1.h>
1414
#include <wlm/proto/ext-image-capture-source-v1.h>
15+
#include <wlm/proto/ext-foreign-toplevel-list-v1.h>
1516
#include <wlm/proto/linux-dmabuf-unstable-v1.h>
1617
#include <wlm/wayland/shm.h>
1718
#include <wlm/wayland/dmabuf.h>
@@ -26,6 +27,9 @@ typedef struct output_list_node {
2627
struct output_list_node * next;
2728
struct ctx * ctx;
2829
char * name;
30+
char * make;
31+
char * model;
32+
char * description;
2933
struct wl_output * output;
3034
struct zxdg_output_v1 * xdg_output;
3135
uint32_t output_id;
@@ -129,6 +133,7 @@ void wlm_wayland_window_set_title(struct ctx * ctx, const char * title);
129133
void wlm_wayland_window_set_fullscreen(struct ctx * ctx);
130134
void wlm_wayland_window_unset_fullscreen(struct ctx * ctx);
131135
void wlm_wayland_window_update_scale(struct ctx * ctx, double scale, bool is_fractional);
136+
bool wlm_wayland_find_output(ctx_t * ctx, const char * output_name, output_list_node_t ** output);
132137
void wlm_wayland_cleanup(struct ctx * ctx);
133138

134139
#endif

src/egl.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "wlm/mirror/target.h"
12
#include <GLES2/gl2.h>
23
#include <GLES2/gl2ext.h>
34
#include <EGL/egl.h>
@@ -422,13 +423,17 @@ void wlm_egl_resize_viewport(ctx_t * ctx) {
422423

423424
// rotate texture dimensions by output transform
424425
if (ctx->egl.texture_initialized) {
425-
wlm_util_viewport_apply_output_transform(&tex_width, &tex_height, ctx->mirror.current_target->transform);
426+
enum wl_output_transform transform = wlm_mirror_target_get_transform(ctx->mirror.current_target);
427+
wlm_util_viewport_apply_output_transform(&tex_width, &tex_height, transform);
426428
}
427429

428430
// clamp texture dimensions to specified region
429431
region_t output_region;
430432
region_t clamp_region;
431433
if (ctx->egl.texture_initialized && ctx->opt.has_region && !ctx->egl.texture_region_aware) {
434+
// TODO: handle output regions differently
435+
// TODO: allow specifying regions relative to recording target
436+
432437
output_region = (region_t){
433438
.x = 0, .y = 0,
434439
.width = tex_width, .height = tex_height
@@ -437,7 +442,12 @@ void wlm_egl_resize_viewport(ctx_t * ctx) {
437442

438443
// HACK: calculate effective output fractional scale
439444
// wayland doesn't provide this information
440-
double output_scale = (double)tex_width / ctx->mirror.current_target->width;
445+
// TODO: figure out how to deal with this without hardcoding output targets
446+
double output_scale = 1;
447+
output_list_node_t * output_node = wlm_mirror_target_get_output_node(ctx->mirror.current_target);
448+
if (output_node != NULL) {
449+
output_scale = (double)tex_width / output_node->width;
450+
}
441451
wlm_util_region_scale(&clamp_region, output_scale);
442452
wlm_util_region_clamp(&clamp_region, &output_region);
443453

@@ -510,7 +520,8 @@ void wlm_egl_resize_viewport(ctx_t * ctx) {
510520
wlm_util_mat3_apply_region_transform(&texture_transform, &clamp_region, &output_region);
511521
}
512522

513-
wlm_util_mat3_apply_output_transform(&texture_transform, ctx->mirror.current_target->transform);
523+
enum wl_output_transform transform = wlm_mirror_target_get_transform(ctx->mirror.current_target);
524+
wlm_util_mat3_apply_output_transform(&texture_transform, transform);
514525
wlm_util_mat3_apply_invert_y(&texture_transform, ctx->mirror.invert_y);
515526
}
516527

src/mirror.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,16 @@ void wlm_mirror_init(ctx_t * ctx) {
7474

7575
ctx->mirror.initialized = true;
7676

77+
// TODO: use wlm_mirror_target_parse
78+
// TODO: make wlm_mirror_target_parse implement finding output (or toplevel?) by region
79+
// TODO: only find and create target in a single place! (other place is opt parse)
7780
// finding target output
78-
if (!wlm_opt_find_output(ctx, &ctx->mirror.current_target, &ctx->mirror.current_region)) {
81+
output_list_node_t * target_output = NULL;
82+
if (!wlm_opt_find_output(ctx, &target_output, &ctx->mirror.current_region)) {
7983
wlm_log_error("mirror::init(): failed to find output\n");
8084
wlm_exit_fail(ctx);
8185
}
86+
ctx->mirror.current_target = wlm_mirror_target_create_output(ctx, target_output);
8287

8388
// update window title
8489
wlm_mirror_update_title(ctx);
@@ -201,7 +206,7 @@ void wlm_mirror_backend_init(ctx_t * ctx) {
201206
void wlm_mirror_output_removed(ctx_t * ctx, output_list_node_t * node) {
202207
if (!ctx->mirror.initialized) return;
203208
if (ctx->mirror.current_target == NULL) return;
204-
if (ctx->mirror.current_target != node) return;
209+
if (wlm_mirror_target_get_output_node(ctx->mirror.current_target) != node) return;
205210

206211
wlm_log_error("mirror::output_removed(): output disappeared, closing\n");
207212
wlm_exit_fail(ctx);
@@ -228,14 +233,26 @@ static size_t specifier_str(ctx_t * ctx, char *dst, int n, specifier_t specifier
228233
}
229234

230235
static int format_title(ctx_t * ctx, char ** dst, char * fmt) {
236+
uint32_t target_width = 0;
237+
uint32_t target_height = 0;
238+
const char * target_name = "";
239+
240+
// TODO: support for other target types
241+
output_list_node_t * output_node = wlm_mirror_target_get_output_node(ctx->mirror.current_target);
242+
if (output_node != NULL) {
243+
target_width = output_node->width;
244+
target_height = output_node->height;
245+
target_name = output_node->name;
246+
}
247+
231248
specifier_t replacements[] = {
232249
{"{x}", 'd', {.d = ctx->mirror.current_region.x}},
233250
{"{y}", 'd', {.d = ctx->mirror.current_region.y}},
234251
{"{width}", 'd', {.d = ctx->mirror.current_region.width}},
235252
{"{height}", 'd', {.d = ctx->mirror.current_region.height}},
236-
{"{target_width}", 'd', {.d = ctx->mirror.current_target->width}},
237-
{"{target_height}", 'd', {.d = ctx->mirror.current_target->height}},
238-
{"{target_output}", 's', {.s = ctx->mirror.current_target->name}}
253+
{"{target_width}", 'd', {.d = target_width}},
254+
{"{target_height}", 'd', {.d = target_height}},
255+
{"{target_output}", 's', {.s = target_name}}
239256
};
240257

241258
size_t length = strlen(fmt);
@@ -321,6 +338,7 @@ void wlm_mirror_cleanup(ctx_t * ctx) {
321338

322339
wlm_log_debug(ctx, "mirror::cleanup(): destroying mirror objects\n");
323340

341+
if (ctx->mirror.current_target != NULL) wlm_mirror_target_destroy(ctx->mirror.current_target);
324342
if (ctx->mirror.backend != NULL) ctx->mirror.backend->do_cleanup(ctx);
325343
if (ctx->mirror.frame_callback != NULL) wl_callback_destroy(ctx->mirror.frame_callback);
326344

src/mirror/export-dmabuf.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,17 @@ static void do_capture(ctx_t * ctx) {
248248
backend->state = STATE_WAIT_FRAME;
249249
backend->processed_objects = 0;
250250

251+
// check if target is supported
252+
output_list_node_t * output_node = wlm_mirror_target_get_output_node(ctx->mirror.current_target);
253+
if (output_node == NULL) {
254+
wlm_log_error("mirror-export-dmabuf::do_capture(): capture target not supported by this backend\n");
255+
wlm_mirror_backend_fail(ctx);
256+
return;
257+
}
258+
251259
// create wlr_dmabuf_export_frame
252260
backend->dmabuf_frame = zwlr_export_dmabuf_manager_v1_capture_output(
253-
ctx->wl.dmabuf_manager, ctx->opt.show_cursor, ctx->mirror.current_target->output
261+
ctx->wl.dmabuf_manager, ctx->opt.show_cursor, output_node->output
254262
);
255263
if (backend->dmabuf_frame == NULL) {
256264
wlm_log_error("mirror-export-dmabuf::do_capture(): failed to create wlr_dmabuf_export_frame\n");

src/mirror/extcopy.c

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include "wlm/mirror/target.h"
12
#include <wlm/mirror/extcopy.h>
23
#include <wlm/context.h>
34
#include <wlm/wayland/shm.h>
@@ -28,12 +29,10 @@ static void extcopy_session_cleanup(ctx_t * ctx, extcopy_mirror_backend_t * back
2829
extcopy_frame_cleanup(backend);
2930

3031
if (backend->capture_session != NULL) ext_image_copy_capture_session_v1_destroy(backend->capture_session);
31-
if (backend->capture_source != NULL) ext_image_capture_source_v1_destroy(backend->capture_source);
3232
if (wlm_wayland_dmabuf_get_buffer(ctx) != NULL) wlm_wayland_dmabuf_dealloc(ctx);
3333
if (wlm_wayland_shm_get_buffer(ctx) != NULL) wlm_wayland_shm_dealloc(ctx);
3434

3535
backend->capture_session = NULL;
36-
backend->capture_source = NULL;
3736
}
3837

3938
static void backend_cancel(ctx_t * ctx, extcopy_mirror_backend_t * backend) {
@@ -354,11 +353,17 @@ static void do_capture(ctx_t * ctx) {
354353
extcopy_mirror_backend_t * backend = (extcopy_mirror_backend_t *)ctx->mirror.backend;
355354

356355
if (backend->state == STATE_INIT || backend->state == STATE_CANCELED) {
357-
backend->capture_source = ext_output_image_capture_source_manager_v1_create_source(ctx->wl.output_capture_source_manager, ctx->mirror.current_target->output);
356+
// check if target is supported
357+
struct ext_image_capture_source_v1 * capture_source = wlm_mirror_target_get_capture_source(ctx->mirror.current_target);
358+
if (capture_source == NULL) {
359+
wlm_log_error("mirror-extcopy::do_capture(): capture target not supported by this backend\n");
360+
wlm_mirror_backend_fail(ctx);
361+
return;
362+
}
358363

359364
wlm_log_debug(ctx, "mirror-extcopy::do_capture(): creating capture session\n");
360365
backend->state = STATE_WAIT_BUFFER_INFO;
361-
backend->capture_session = ext_image_copy_capture_manager_v1_create_session(ctx->wl.copy_capture_manager, backend->capture_source, ctx->opt.show_cursor ? EXT_IMAGE_COPY_CAPTURE_MANAGER_V1_OPTIONS_PAINT_CURSORS : 0);
366+
backend->capture_session = ext_image_copy_capture_manager_v1_create_session(ctx->wl.copy_capture_manager, capture_source, ctx->opt.show_cursor ? EXT_IMAGE_COPY_CAPTURE_MANAGER_V1_OPTIONS_PAINT_CURSORS : 0);
362367
ext_image_copy_capture_session_v1_add_listener(backend->capture_session, &capture_session_listener, (void *)ctx);
363368
} else if (backend->state == STATE_READY) {
364369
if (backend->capture_frame != NULL) {
@@ -438,7 +443,6 @@ static void wlm_mirror_extcopy_init(ctx_t * ctx, bool use_dmabuf) {
438443
backend->header.fail_count = 0;
439444
backend->use_dmabuf = use_dmabuf;
440445

441-
backend->capture_source = NULL;
442446
backend->capture_session = NULL;
443447
backend->capture_frame = NULL;
444448

src/mirror/screencopy.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,18 +281,26 @@ static void do_capture(ctx_t * ctx) {
281281
backend->frame_flags = 0;
282282
backend->state = STATE_WAIT_BUFFER;
283283

284+
// check if target is supported
285+
output_list_node_t * output_node = wlm_mirror_target_get_output_node(ctx->mirror.current_target);
286+
if (output_node == NULL) {
287+
wlm_log_error("mirror-screencopy::do_capture(): capture target not supported by this backend\n");
288+
wlm_mirror_backend_fail(ctx);
289+
return;
290+
}
291+
284292
// create screencopy_frame
285293
if (ctx->opt.has_region) {
286294
backend->screencopy_frame = zwlr_screencopy_manager_v1_capture_output_region(
287-
ctx->wl.screencopy_manager, ctx->opt.show_cursor, ctx->mirror.current_target->output,
288-
ctx->mirror.current_target->x + ctx->mirror.current_region.x,
289-
ctx->mirror.current_target->y + ctx->mirror.current_region.y,
295+
ctx->wl.screencopy_manager, ctx->opt.show_cursor, output_node->output,
296+
output_node->x + ctx->mirror.current_region.x,
297+
output_node->y + ctx->mirror.current_region.y,
290298
ctx->mirror.current_region.width,
291299
ctx->mirror.current_region.height
292300
);
293301
} else {
294302
backend->screencopy_frame = zwlr_screencopy_manager_v1_capture_output(
295-
ctx->wl.screencopy_manager, ctx->opt.show_cursor, ctx->mirror.current_target->output
303+
ctx->wl.screencopy_manager, ctx->opt.show_cursor, output_node->output
296304
);
297305
}
298306
if (backend->screencopy_frame == NULL) {

0 commit comments

Comments
 (0)