diff options
author | emersion <contact@emersion.fr> | 2018-04-06 17:37:48 -0400 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-04-07 12:10:50 -0400 |
commit | 8af0c2b00074879335f6e224512667947ca234cf (patch) | |
tree | 5a28be4714a9db82614510d605127794eed4610a | |
parent | Merge pull request #1756 from emersion/output-damage (diff) | |
download | sway-8af0c2b00074879335f6e224512667947ca234cf.tar.gz sway-8af0c2b00074879335f6e224512667947ca234cf.tar.zst sway-8af0c2b00074879335f6e224512667947ca234cf.zip |
Don't send frame done immediately when rendering
-rw-r--r-- | sway/desktop/output.c | 223 |
1 files changed, 144 insertions, 79 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 23d20b79..1a72b5db 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -66,6 +66,10 @@ struct root_geometry { | |||
66 | static bool get_surface_box(struct root_geometry *geo, | 66 | static 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 | ||
98 | static void output_surface_for_each_surface(struct wlr_surface *surface, | 102 | static 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 | ||
126 | static 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 | |||
139 | static 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 | |||
122 | static void scale_box(struct wlr_box *box, float scale) { | 154 | static 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) { | |||
129 | struct render_data { | 161 | struct 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 | ||
177 | static void render_surface(struct sway_output *output, struct timespec *when, | 204 | static 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 | ||
189 | static void render_view(struct sway_output *output, struct timespec *when, | 211 | static 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 | ||
201 | static void render_layer(struct sway_output *output, struct timespec *when, | 218 | static 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 | ||
212 | struct render_view_data { | 229 | static 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 | |||
217 | static 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")) { | 234 | static 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 | ||
227 | static void render_output(struct sway_output *output, struct timespec *when, | 250 | static 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 | ||
288 | renderer_end: | 288 | renderer_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 | ||
301 | struct send_frame_done_data { | ||
302 | struct root_geometry root_geo; | ||
303 | struct sway_output *output; | ||
304 | struct timespec *when; | ||
305 | }; | ||
306 | |||
307 | static 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 | |||
318 | static 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 | |||
324 | static 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 | |||
330 | static 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 | |||
340 | static 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 | |||
346 | static 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 | |||
301 | static void damage_handle_frame(struct wl_listener *listener, void *data) { | 369 | static 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 | ||
328 | void output_damage_whole(struct sway_output *output) { | 397 | void 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 | ||