diff options
author | emersion <contact@emersion.fr> | 2018-03-30 13:18:50 -0400 |
---|---|---|
committer | emersion <contact@emersion.fr> | 2018-03-30 17:16:35 -0400 |
commit | a776ecbb860608e0f75430a53ea75a6ed19ac746 (patch) | |
tree | f664978ac74c3fc13993ed709cc1015c025d3344 /sway/desktop/output.c | |
parent | Merge pull request #1667 from emersion/wlroots-xwayland-map (diff) | |
download | sway-a776ecbb860608e0f75430a53ea75a6ed19ac746.tar.gz sway-a776ecbb860608e0f75430a53ea75a6ed19ac746.tar.zst sway-a776ecbb860608e0f75430a53ea75a6ed19ac746.zip |
Add lite damage tracking
This skips the renderer if nothing has changed, and renders
everything otherwise.
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 148 |
1 files changed, 103 insertions, 45 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index f3416c03..ea457996 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -6,18 +6,19 @@ | |||
6 | #include <wlr/render/wlr_renderer.h> | 6 | #include <wlr/render/wlr_renderer.h> |
7 | #include <wlr/types/wlr_box.h> | 7 | #include <wlr/types/wlr_box.h> |
8 | #include <wlr/types/wlr_matrix.h> | 8 | #include <wlr/types/wlr_matrix.h> |
9 | #include <wlr/types/wlr_output.h> | 9 | #include <wlr/types/wlr_output_damage.h> |
10 | #include <wlr/types/wlr_output_layout.h> | 10 | #include <wlr/types/wlr_output_layout.h> |
11 | #include <wlr/types/wlr_output.h> | ||
11 | #include <wlr/types/wlr_surface.h> | 12 | #include <wlr/types/wlr_surface.h> |
12 | #include <wlr/types/wlr_wl_shell.h> | 13 | #include <wlr/types/wlr_wl_shell.h> |
13 | #include "log.h" | 14 | #include "log.h" |
14 | #include "sway/tree/container.h" | ||
15 | #include "sway/input/input-manager.h" | 15 | #include "sway/input/input-manager.h" |
16 | #include "sway/input/seat.h" | 16 | #include "sway/input/seat.h" |
17 | #include "sway/layers.h" | 17 | #include "sway/layers.h" |
18 | #include "sway/tree/layout.h" | ||
19 | #include "sway/output.h" | 18 | #include "sway/output.h" |
20 | #include "sway/server.h" | 19 | #include "sway/server.h" |
20 | #include "sway/tree/container.h" | ||
21 | #include "sway/tree/layout.h" | ||
21 | #include "sway/tree/view.h" | 22 | #include "sway/tree/view.h" |
22 | 23 | ||
23 | /** | 24 | /** |
@@ -145,13 +146,13 @@ static void render_wl_shell_surface(struct wlr_wl_shell_surface *surface, | |||
145 | 146 | ||
146 | struct render_data { | 147 | struct render_data { |
147 | struct sway_output *output; | 148 | struct sway_output *output; |
148 | struct timespec *now; | 149 | struct timespec *when; |
149 | }; | 150 | }; |
150 | 151 | ||
151 | static void output_frame_view(struct sway_container *view, void *data) { | 152 | static void render_view(struct sway_container *view, void *data) { |
152 | struct render_data *rdata = data; | 153 | struct render_data *rdata = data; |
153 | struct sway_output *output = rdata->output; | 154 | struct sway_output *output = rdata->output; |
154 | struct timespec *now = rdata->now; | 155 | struct timespec *when = rdata->when; |
155 | struct wlr_output *wlr_output = output->wlr_output; | 156 | struct wlr_output *wlr_output = output->wlr_output; |
156 | struct sway_view *sway_view = view->sway_view; | 157 | struct sway_view *sway_view = view->sway_view; |
157 | struct wlr_surface *surface = sway_view->surface; | 158 | struct wlr_surface *surface = sway_view->surface; |
@@ -164,18 +165,18 @@ static void output_frame_view(struct sway_container *view, void *data) { | |||
164 | case SWAY_XDG_SHELL_V6_VIEW: { | 165 | case SWAY_XDG_SHELL_V6_VIEW: { |
165 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; | 166 | int window_offset_x = view->sway_view->wlr_xdg_surface_v6->geometry.x; |
166 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; | 167 | int window_offset_y = view->sway_view->wlr_xdg_surface_v6->geometry.y; |
167 | render_surface(surface, wlr_output, now, | 168 | render_surface(surface, wlr_output, when, |
168 | view->x - window_offset_x, view->y - window_offset_y, 0); | 169 | view->x - window_offset_x, view->y - window_offset_y, 0); |
169 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, | 170 | render_xdg_v6_popups(sway_view->wlr_xdg_surface_v6, wlr_output, |
170 | now, view->x - window_offset_x, view->y - window_offset_y, 0); | 171 | when, view->x - window_offset_x, view->y - window_offset_y, 0); |
171 | break; | 172 | break; |
172 | } | 173 | } |
173 | case SWAY_WL_SHELL_VIEW: | 174 | case SWAY_WL_SHELL_VIEW: |
174 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, | 175 | render_wl_shell_surface(sway_view->wlr_wl_shell_surface, wlr_output, |
175 | now, view->x, view->y, 0, false); | 176 | when, view->x, view->y, 0, false); |
176 | break; | 177 | break; |
177 | case SWAY_XWAYLAND_VIEW: | 178 | case SWAY_XWAYLAND_VIEW: |
178 | render_surface(surface, wlr_output, now, view->x, view->y, 0); | 179 | render_surface(surface, wlr_output, when, view->x, view->y, 0); |
179 | break; | 180 | break; |
180 | default: | 181 | default: |
181 | break; | 182 | break; |
@@ -195,82 +196,134 @@ static void render_layer(struct sway_output *output, | |||
195 | } | 196 | } |
196 | } | 197 | } |
197 | 198 | ||
198 | static void handle_output_frame(struct wl_listener *listener, void *data) { | 199 | static void render_output(struct sway_output *output, struct timespec *when, |
199 | struct sway_output *soutput = wl_container_of(listener, soutput, frame); | 200 | pixman_region32_t *damage) { |
200 | struct wlr_output *wlr_output = data; | 201 | wlr_log(L_DEBUG, "render"); |
202 | struct wlr_output *wlr_output = output->wlr_output; | ||
201 | struct wlr_renderer *renderer = | 203 | struct wlr_renderer *renderer = |
202 | wlr_backend_get_renderer(wlr_output->backend); | 204 | wlr_backend_get_renderer(wlr_output->backend); |
203 | 205 | ||
204 | wlr_output_make_current(wlr_output, NULL); | ||
205 | wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); | 206 | wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height); |
206 | 207 | ||
208 | if (!pixman_region32_not_empty(damage)) { | ||
209 | // Output isn't damaged but needs buffer swap | ||
210 | goto renderer_end; | ||
211 | } | ||
212 | |||
213 | // TODO | ||
214 | int width, height; | ||
215 | wlr_output_transformed_resolution(wlr_output, &width, &height); | ||
216 | pixman_region32_union_rect(damage, damage, 0, 0, width, height); | ||
217 | |||
207 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 218 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
208 | wlr_renderer_clear(renderer, clear_color); | 219 | wlr_renderer_clear(renderer, clear_color); |
209 | 220 | ||
210 | struct timespec now; | ||
211 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
212 | |||
213 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; | 221 | struct wlr_output_layout *layout = root_container.sway_root->output_layout; |
214 | const struct wlr_box *output_box = wlr_output_layout_get_box( | 222 | const struct wlr_box *output_box = |
215 | layout, wlr_output); | 223 | wlr_output_layout_get_box(layout, wlr_output); |
216 | 224 | ||
217 | render_layer(soutput, output_box, &now, | 225 | render_layer(output, output_box, when, |
218 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | 226 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); |
219 | render_layer(soutput, output_box, &now, | 227 | render_layer(output, output_box, when, |
220 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 228 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); |
221 | 229 | ||
222 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 230 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
223 | struct sway_container *focus = | 231 | struct sway_container *focus = |
224 | sway_seat_get_focus_inactive(seat, soutput->swayc); | 232 | sway_seat_get_focus_inactive(seat, output->swayc); |
225 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? | 233 | struct sway_container *workspace = (focus->type == C_WORKSPACE ? |
226 | focus : | 234 | focus : |
227 | container_parent(focus, C_WORKSPACE)); | 235 | container_parent(focus, C_WORKSPACE)); |
228 | 236 | ||
229 | struct render_data rdata = { | 237 | struct render_data rdata = { |
230 | .output = soutput, | 238 | .output = output, |
231 | .now = &now, | 239 | .when = when, |
232 | }; | 240 | }; |
233 | container_descendants(workspace, C_VIEW, output_frame_view, &rdata); | 241 | container_descendants(workspace, C_VIEW, render_view, &rdata); |
234 | 242 | ||
235 | // render unmanaged views on top | 243 | // render unmanaged views on top |
236 | struct sway_view *view; | 244 | struct sway_view *view; |
237 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, | 245 | wl_list_for_each(view, &root_container.sway_root->unmanaged_views, |
238 | unmanaged_view_link) { | 246 | unmanaged_view_link) { |
239 | if (view->type == SWAY_XWAYLAND_VIEW) { | 247 | if (view->type == SWAY_XWAYLAND_VIEW) { |
240 | // the only kind of unamanged view right now is xwayland override redirect | 248 | // the only kind of unamanged view right now is xwayland override |
249 | // redirect | ||
241 | int view_x = view->wlr_xwayland_surface->x; | 250 | int view_x = view->wlr_xwayland_surface->x; |
242 | int view_y = view->wlr_xwayland_surface->y; | 251 | int view_y = view->wlr_xwayland_surface->y; |
243 | render_surface(view->surface, wlr_output, &soutput->last_frame, | 252 | render_surface(view->surface, wlr_output, &output->last_frame, |
244 | view_x, view_y, 0); | 253 | view_x, view_y, 0); |
245 | } | 254 | } |
246 | } | 255 | } |
247 | 256 | ||
248 | // TODO: Consider revising this when fullscreen windows are supported | 257 | // TODO: Consider revising this when fullscreen windows are supported |
249 | render_layer(soutput, output_box, &now, | 258 | render_layer(output, output_box, when, |
250 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 259 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); |
251 | render_layer(soutput, output_box, &now, | 260 | render_layer(output, output_box, when, |
252 | &soutput->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 261 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); |
253 | 262 | ||
263 | renderer_end: | ||
254 | wlr_renderer_end(renderer); | 264 | wlr_renderer_end(renderer); |
255 | wlr_output_swap_buffers(wlr_output, &now, NULL); | 265 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { |
256 | soutput->last_frame = now; | 266 | return; |
267 | } | ||
268 | output->last_frame = *when; | ||
257 | } | 269 | } |
258 | 270 | ||
259 | static void handle_output_destroy(struct wl_listener *listener, void *data) { | 271 | static void damage_handle_frame(struct wl_listener *listener, void *data) { |
260 | struct sway_output *output = wl_container_of(listener, output, destroy); | 272 | struct sway_output *output = |
273 | wl_container_of(listener, output, damage_frame); | ||
261 | struct wlr_output *wlr_output = data; | 274 | struct wlr_output *wlr_output = data; |
262 | wlr_log(L_DEBUG, "Output %p %s removed", wlr_output, wlr_output->name); | ||
263 | 275 | ||
276 | if (!wlr_output->enabled) { | ||
277 | return; | ||
278 | } | ||
279 | |||
280 | struct timespec now; | ||
281 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
282 | |||
283 | bool needs_swap; | ||
284 | pixman_region32_t damage; | ||
285 | pixman_region32_init(&damage); | ||
286 | if (!wlr_output_damage_make_current(output->damage, &needs_swap, &damage)) { | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | if (needs_swap) { | ||
291 | render_output(output, &now, &damage); | ||
292 | } | ||
293 | |||
294 | pixman_region32_fini(&damage); | ||
295 | |||
296 | // TODO: send frame done events here instead of inside render_surface | ||
297 | } | ||
298 | |||
299 | void output_damage_whole(struct sway_output *output) { | ||
300 | wlr_output_damage_add_whole(output->damage); | ||
301 | } | ||
302 | |||
303 | void output_damage_whole_view(struct sway_output *output, | ||
304 | struct sway_view *view) { | ||
305 | // TODO | ||
306 | output_damage_whole(output); | ||
307 | } | ||
308 | |||
309 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | ||
310 | struct sway_output *output = | ||
311 | wl_container_of(listener, output, damage_destroy); | ||
312 | container_output_destroy(output->swayc); | ||
313 | } | ||
314 | |||
315 | static void handle_destroy(struct wl_listener *listener, void *data) { | ||
316 | struct sway_output *output = wl_container_of(listener, output, destroy); | ||
264 | container_output_destroy(output->swayc); | 317 | container_output_destroy(output->swayc); |
265 | } | 318 | } |
266 | 319 | ||
267 | static void handle_output_mode(struct wl_listener *listener, void *data) { | 320 | static void handle_mode(struct wl_listener *listener, void *data) { |
268 | struct sway_output *output = wl_container_of(listener, output, mode); | 321 | struct sway_output *output = wl_container_of(listener, output, mode); |
269 | arrange_layers(output); | 322 | arrange_layers(output); |
270 | arrange_windows(output->swayc, -1, -1); | 323 | arrange_windows(output->swayc, -1, -1); |
271 | } | 324 | } |
272 | 325 | ||
273 | static void handle_output_transform(struct wl_listener *listener, void *data) { | 326 | static void handle_transform(struct wl_listener *listener, void *data) { |
274 | struct sway_output *output = wl_container_of(listener, output, transform); | 327 | struct sway_output *output = wl_container_of(listener, output, transform); |
275 | arrange_layers(output); | 328 | arrange_layers(output); |
276 | arrange_windows(output->swayc, -1, -1); | 329 | arrange_windows(output->swayc, -1, -1); |
@@ -295,6 +348,8 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
295 | wlr_output_set_mode(wlr_output, mode); | 348 | wlr_output_set_mode(wlr_output, mode); |
296 | } | 349 | } |
297 | 350 | ||
351 | output->damage = wlr_output_damage_create(wlr_output); | ||
352 | |||
298 | output->swayc = container_output_create(output); | 353 | output->swayc = container_output_create(output); |
299 | if (!output->swayc) { | 354 | if (!output->swayc) { |
300 | free(output); | 355 | free(output); |
@@ -308,14 +363,17 @@ void handle_new_output(struct wl_listener *listener, void *data) { | |||
308 | 363 | ||
309 | sway_input_manager_configure_xcursor(input_manager); | 364 | sway_input_manager_configure_xcursor(input_manager); |
310 | 365 | ||
311 | wl_signal_add(&wlr_output->events.frame, &output->frame); | ||
312 | output->frame.notify = handle_output_frame; | ||
313 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); | 366 | wl_signal_add(&wlr_output->events.destroy, &output->destroy); |
314 | output->destroy.notify = handle_output_destroy; | 367 | output->destroy.notify = handle_destroy; |
315 | wl_signal_add(&wlr_output->events.mode, &output->mode); | 368 | wl_signal_add(&wlr_output->events.mode, &output->mode); |
316 | output->mode.notify = handle_output_mode; | 369 | output->mode.notify = handle_mode; |
317 | wl_signal_add(&wlr_output->events.transform, &output->transform); | 370 | wl_signal_add(&wlr_output->events.transform, &output->transform); |
318 | output->transform.notify = handle_output_transform; | 371 | output->transform.notify = handle_transform; |
372 | |||
373 | wl_signal_add(&output->damage->events.frame, &output->damage_frame); | ||
374 | output->damage_frame.notify = damage_handle_frame; | ||
375 | wl_signal_add(&output->damage->events.destroy, &output->damage_destroy); | ||
376 | output->damage_destroy.notify = damage_handle_destroy; | ||
319 | 377 | ||
320 | arrange_layers(output); | 378 | arrange_layers(output); |
321 | arrange_windows(&root_container, -1, -1); | 379 | arrange_windows(&root_container, -1, -1); |