aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Drew DeVault <sir@cmpwn.com>2018-04-07 12:23:26 -0400
committerLibravatar GitHub <noreply@github.com>2018-04-07 12:23:26 -0400
commitb12b848bdcc92b12bd3db29e84b3a719b268abf3 (patch)
tree30460351cbb57a25f4cd809a6d21e4475641de0e
parentMerge pull request #1765 from emersion/fix-bad-assert (diff)
parentDon't send frame done immediately when rendering (diff)
downloadsway-b12b848bdcc92b12bd3db29e84b3a719b268abf3.tar.gz
sway-b12b848bdcc92b12bd3db29e84b3a719b268abf3.tar.zst
sway-b12b848bdcc92b12bd3db29e84b3a719b268abf3.zip
Merge pull request #1759 from emersion/output-send-frame-done
Don't send frame done immediately when rendering
-rw-r--r--sway/desktop/output.c223
1 files changed, 144 insertions, 79 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index dea51bdf..1b3143d0 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -66,6 +66,10 @@ struct root_geometry {
66static bool get_surface_box(struct root_geometry *geo, 66static bool get_surface_box(struct root_geometry *geo,
67 struct sway_output *output, struct wlr_surface *surface, int sx, int sy, 67 struct sway_output *output, struct wlr_surface *surface, int sx, int sy,
68 struct wlr_box *surface_box) { 68 struct wlr_box *surface_box) {
69 if (!wlr_surface_has_buffer(surface)) {
70 return false;
71 }
72
69 int sw = surface->current->width; 73 int sw = surface->current->width;
70 int sh = surface->current->height; 74 int sh = surface->current->height;
71 75
@@ -95,7 +99,7 @@ static bool get_surface_box(struct root_geometry *geo,
95 return wlr_box_intersection(&output_box, &rotated_box, &intersection); 99 return wlr_box_intersection(&output_box, &rotated_box, &intersection);
96} 100}
97 101
98static void output_surface_for_each_surface(struct wlr_surface *surface, 102static void surface_for_each_surface(struct wlr_surface *surface,
99 double ox, double oy, struct root_geometry *geo, 103 double ox, double oy, struct root_geometry *geo,
100 wlr_surface_iterator_func_t iterator, void *user_data) { 104 wlr_surface_iterator_func_t iterator, void *user_data) {
101 geo->x = ox; 105 geo->x = ox;
@@ -119,6 +123,34 @@ static void output_view_for_each_surface(struct sway_view *view,
119 view_for_each_surface(view, iterator, user_data); 123 view_for_each_surface(view, iterator, user_data);
120} 124}
121 125
126static void layer_for_each_surface(struct wl_list *layer_surfaces,
127 struct root_geometry *geo, wlr_surface_iterator_func_t iterator,
128 void *user_data) {
129 struct sway_layer_surface *layer_surface;
130 wl_list_for_each(layer_surface, layer_surfaces, link) {
131 struct wlr_layer_surface *wlr_layer_surface =
132 layer_surface->layer_surface;
133 surface_for_each_surface(wlr_layer_surface->surface,
134 layer_surface->geo.x, layer_surface->geo.y, geo, iterator,
135 user_data);
136 }
137}
138
139static void unmanaged_for_each_surface(struct wl_list *unmanaged,
140 struct sway_output *output, struct root_geometry *geo,
141 wlr_surface_iterator_func_t iterator, void *user_data) {
142 struct sway_xwayland_unmanaged *unmanaged_surface;
143 wl_list_for_each(unmanaged_surface, unmanaged, link) {
144 struct wlr_xwayland_surface *xsurface =
145 unmanaged_surface->wlr_xwayland_surface;
146 double ox = unmanaged_surface->lx - output->swayc->x;
147 double oy = unmanaged_surface->ly - output->swayc->y;
148
149 surface_for_each_surface(xsurface->surface, ox, oy, geo,
150 iterator, user_data);
151 }
152}
153
122static void scale_box(struct wlr_box *box, float scale) { 154static void scale_box(struct wlr_box *box, float scale) {
123 box->x *= scale; 155 box->x *= scale;
124 box->y *= scale; 156 box->y *= scale;
@@ -129,7 +161,6 @@ static void scale_box(struct wlr_box *box, float scale) {
129struct render_data { 161struct render_data {
130 struct root_geometry root_geo; 162 struct root_geometry root_geo;
131 struct sway_output *output; 163 struct sway_output *output;
132 struct timespec *when;
133 float alpha; 164 float alpha;
134}; 165};
135 166
@@ -137,7 +168,6 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
137 void *_data) { 168 void *_data) {
138 struct render_data *data = _data; 169 struct render_data *data = _data;
139 struct wlr_output *wlr_output = data->output->wlr_output; 170 struct wlr_output *wlr_output = data->output->wlr_output;
140 struct timespec *when = data->when;
141 float rotation = data->root_geo.rotation; 171 float rotation = data->root_geo.rotation;
142 float alpha = data->alpha; 172 float alpha = data->alpha;
143 173
@@ -169,59 +199,52 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
169 199
170 wlr_render_texture_with_matrix(renderer, surface->texture, 200 wlr_render_texture_with_matrix(renderer, surface->texture,
171 matrix, alpha); 201 matrix, alpha);
172
173 // TODO: don't send the frame done event now
174 wlr_surface_send_frame_done(surface, when);
175} 202}
176 203
177static void render_surface(struct sway_output *output, struct timespec *when, 204static void render_layer(struct sway_output *output,
178 struct wlr_surface *surface, double ox, double oy) { 205 struct wl_list *layer_surfaces) {
179 struct render_data data = { 206 struct render_data data = { .output = output, .alpha = 1.0f };
180 .output = output, 207 layer_for_each_surface(layer_surfaces, &data.root_geo,
181 .when = when,
182 .alpha = 1.0f,
183 };
184
185 output_surface_for_each_surface(surface, ox, oy, &data.root_geo,
186 render_surface_iterator, &data); 208 render_surface_iterator, &data);
187} 209}
188 210
189static void render_view(struct sway_output *output, struct timespec *when, 211static void render_unmanaged(struct sway_output *output,
190 struct sway_view *view) { 212 struct wl_list *unmanaged) {
191 struct render_data data = { 213 struct render_data data = { .output = output, .alpha = 1.0f };
192 .output = output, 214 unmanaged_for_each_surface(unmanaged, output, &data.root_geo,
193 .when = when,
194 .alpha = view->swayc->alpha,
195 };
196
197 output_view_for_each_surface(view, &data.root_geo,
198 render_surface_iterator, &data); 215 render_surface_iterator, &data);
199} 216}
200 217
201static void render_layer(struct sway_output *output, struct timespec *when, 218static void render_container_iterator(struct sway_container *con,
202 struct wl_list *layer_surfaces) { 219 void *_data) {
203 struct sway_layer_surface *layer_surface; 220 struct sway_output *output = _data;
204 wl_list_for_each(layer_surface, layer_surfaces, link) { 221 if (!sway_assert(con->type == C_VIEW, "expected a view")) {
205 struct wlr_layer_surface *wlr_layer_surface = 222 return;
206 layer_surface->layer_surface;
207 render_surface(output, when, wlr_layer_surface->surface,
208 layer_surface->geo.x, layer_surface->geo.y);
209 } 223 }
224 struct render_data data = { .output = output, .alpha = con->alpha };
225 output_view_for_each_surface(con->sway_view, &data.root_geo,
226 render_surface_iterator, &data);
210} 227}
211 228
212struct render_view_data { 229static void render_container(struct sway_output *output,
213 struct sway_output *output; 230 struct sway_container *con) {
214 struct timespec *when; 231 container_descendants(con, C_VIEW, render_container_iterator, output);
215}; 232}
216
217static void render_view_iterator(struct sway_container *con, void *_data) {
218 struct render_view_data *data = _data;
219 233
220 if (!sway_assert(con->type == C_VIEW, "expected a view")) { 234static struct sway_container *output_get_active_workspace(
221 return; 235 struct sway_output *output) {
236 struct sway_seat *seat = input_manager_current_seat(input_manager);
237 struct sway_container *focus =
238 seat_get_focus_inactive(seat, output->swayc);
239 if (!focus) {
240 // We've never been to this output before
241 focus = output->swayc->children->items[0];
222 } 242 }
223 243 struct sway_container *workspace = focus;
224 render_view(data->output, data->when, con->sway_view); 244 if (workspace->type != C_WORKSPACE) {
245 workspace = container_parent(workspace, C_WORKSPACE);
246 }
247 return workspace;
225} 248}
226 249
227static void render_output(struct sway_output *output, struct timespec *when, 250static void render_output(struct sway_output *output, struct timespec *when,
@@ -250,40 +273,17 @@ static void render_output(struct sway_output *output, struct timespec *when,
250 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; 273 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
251 wlr_renderer_clear(renderer, clear_color); 274 wlr_renderer_clear(renderer, clear_color);
252 275
253 render_layer(output, when, 276 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
254 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); 277 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
255 render_layer(output, when,
256 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
257 278
258 // Render all views in the current workspace 279 struct sway_container *workspace = output_get_active_workspace(output);
259 struct sway_seat *seat = input_manager_current_seat(input_manager); 280 render_container(output, workspace);
260 struct sway_container *focus =
261 seat_get_focus_inactive(seat, output->swayc);
262 if (!focus) {
263 // We've never been to this output before
264 focus = output->swayc->children->items[0];
265 }
266 struct sway_container *workspace = focus->type == C_WORKSPACE ?
267 focus : container_parent(focus, C_WORKSPACE);
268 struct render_view_data data = { .output = output, .when = when };
269 container_descendants(workspace, C_VIEW, render_view_iterator, &data);
270 281
271 // Render unmanaged views on top 282 render_unmanaged(output, &root_container.sway_root->xwayland_unmanaged);
272 struct wl_list *unmanaged = &root_container.sway_root->xwayland_unmanaged;
273 struct sway_xwayland_unmanaged *unmanaged_surface;
274 wl_list_for_each(unmanaged_surface, unmanaged, link) {
275 struct wlr_xwayland_surface *xsurface =
276 unmanaged_surface->wlr_xwayland_surface;
277 double ox = unmanaged_surface->lx - output->swayc->x;
278 double oy = unmanaged_surface->ly - output->swayc->y;
279 render_surface(output, when, xsurface->surface, ox, oy);
280 }
281 283
282 // TODO: consider revising this when fullscreen windows are supported 284 // TODO: consider revising this when fullscreen windows are supported
283 render_layer(output, when, 285 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
284 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); 286 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
285 render_layer(output, when,
286 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
287 287
288renderer_end: 288renderer_end:
289 if (root_container.sway_root->debug_tree) { 289 if (root_container.sway_root->debug_tree) {
@@ -298,6 +298,74 @@ renderer_end:
298 output->last_frame = *when; 298 output->last_frame = *when;
299} 299}
300 300
301struct send_frame_done_data {
302 struct root_geometry root_geo;
303 struct sway_output *output;
304 struct timespec *when;
305};
306
307static void send_frame_done_iterator(struct wlr_surface *surface,
308 int sx, int sy, void *_data) {
309 struct send_frame_done_data *data = _data;
310
311 bool intersects = get_surface_box(&data->root_geo, data->output, surface,
312 sx, sy, NULL);
313 if (intersects) {
314 wlr_surface_send_frame_done(surface, data->when);
315 }
316}
317
318static void send_frame_done_layer(struct send_frame_done_data *data,
319 struct wl_list *layer_surfaces) {
320 layer_for_each_surface(layer_surfaces, &data->root_geo,
321 send_frame_done_iterator, data);
322}
323
324static void send_frame_done_unmanaged(struct send_frame_done_data *data,
325 struct wl_list *unmanaged) {
326 unmanaged_for_each_surface(unmanaged, data->output, &data->root_geo,
327 send_frame_done_iterator, data);
328}
329
330static void send_frame_done_container_iterator(struct sway_container *con,
331 void *_data) {
332 struct send_frame_done_data *data = _data;
333 if (!sway_assert(con->type == C_VIEW, "expected a view")) {
334 return;
335 }
336 output_view_for_each_surface(con->sway_view, &data->root_geo,
337 send_frame_done_iterator, data);
338}
339
340static void send_frame_done_container(struct send_frame_done_data *data,
341 struct sway_container *con) {
342 container_descendants(con, C_VIEW,
343 send_frame_done_container_iterator, data);
344}
345
346static void send_frame_done(struct sway_output *output, struct timespec *when) {
347 struct send_frame_done_data data = {
348 .output = output,
349 .when = when,
350 };
351
352 send_frame_done_layer(&data,
353 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
354 send_frame_done_layer(&data,
355 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
356
357 struct sway_container *workspace = output_get_active_workspace(output);
358 send_frame_done_container(&data, workspace);
359
360 send_frame_done_unmanaged(&data,
361 &root_container.sway_root->xwayland_unmanaged);
362
363 send_frame_done_layer(&data,
364 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
365 send_frame_done_layer(&data,
366 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
367}
368
301static void damage_handle_frame(struct wl_listener *listener, void *data) { 369static void damage_handle_frame(struct wl_listener *listener, void *data) {
302 struct sway_output *output = 370 struct sway_output *output =
303 wl_container_of(listener, output, damage_frame); 371 wl_container_of(listener, output, damage_frame);
@@ -322,7 +390,8 @@ static void damage_handle_frame(struct wl_listener *listener, void *data) {
322 390
323 pixman_region32_fini(&damage); 391 pixman_region32_fini(&damage);
324 392
325 // TODO: send frame done events here instead of inside render_surface 393 // Send frame done to all visible surfaces
394 send_frame_done(output, &now);
326} 395}
327 396
328void output_damage_whole(struct sway_output *output) { 397void output_damage_whole(struct sway_output *output) {
@@ -342,10 +411,6 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy,
342 float rotation = data->root_geo.rotation; 411 float rotation = data->root_geo.rotation;
343 bool whole = data->whole; 412 bool whole = data->whole;
344 413
345 if (!wlr_surface_has_buffer(surface)) {
346 return;
347 }
348
349 struct wlr_box box; 414 struct wlr_box box;
350 bool intersects = get_surface_box(&data->root_geo, data->output, surface, 415 bool intersects = get_surface_box(&data->root_geo, data->output, surface,
351 sx, sy, &box); 416 sx, sy, &box);
@@ -387,7 +452,7 @@ void output_damage_surface(struct sway_output *output, double ox, double oy,
387 .whole = whole, 452 .whole = whole,
388 }; 453 };
389 454
390 output_surface_for_each_surface(surface, ox, oy, &data.root_geo, 455 surface_for_each_surface(surface, ox, oy, &data.root_geo,
391 damage_surface_iterator, &data); 456 damage_surface_iterator, &data);
392} 457}
393 458