diff options
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r-- | sway/desktop/output.c | 317 |
1 files changed, 207 insertions, 110 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9b0f1ae3..c150270e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -163,14 +163,65 @@ static void scale_box(struct wlr_box *box, float scale) { | |||
163 | struct render_data { | 163 | struct render_data { |
164 | struct root_geometry root_geo; | 164 | struct root_geometry root_geo; |
165 | struct sway_output *output; | 165 | struct sway_output *output; |
166 | pixman_region32_t *damage; | ||
166 | float alpha; | 167 | float alpha; |
167 | }; | 168 | }; |
168 | 169 | ||
170 | static void scissor_output(struct wlr_output *wlr_output, | ||
171 | pixman_box32_t *rect) { | ||
172 | struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); | ||
173 | assert(renderer); | ||
174 | |||
175 | struct wlr_box box = { | ||
176 | .x = rect->x1, | ||
177 | .y = rect->y1, | ||
178 | .width = rect->x2 - rect->x1, | ||
179 | .height = rect->y2 - rect->y1, | ||
180 | }; | ||
181 | |||
182 | int ow, oh; | ||
183 | wlr_output_transformed_resolution(wlr_output, &ow, &oh); | ||
184 | |||
185 | enum wl_output_transform transform = | ||
186 | wlr_output_transform_invert(wlr_output->transform); | ||
187 | wlr_box_transform(&box, transform, ow, oh, &box); | ||
188 | |||
189 | wlr_renderer_scissor(renderer, &box); | ||
190 | } | ||
191 | |||
192 | static void render_texture(struct wlr_output *wlr_output, | ||
193 | pixman_region32_t *output_damage, struct wlr_texture *texture, | ||
194 | const struct wlr_box *box, const float matrix[static 9], float alpha) { | ||
195 | struct wlr_renderer *renderer = | ||
196 | wlr_backend_get_renderer(wlr_output->backend); | ||
197 | |||
198 | pixman_region32_t damage; | ||
199 | pixman_region32_init(&damage); | ||
200 | pixman_region32_union_rect(&damage, &damage, box->x, box->y, | ||
201 | box->width, box->height); | ||
202 | pixman_region32_intersect(&damage, &damage, output_damage); | ||
203 | bool damaged = pixman_region32_not_empty(&damage); | ||
204 | if (!damaged) { | ||
205 | goto damage_finish; | ||
206 | } | ||
207 | |||
208 | int nrects; | ||
209 | pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); | ||
210 | for (int i = 0; i < nrects; ++i) { | ||
211 | scissor_output(wlr_output, &rects[i]); | ||
212 | wlr_render_texture_with_matrix(renderer, texture, matrix, alpha); | ||
213 | } | ||
214 | |||
215 | damage_finish: | ||
216 | pixman_region32_fini(&damage); | ||
217 | } | ||
218 | |||
169 | static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | 219 | static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, |
170 | void *_data) { | 220 | void *_data) { |
171 | struct render_data *data = _data; | 221 | struct render_data *data = _data; |
172 | struct wlr_output *wlr_output = data->output->wlr_output; | 222 | struct wlr_output *wlr_output = data->output->wlr_output; |
173 | float rotation = data->root_geo.rotation; | 223 | float rotation = data->root_geo.rotation; |
224 | pixman_region32_t *output_damage = data->damage; | ||
174 | float alpha = data->alpha; | 225 | float alpha = data->alpha; |
175 | 226 | ||
176 | if (!wlr_surface_has_buffer(surface)) { | 227 | if (!wlr_surface_has_buffer(surface)) { |
@@ -184,13 +235,6 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
184 | return; | 235 | return; |
185 | } | 236 | } |
186 | 237 | ||
187 | struct wlr_renderer *renderer = | ||
188 | wlr_backend_get_renderer(wlr_output->backend); | ||
189 | if (!sway_assert(renderer != NULL, | ||
190 | "expected the output backend to have a renderer")) { | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | scale_box(&box, wlr_output->scale); | 238 | scale_box(&box, wlr_output->scale); |
195 | 239 | ||
196 | float matrix[9]; | 240 | float matrix[9]; |
@@ -199,38 +243,81 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
199 | wlr_matrix_project_box(matrix, &box, transform, rotation, | 243 | wlr_matrix_project_box(matrix, &box, transform, rotation, |
200 | wlr_output->transform_matrix); | 244 | wlr_output->transform_matrix); |
201 | 245 | ||
202 | wlr_render_texture_with_matrix(renderer, surface->texture, | 246 | render_texture(wlr_output, output_damage, surface->texture, &box, matrix, |
203 | matrix, alpha); | 247 | alpha); |
204 | } | 248 | } |
205 | 249 | ||
206 | static void render_layer(struct sway_output *output, | 250 | static void render_layer(struct sway_output *output, |
207 | struct wl_list *layer_surfaces) { | 251 | pixman_region32_t *damage, struct wl_list *layer_surfaces) { |
208 | struct render_data data = { .output = output, .alpha = 1.0f }; | 252 | struct render_data data = { |
253 | .output = output, | ||
254 | .damage = damage, | ||
255 | .alpha = 1.0f, | ||
256 | }; | ||
209 | layer_for_each_surface(layer_surfaces, &data.root_geo, | 257 | layer_for_each_surface(layer_surfaces, &data.root_geo, |
210 | render_surface_iterator, &data); | 258 | render_surface_iterator, &data); |
211 | } | 259 | } |
212 | 260 | ||
213 | static void render_unmanaged(struct sway_output *output, | 261 | static void render_unmanaged(struct sway_output *output, |
214 | struct wl_list *unmanaged) { | 262 | pixman_region32_t *damage, struct wl_list *unmanaged) { |
215 | struct render_data data = { .output = output, .alpha = 1.0f }; | 263 | struct render_data data = { |
264 | .output = output, | ||
265 | .damage = damage, | ||
266 | .alpha = 1.0f, | ||
267 | }; | ||
216 | unmanaged_for_each_surface(unmanaged, output, &data.root_geo, | 268 | unmanaged_for_each_surface(unmanaged, output, &data.root_geo, |
217 | render_surface_iterator, &data); | 269 | render_surface_iterator, &data); |
218 | } | 270 | } |
219 | 271 | ||
220 | static void render_view(struct sway_view *view, struct sway_output *output) { | 272 | static void render_view(struct sway_view *view, struct sway_output *output, |
221 | struct render_data data = { .output = output, .alpha = view->swayc->alpha }; | 273 | pixman_region32_t *damage) { |
274 | struct render_data data = { | ||
275 | .output = output, | ||
276 | .damage = damage, | ||
277 | .alpha = view->swayc->alpha, | ||
278 | }; | ||
222 | output_view_for_each_surface( | 279 | output_view_for_each_surface( |
223 | view, &data.root_geo, render_surface_iterator, &data); | 280 | view, &data.root_geo, render_surface_iterator, &data); |
224 | } | 281 | } |
225 | 282 | ||
283 | static void render_rect(struct wlr_output *wlr_output, | ||
284 | pixman_region32_t *output_damage, const struct wlr_box *_box, | ||
285 | float color[static 4]) { | ||
286 | struct wlr_renderer *renderer = | ||
287 | wlr_backend_get_renderer(wlr_output->backend); | ||
288 | |||
289 | struct wlr_box box = *_box; | ||
290 | scale_box(&box, wlr_output->scale); | ||
291 | |||
292 | pixman_region32_t damage; | ||
293 | pixman_region32_init(&damage); | ||
294 | pixman_region32_union_rect(&damage, &damage, box.x, box.y, | ||
295 | box.width, box.height); | ||
296 | pixman_region32_intersect(&damage, &damage, output_damage); | ||
297 | bool damaged = pixman_region32_not_empty(&damage); | ||
298 | if (!damaged) { | ||
299 | goto damage_finish; | ||
300 | } | ||
301 | |||
302 | int nrects; | ||
303 | pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); | ||
304 | for (int i = 0; i < nrects; ++i) { | ||
305 | scissor_output(wlr_output, &rects[i]); | ||
306 | wlr_render_rect(renderer, &box, color, | ||
307 | wlr_output->transform_matrix); | ||
308 | } | ||
309 | |||
310 | damage_finish: | ||
311 | pixman_region32_fini(&damage); | ||
312 | } | ||
313 | |||
226 | /** | 314 | /** |
227 | * Render decorations for a view with "border normal". | 315 | * Render decorations for a view with "border normal". |
228 | */ | 316 | */ |
229 | static void render_container_simple_border_normal(struct sway_output *output, | 317 | static void render_container_simple_border_normal(struct sway_output *output, |
318 | pixman_region32_t *output_damage, | ||
230 | struct sway_container *con, struct border_colors *colors, | 319 | struct sway_container *con, struct border_colors *colors, |
231 | struct wlr_texture *title_texture) { | 320 | struct wlr_texture *title_texture) { |
232 | struct wlr_renderer *renderer = | ||
233 | wlr_backend_get_renderer(output->wlr_output->backend); | ||
234 | struct wlr_box box; | 321 | struct wlr_box box; |
235 | float color[4]; | 322 | float color[4]; |
236 | 323 | ||
@@ -241,9 +328,7 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
241 | box.y = con->y + 1; | 328 | box.y = con->y + 1; |
242 | box.width = con->sway_view->border_thickness; | 329 | box.width = con->sway_view->border_thickness; |
243 | box.height = con->height - 1; | 330 | box.height = con->height - 1; |
244 | scale_box(&box, output->wlr_output->scale); | 331 | render_rect(output->wlr_output, output_damage, &box, color); |
245 | wlr_render_rect(renderer, &box, color, | ||
246 | output->wlr_output->transform_matrix); | ||
247 | 332 | ||
248 | // Child border - right edge | 333 | // Child border - right edge |
249 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { | 334 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { |
@@ -256,9 +341,7 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
256 | box.y = con->y + 1; | 341 | box.y = con->y + 1; |
257 | box.width = con->sway_view->border_thickness; | 342 | box.width = con->sway_view->border_thickness; |
258 | box.height = con->height - 1; | 343 | box.height = con->height - 1; |
259 | scale_box(&box, output->wlr_output->scale); | 344 | render_rect(output->wlr_output, output_damage, &box, color); |
260 | wlr_render_rect(renderer, &box, color, | ||
261 | output->wlr_output->transform_matrix); | ||
262 | 345 | ||
263 | // Child border - bottom edge | 346 | // Child border - bottom edge |
264 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { | 347 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { |
@@ -271,9 +354,7 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
271 | box.y = con->y + con->height - con->sway_view->border_thickness; | 354 | box.y = con->y + con->height - con->sway_view->border_thickness; |
272 | box.width = con->width; | 355 | box.width = con->width; |
273 | box.height = con->sway_view->border_thickness; | 356 | box.height = con->sway_view->border_thickness; |
274 | scale_box(&box, output->wlr_output->scale); | 357 | render_rect(output->wlr_output, output_damage, &box, color); |
275 | wlr_render_rect(renderer, &box, color, | ||
276 | output->wlr_output->transform_matrix); | ||
277 | 358 | ||
278 | // Single pixel bar above title | 359 | // Single pixel bar above title |
279 | memcpy(&color, colors->border, sizeof(float) * 4); | 360 | memcpy(&color, colors->border, sizeof(float) * 4); |
@@ -282,18 +363,14 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
282 | box.y = con->y; | 363 | box.y = con->y; |
283 | box.width = con->width; | 364 | box.width = con->width; |
284 | box.height = 1; | 365 | box.height = 1; |
285 | scale_box(&box, output->wlr_output->scale); | 366 | render_rect(output->wlr_output, output_damage, &box, color); |
286 | wlr_render_rect(renderer, &box, color, | ||
287 | output->wlr_output->transform_matrix); | ||
288 | 367 | ||
289 | // Single pixel bar below title | 368 | // Single pixel bar below title |
290 | box.x = con->x + con->sway_view->border_thickness; | 369 | box.x = con->x + con->sway_view->border_thickness; |
291 | box.y = con->sway_view->y - 1; | 370 | box.y = con->sway_view->y - 1; |
292 | box.width = con->width - con->sway_view->border_thickness * 2; | 371 | box.width = con->width - con->sway_view->border_thickness * 2; |
293 | box.height = 1; | 372 | box.height = 1; |
294 | scale_box(&box, output->wlr_output->scale); | 373 | render_rect(output->wlr_output, output_damage, &box, color); |
295 | wlr_render_rect(renderer, &box, color, | ||
296 | output->wlr_output->transform_matrix); | ||
297 | 374 | ||
298 | // Title background | 375 | // Title background |
299 | memcpy(&color, colors->background, sizeof(float) * 4); | 376 | memcpy(&color, colors->background, sizeof(float) * 4); |
@@ -302,20 +379,24 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
302 | box.y = con->y + 1; | 379 | box.y = con->y + 1; |
303 | box.width = con->width - con->sway_view->border_thickness * 2; | 380 | box.width = con->width - con->sway_view->border_thickness * 2; |
304 | box.height = con->sway_view->y - con->y - 2; | 381 | box.height = con->sway_view->y - con->y - 2; |
305 | scale_box(&box, output->wlr_output->scale); | 382 | render_rect(output->wlr_output, output_damage, &box, color); |
306 | wlr_render_rect(renderer, &box, color, | ||
307 | output->wlr_output->transform_matrix); | ||
308 | 383 | ||
309 | // Title text | 384 | // Title text |
310 | if (title_texture) { | 385 | if (title_texture) { |
311 | struct wlr_box scissor_box; | 386 | float output_scale = output->wlr_output->scale; |
312 | wlr_box_transform(&box, | 387 | struct wlr_box texture_box = { |
313 | wlr_output_transform_invert(output->wlr_output->transform), | 388 | .x = box.x * output_scale, |
314 | output->swayc->width, output->swayc->height, &scissor_box); | 389 | .y = box.y * output_scale, |
315 | wlr_renderer_scissor(renderer, &scissor_box); | 390 | }; |
316 | wlr_render_texture(renderer, title_texture, | 391 | wlr_texture_get_size(title_texture, |
317 | output->wlr_output->transform_matrix, box.x, box.y, 1); | 392 | &texture_box.width, &texture_box.height); |
318 | wlr_renderer_scissor(renderer, NULL); | 393 | |
394 | float matrix[9]; | ||
395 | wlr_matrix_project_box(matrix, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, | ||
396 | 0.0, output->wlr_output->transform_matrix); | ||
397 | |||
398 | render_texture(output->wlr_output, output_damage, title_texture, | ||
399 | &texture_box, matrix, 1.0); | ||
319 | } | 400 | } |
320 | } | 401 | } |
321 | 402 | ||
@@ -323,9 +404,8 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
323 | * Render decorations for a view with "border pixel". | 404 | * Render decorations for a view with "border pixel". |
324 | */ | 405 | */ |
325 | static void render_container_simple_border_pixel(struct sway_output *output, | 406 | static void render_container_simple_border_pixel(struct sway_output *output, |
326 | struct sway_container *con, struct border_colors *colors) { | 407 | pixman_region32_t *output_damage, struct sway_container *con, |
327 | struct wlr_renderer *renderer = | 408 | struct border_colors *colors) { |
328 | wlr_backend_get_renderer(output->wlr_output->backend); | ||
329 | struct wlr_box box; | 409 | struct wlr_box box; |
330 | float color[4]; | 410 | float color[4]; |
331 | 411 | ||
@@ -336,9 +416,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, | |||
336 | box.y = con->y; | 416 | box.y = con->y; |
337 | box.width = con->sway_view->border_thickness; | 417 | box.width = con->sway_view->border_thickness; |
338 | box.height = con->height; | 418 | box.height = con->height; |
339 | scale_box(&box, output->wlr_output->scale); | 419 | render_rect(output->wlr_output, output_damage, &box, color); |
340 | wlr_render_rect(renderer, &box, color, | ||
341 | output->wlr_output->transform_matrix); | ||
342 | 420 | ||
343 | // Child border - right edge | 421 | // Child border - right edge |
344 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { | 422 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { |
@@ -351,18 +429,14 @@ static void render_container_simple_border_pixel(struct sway_output *output, | |||
351 | box.y = con->y; | 429 | box.y = con->y; |
352 | box.width = con->sway_view->border_thickness; | 430 | box.width = con->sway_view->border_thickness; |
353 | box.height = con->height; | 431 | box.height = con->height; |
354 | scale_box(&box, output->wlr_output->scale); | 432 | render_rect(output->wlr_output, output_damage, &box, color); |
355 | wlr_render_rect(renderer, &box, color, | ||
356 | output->wlr_output->transform_matrix); | ||
357 | 433 | ||
358 | // Child border - top edge | 434 | // Child border - top edge |
359 | box.x = con->x; | 435 | box.x = con->x; |
360 | box.y = con->y; | 436 | box.y = con->y; |
361 | box.width = con->width; | 437 | box.width = con->width; |
362 | box.height = con->sway_view->border_thickness; | 438 | box.height = con->sway_view->border_thickness; |
363 | scale_box(&box, output->wlr_output->scale); | 439 | render_rect(output->wlr_output, output_damage, &box, color); |
364 | wlr_render_rect(renderer, &box, color, | ||
365 | output->wlr_output->transform_matrix); | ||
366 | 440 | ||
367 | // Child border - bottom edge | 441 | // Child border - bottom edge |
368 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { | 442 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { |
@@ -375,13 +449,11 @@ static void render_container_simple_border_pixel(struct sway_output *output, | |||
375 | box.y = con->y + con->height - con->sway_view->border_thickness; | 449 | box.y = con->y + con->height - con->sway_view->border_thickness; |
376 | box.width = con->width; | 450 | box.width = con->width; |
377 | box.height = con->sway_view->border_thickness; | 451 | box.height = con->sway_view->border_thickness; |
378 | scale_box(&box, output->wlr_output->scale); | 452 | render_rect(output->wlr_output, output_damage, &box, color); |
379 | wlr_render_rect(renderer, &box, color, | ||
380 | output->wlr_output->transform_matrix); | ||
381 | } | 453 | } |
382 | 454 | ||
383 | static void render_container(struct sway_output *output, | 455 | static void render_container(struct sway_output *output, |
384 | struct sway_container *con); | 456 | pixman_region32_t *damage, struct sway_container *con); |
385 | 457 | ||
386 | /** | 458 | /** |
387 | * Render a container's children using a L_HORIZ or L_VERT layout. | 459 | * Render a container's children using a L_HORIZ or L_VERT layout. |
@@ -390,7 +462,7 @@ static void render_container(struct sway_output *output, | |||
390 | * they'll apply their own borders to their children. | 462 | * they'll apply their own borders to their children. |
391 | */ | 463 | */ |
392 | static void render_container_simple(struct sway_output *output, | 464 | static void render_container_simple(struct sway_output *output, |
393 | struct sway_container *con) { | 465 | pixman_region32_t *damage, struct sway_container *con) { |
394 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 466 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
395 | struct sway_container *focus = seat_get_focus(seat); | 467 | struct sway_container *focus = seat_get_focus(seat); |
396 | 468 | ||
@@ -413,15 +485,16 @@ static void render_container_simple(struct sway_output *output, | |||
413 | } | 485 | } |
414 | 486 | ||
415 | if (child->sway_view->border == B_NORMAL) { | 487 | if (child->sway_view->border == B_NORMAL) { |
416 | render_container_simple_border_normal(output, child, | 488 | render_container_simple_border_normal(output, damage, |
417 | colors, title_texture); | 489 | child, colors, title_texture); |
418 | } else { | 490 | } else { |
419 | render_container_simple_border_pixel(output, child, colors); | 491 | render_container_simple_border_pixel(output, damage, child, |
492 | colors); | ||
420 | } | 493 | } |
421 | } | 494 | } |
422 | render_view(child->sway_view, output); | 495 | render_view(child->sway_view, output, damage); |
423 | } else { | 496 | } else { |
424 | render_container(output, child); | 497 | render_container(output, damage, child); |
425 | } | 498 | } |
426 | } | 499 | } |
427 | } | 500 | } |
@@ -430,7 +503,7 @@ static void render_container_simple(struct sway_output *output, | |||
430 | * Render a container's children using the L_TABBED layout. | 503 | * Render a container's children using the L_TABBED layout. |
431 | */ | 504 | */ |
432 | static void render_container_tabbed(struct sway_output *output, | 505 | static void render_container_tabbed(struct sway_output *output, |
433 | struct sway_container *con) { | 506 | pixman_region32_t *damage, struct sway_container *con) { |
434 | // TODO | 507 | // TODO |
435 | } | 508 | } |
436 | 509 | ||
@@ -438,23 +511,23 @@ static void render_container_tabbed(struct sway_output *output, | |||
438 | * Render a container's children using the L_STACKED layout. | 511 | * Render a container's children using the L_STACKED layout. |
439 | */ | 512 | */ |
440 | static void render_container_stacked(struct sway_output *output, | 513 | static void render_container_stacked(struct sway_output *output, |
441 | struct sway_container *con) { | 514 | pixman_region32_t *damage, struct sway_container *con) { |
442 | // TODO | 515 | // TODO |
443 | } | 516 | } |
444 | 517 | ||
445 | static void render_container(struct sway_output *output, | 518 | static void render_container(struct sway_output *output, |
446 | struct sway_container *con) { | 519 | pixman_region32_t *damage, struct sway_container *con) { |
447 | switch (con->layout) { | 520 | switch (con->layout) { |
448 | case L_NONE: | 521 | case L_NONE: |
449 | case L_HORIZ: | 522 | case L_HORIZ: |
450 | case L_VERT: | 523 | case L_VERT: |
451 | render_container_simple(output, con); | 524 | render_container_simple(output, damage, con); |
452 | break; | 525 | break; |
453 | case L_STACKED: | 526 | case L_STACKED: |
454 | render_container_stacked(output, con); | 527 | render_container_stacked(output, damage, con); |
455 | break; | 528 | break; |
456 | case L_TABBED: | 529 | case L_TABBED: |
457 | render_container_tabbed(output, con); | 530 | render_container_tabbed(output, damage, con); |
458 | break; | 531 | break; |
459 | case L_FLOATING: | 532 | case L_FLOATING: |
460 | // TODO | 533 | // TODO |
@@ -496,37 +569,51 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
496 | goto renderer_end; | 569 | goto renderer_end; |
497 | } | 570 | } |
498 | 571 | ||
499 | // TODO: don't damage the whole output | 572 | //wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); |
500 | int width, height; | ||
501 | wlr_output_transformed_resolution(wlr_output, &width, &height); | ||
502 | pixman_region32_union_rect(damage, damage, 0, 0, width, height); | ||
503 | 573 | ||
504 | struct sway_container *workspace = output_get_active_workspace(output); | 574 | struct sway_container *workspace = output_get_active_workspace(output); |
505 | 575 | ||
506 | if (workspace->sway_workspace->fullscreen) { | 576 | if (workspace->sway_workspace->fullscreen) { |
507 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; | 577 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; |
508 | wlr_renderer_clear(renderer, clear_color); | 578 | |
579 | int nrects; | ||
580 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); | ||
581 | for (int i = 0; i < nrects; ++i) { | ||
582 | scissor_output(wlr_output, &rects[i]); | ||
583 | wlr_renderer_clear(renderer, clear_color); | ||
584 | } | ||
585 | |||
509 | // TODO: handle views smaller than the output | 586 | // TODO: handle views smaller than the output |
510 | render_view(workspace->sway_workspace->fullscreen, output); | 587 | render_view(workspace->sway_workspace->fullscreen, output, damage); |
511 | 588 | ||
512 | if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { | 589 | if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { |
513 | render_unmanaged(output, | 590 | render_unmanaged(output, damage, |
514 | &root_container.sway_root->xwayland_unmanaged); | 591 | &root_container.sway_root->xwayland_unmanaged); |
515 | } | 592 | } |
516 | } else { | 593 | } else { |
517 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 594 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
518 | wlr_renderer_clear(renderer, clear_color); | ||
519 | 595 | ||
520 | render_layer(output, | 596 | int nrects; |
521 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | 597 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); |
522 | render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 598 | for (int i = 0; i < nrects; ++i) { |
599 | scissor_output(wlr_output, &rects[i]); | ||
600 | wlr_renderer_clear(renderer, clear_color); | ||
601 | } | ||
602 | |||
603 | render_layer(output, damage, | ||
604 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | ||
605 | render_layer(output, damage, | ||
606 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | ||
523 | 607 | ||
524 | render_container(output, workspace); | 608 | render_container(output, damage, workspace); |
525 | 609 | ||
526 | render_unmanaged(output, &root_container.sway_root->xwayland_unmanaged); | 610 | render_unmanaged(output, damage, |
527 | render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 611 | &root_container.sway_root->xwayland_unmanaged); |
612 | render_layer(output, damage, | ||
613 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | ||
528 | } | 614 | } |
529 | render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 615 | render_layer(output, damage, |
616 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | ||
530 | 617 | ||
531 | renderer_end: | 618 | renderer_end: |
532 | if (root_container.sway_root->debug_tree) { | 619 | if (root_container.sway_root->debug_tree) { |
@@ -534,6 +621,7 @@ renderer_end: | |||
534 | wlr_output->transform_matrix, 0, 0, 1); | 621 | wlr_output->transform_matrix, 0, 0, 1); |
535 | } | 622 | } |
536 | 623 | ||
624 | wlr_renderer_scissor(renderer, NULL); | ||
537 | wlr_renderer_end(renderer); | 625 | wlr_renderer_end(renderer); |
538 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { | 626 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { |
539 | return; | 627 | return; |
@@ -663,28 +751,28 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
663 | 751 | ||
664 | scale_box(&box, output->wlr_output->scale); | 752 | scale_box(&box, output->wlr_output->scale); |
665 | 753 | ||
754 | int center_x = box.x + box.width/2; | ||
755 | int center_y = box.y + box.height/2; | ||
756 | |||
757 | pixman_region32_t damage; | ||
758 | pixman_region32_init(&damage); | ||
759 | pixman_region32_copy(&damage, &surface->current->surface_damage); | ||
760 | wlr_region_scale(&damage, &damage, output->wlr_output->scale); | ||
761 | if (ceil(output->wlr_output->scale) > surface->current->scale) { | ||
762 | // When scaling up a surface, it'll become blurry so we need to | ||
763 | // expand the damage region | ||
764 | wlr_region_expand(&damage, &damage, | ||
765 | ceil(output->wlr_output->scale) - surface->current->scale); | ||
766 | } | ||
767 | pixman_region32_translate(&damage, box.x, box.y); | ||
768 | wlr_region_rotated_bounds(&damage, &damage, rotation, | ||
769 | center_x, center_y); | ||
770 | wlr_output_damage_add(output->damage, &damage); | ||
771 | pixman_region32_fini(&damage); | ||
772 | |||
666 | if (whole) { | 773 | if (whole) { |
667 | wlr_box_rotated_bounds(&box, rotation, &box); | 774 | wlr_box_rotated_bounds(&box, rotation, &box); |
668 | wlr_output_damage_add_box(output->damage, &box); | 775 | wlr_output_damage_add_box(output->damage, &box); |
669 | } else { | ||
670 | int center_x = box.x + box.width/2; | ||
671 | int center_y = box.y + box.height/2; | ||
672 | |||
673 | pixman_region32_t damage; | ||
674 | pixman_region32_init(&damage); | ||
675 | pixman_region32_copy(&damage, &surface->current->surface_damage); | ||
676 | wlr_region_scale(&damage, &damage, output->wlr_output->scale); | ||
677 | if (ceil(output->wlr_output->scale) > surface->current->scale) { | ||
678 | // When scaling up a surface, it'll become blurry so we need to | ||
679 | // expand the damage region | ||
680 | wlr_region_expand(&damage, &damage, | ||
681 | ceil(output->wlr_output->scale) - surface->current->scale); | ||
682 | } | ||
683 | pixman_region32_translate(&damage, box.x, box.y); | ||
684 | wlr_region_rotated_bounds(&damage, &damage, rotation, | ||
685 | center_x, center_y); | ||
686 | wlr_output_damage_add(output->damage, &damage); | ||
687 | pixman_region32_fini(&damage); | ||
688 | } | 776 | } |
689 | } | 777 | } |
690 | 778 | ||
@@ -699,8 +787,8 @@ void output_damage_surface(struct sway_output *output, double ox, double oy, | |||
699 | damage_surface_iterator, &data); | 787 | damage_surface_iterator, &data); |
700 | } | 788 | } |
701 | 789 | ||
702 | void output_damage_view(struct sway_output *output, struct sway_view *view, | 790 | static void output_damage_view(struct sway_output *output, |
703 | bool whole) { | 791 | struct sway_view *view, bool whole) { |
704 | if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { | 792 | if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { |
705 | return; | 793 | return; |
706 | } | 794 | } |
@@ -720,6 +808,11 @@ void output_damage_view(struct sway_output *output, struct sway_view *view, | |||
720 | damage_surface_iterator, &data); | 808 | damage_surface_iterator, &data); |
721 | } | 809 | } |
722 | 810 | ||
811 | void output_damage_from_view(struct sway_output *output, | ||
812 | struct sway_view *view) { | ||
813 | output_damage_view(output, view, false); | ||
814 | } | ||
815 | |||
723 | static void output_damage_whole_container_iterator(struct sway_container *con, | 816 | static void output_damage_whole_container_iterator(struct sway_container *con, |
724 | void *data) { | 817 | void *data) { |
725 | struct sway_output *output = data; | 818 | struct sway_output *output = data; |
@@ -742,8 +835,12 @@ void output_damage_whole_container(struct sway_output *output, | |||
742 | }; | 835 | }; |
743 | wlr_output_damage_add_box(output->damage, &box); | 836 | wlr_output_damage_add_box(output->damage, &box); |
744 | 837 | ||
745 | container_descendants(con, C_VIEW, output_damage_whole_container_iterator, | 838 | if (con->type == C_VIEW) { |
746 | output); | 839 | output_damage_whole_container_iterator(con, output); |
840 | } else { | ||
841 | container_descendants(con, C_VIEW, | ||
842 | output_damage_whole_container_iterator, output); | ||
843 | } | ||
747 | } | 844 | } |
748 | 845 | ||
749 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 846 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { |