1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
#include "wm.h"
typedef struct Payload Payload;
struct Payload
{
Client *client;
struct wlr_output *output;
struct wlr_renderer *renderer;
struct timespec *when;
};
static
void
draw(struct wlr_surface *surface, int sx, int sy, void *data)
{
float matrix[9];
double ox, oy;
Client *client;
Payload *payload;
struct wlr_box box;
struct wlr_output *output;
struct wlr_texture *texture;
enum wl_output_transform transform;
payload = data;
client = payload->client;
output = payload->output;
texture = wlr_surface_get_texture(surface);
if(!texture)
return;
ox = 0, oy = 0;
wlr_output_layout_output_coords(server.output.layout, output, &ox, &oy);
ox += client->x + sx, oy += client->y + sy;
box = (struct wlr_box){
.x = ox * output->scale,
.y = oy * output->scale,
.width = surface->current.width * output->scale,
.height = surface->current.height * output->scale,
};
transform = wlr_output_transform_invert(surface->current.transform);
wlr_matrix_project_box(matrix, &box, transform, 0, output->transform_matrix);
wlr_render_texture_with_matrix(payload->renderer, texture, matrix, 1);
wlr_surface_send_frame_done(surface, payload->when);
}
static
void
render(struct wl_listener *l, void *data)
{
int width, height;
struct timespec now;
Client *client;
Monitor *monitor;
struct wlr_renderer *renderer;
float color[4] = {0.3, 0.3, 0.3, 1.0};
monitor = wl_container_of(l, monitor, event.render);
renderer = server.renderer;
clock_gettime(CLOCK_MONOTONIC, &now);
if(!wlr_output_attach_render(monitor->output, nil))
return;
wlr_output_effective_resolution(monitor->output, &width, &height);
/* start of rendering kernel */
wlr_renderer_begin(renderer, width, height);
wlr_renderer_clear(renderer, color);
wl_list_for_each_reverse(client, &server.clients, link) {
if(!client->mapped)
continue;
Payload payload = {
.output = monitor->output,
.client = client,
.renderer = renderer,
.when = &now,
};
wlr_xdg_surface_for_each_surface(client->xdg, draw, &payload);
}
wlr_output_render_software_cursors(monitor->output, nil);
wlr_renderer_end(renderer);
wlr_output_commit(monitor->output);
}
void
make_output(struct wl_listener *l, void *data)
{
struct wlr_output_mode *mode;
struct Monitor *monitor;
struct wlr_output *output = data;
if (!wl_list_empty(&output->modes)) {
mode = wlr_output_preferred_mode(output);
wlr_output_set_mode(output, mode);
wlr_output_enable(output, true);
if (!wlr_output_commit(output)) {
return;
}
}
monitor = calloc(1, sizeof(*monitor));
monitor->output = output;
monitor->event.render.notify = render;
wl_signal_add(&output->events.frame, &monitor->event.render);
wl_list_insert(&server.output.list, &monitor->link);
wlr_output_layout_add_auto(server.output.layout, output);
}
|