diff options
author | 2022-06-07 18:55:26 +0200 | |
---|---|---|
committer | 2022-06-10 11:35:30 +0200 | |
commit | 1c69d0e72fe868d0fa2f6d7d9f9b4b3d7a3f78b4 (patch) | |
tree | 7297c41a7d520a5cade13976749c962c191f21bb | |
parent | swaynag: move close_button up to fix SIGSEGV (diff) | |
download | sway-1c69d0e72fe868d0fa2f6d7d9f9b4b3d7a3f78b4.tar.gz sway-1c69d0e72fe868d0fa2f6d7d9f9b4b3d7a3f78b4.tar.zst sway-1c69d0e72fe868d0fa2f6d7d9f9b4b3d7a3f78b4.zip |
config/output: use wlr_output_commit_state
This makes the code more robust because we don't potentially leave
bad state in wlr_output.pending behind anymore. This also fixes a
bug.
Closes: https://github.com/swaywm/sway/issues/7043
References: https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/3610
-rw-r--r-- | sway/config/output.c | 78 |
1 files changed, 40 insertions, 38 deletions
diff --git a/sway/config/output.c b/sway/config/output.c index aa4cf946..85b3f8bd 100644 --- a/sway/config/output.c +++ b/sway/config/output.c | |||
@@ -247,8 +247,8 @@ struct output_config *store_output_config(struct output_config *oc) { | |||
247 | return oc; | 247 | return oc; |
248 | } | 248 | } |
249 | 249 | ||
250 | static void set_mode(struct wlr_output *output, int width, int height, | 250 | static void set_mode(struct wlr_output *output, struct wlr_output_state *pending, |
251 | float refresh_rate, bool custom) { | 251 | int width, int height, float refresh_rate, bool custom) { |
252 | // Not all floating point integers can be represented exactly | 252 | // Not all floating point integers can be represented exactly |
253 | // as (int)(1000 * mHz / 1000.f) | 253 | // as (int)(1000 * mHz / 1000.f) |
254 | // round() the result to avoid any error | 254 | // round() the result to avoid any error |
@@ -256,7 +256,7 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
256 | 256 | ||
257 | if (wl_list_empty(&output->modes) || custom) { | 257 | if (wl_list_empty(&output->modes) || custom) { |
258 | sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name); | 258 | sway_log(SWAY_DEBUG, "Assigning custom mode to %s", output->name); |
259 | wlr_output_set_custom_mode(output, width, height, | 259 | wlr_output_state_set_custom_mode(pending, width, height, |
260 | refresh_rate > 0 ? mhz : 0); | 260 | refresh_rate > 0 ? mhz : 0); |
261 | return; | 261 | return; |
262 | } | 262 | } |
@@ -280,10 +280,11 @@ static void set_mode(struct wlr_output *output, int width, int height, | |||
280 | } else { | 280 | } else { |
281 | sway_log(SWAY_DEBUG, "Assigning configured mode to %s", output->name); | 281 | sway_log(SWAY_DEBUG, "Assigning configured mode to %s", output->name); |
282 | } | 282 | } |
283 | wlr_output_set_mode(output, best); | 283 | wlr_output_state_set_mode(pending, best); |
284 | } | 284 | } |
285 | 285 | ||
286 | static void set_modeline(struct wlr_output *output, drmModeModeInfo *drm_mode) { | 286 | static void set_modeline(struct wlr_output *output, |
287 | struct wlr_output_state *pending, drmModeModeInfo *drm_mode) { | ||
287 | if (!wlr_output_is_drm(output)) { | 288 | if (!wlr_output_is_drm(output)) { |
288 | sway_log(SWAY_ERROR, "Modeline can only be set to DRM output"); | 289 | sway_log(SWAY_ERROR, "Modeline can only be set to DRM output"); |
289 | return; | 290 | return; |
@@ -291,7 +292,7 @@ static void set_modeline(struct wlr_output *output, drmModeModeInfo *drm_mode) { | |||
291 | sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name); | 292 | sway_log(SWAY_DEBUG, "Assigning custom modeline to %s", output->name); |
292 | struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode); | 293 | struct wlr_output_mode *mode = wlr_drm_connector_add_mode(output, drm_mode); |
293 | if (mode) { | 294 | if (mode) { |
294 | wlr_output_set_mode(output, mode); | 295 | wlr_output_state_set_mode(pending, mode); |
295 | } | 296 | } |
296 | } | 297 | } |
297 | 298 | ||
@@ -313,23 +314,24 @@ static bool phys_size_is_aspect_ratio(struct wlr_output *output) { | |||
313 | // 1 inch = 25.4 mm | 314 | // 1 inch = 25.4 mm |
314 | #define MM_PER_INCH 25.4 | 315 | #define MM_PER_INCH 25.4 |
315 | 316 | ||
316 | static int compute_default_scale(struct wlr_output *output) { | 317 | static int compute_default_scale(struct wlr_output *output, |
318 | struct wlr_output_state *pending) { | ||
317 | struct wlr_box box = { .width = output->width, .height = output->height }; | 319 | struct wlr_box box = { .width = output->width, .height = output->height }; |
318 | if (output->pending.committed & WLR_OUTPUT_STATE_MODE) { | 320 | if (pending->committed & WLR_OUTPUT_STATE_MODE) { |
319 | switch (output->pending.mode_type) { | 321 | switch (pending->mode_type) { |
320 | case WLR_OUTPUT_STATE_MODE_FIXED: | 322 | case WLR_OUTPUT_STATE_MODE_FIXED: |
321 | box.width = output->pending.mode->width; | 323 | box.width = pending->mode->width; |
322 | box.height = output->pending.mode->height; | 324 | box.height = pending->mode->height; |
323 | break; | 325 | break; |
324 | case WLR_OUTPUT_STATE_MODE_CUSTOM: | 326 | case WLR_OUTPUT_STATE_MODE_CUSTOM: |
325 | box.width = output->pending.custom_mode.width; | 327 | box.width = pending->custom_mode.width; |
326 | box.height = output->pending.custom_mode.height; | 328 | box.height = pending->custom_mode.height; |
327 | break; | 329 | break; |
328 | } | 330 | } |
329 | } | 331 | } |
330 | enum wl_output_transform transform = output->transform; | 332 | enum wl_output_transform transform = output->transform; |
331 | if (output->pending.committed & WLR_OUTPUT_STATE_TRANSFORM) { | 333 | if (pending->committed & WLR_OUTPUT_STATE_TRANSFORM) { |
332 | transform = output->pending.transform; | 334 | transform = pending->transform; |
333 | } | 335 | } |
334 | wlr_box_transform(&box, &box, transform, box.width, box.height); | 336 | wlr_box_transform(&box, &box, transform, box.width, box.height); |
335 | 337 | ||
@@ -376,7 +378,7 @@ static const uint32_t *bit_depth_preferences[] = { | |||
376 | }; | 378 | }; |
377 | 379 | ||
378 | static void queue_output_config(struct output_config *oc, | 380 | static void queue_output_config(struct output_config *oc, |
379 | struct sway_output *output) { | 381 | struct sway_output *output, struct wlr_output_state *pending) { |
380 | if (output == root->fallback_output) { | 382 | if (output == root->fallback_output) { |
381 | return; | 383 | return; |
382 | } | 384 | } |
@@ -385,29 +387,29 @@ static void queue_output_config(struct output_config *oc, | |||
385 | 387 | ||
386 | if (oc && (!oc->enabled || oc->dpms_state == DPMS_OFF)) { | 388 | if (oc && (!oc->enabled || oc->dpms_state == DPMS_OFF)) { |
387 | sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name); | 389 | sway_log(SWAY_DEBUG, "Turning off output %s", wlr_output->name); |
388 | wlr_output_enable(wlr_output, false); | 390 | wlr_output_state_set_enabled(pending, false); |
389 | return; | 391 | return; |
390 | } | 392 | } |
391 | 393 | ||
392 | sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name); | 394 | sway_log(SWAY_DEBUG, "Turning on output %s", wlr_output->name); |
393 | wlr_output_enable(wlr_output, true); | 395 | wlr_output_state_set_enabled(pending, true); |
394 | 396 | ||
395 | if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) { | 397 | if (oc && oc->drm_mode.type != 0 && oc->drm_mode.type != (uint32_t) -1) { |
396 | sway_log(SWAY_DEBUG, "Set %s modeline", | 398 | sway_log(SWAY_DEBUG, "Set %s modeline", |
397 | wlr_output->name); | 399 | wlr_output->name); |
398 | set_modeline(wlr_output, &oc->drm_mode); | 400 | set_modeline(wlr_output, pending, &oc->drm_mode); |
399 | } else if (oc && oc->width > 0 && oc->height > 0) { | 401 | } else if (oc && oc->width > 0 && oc->height > 0) { |
400 | sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)", | 402 | sway_log(SWAY_DEBUG, "Set %s mode to %dx%d (%f Hz)", |
401 | wlr_output->name, oc->width, oc->height, oc->refresh_rate); | 403 | wlr_output->name, oc->width, oc->height, oc->refresh_rate); |
402 | set_mode(wlr_output, oc->width, oc->height, | 404 | set_mode(wlr_output, pending, oc->width, oc->height, |
403 | oc->refresh_rate, oc->custom_mode == 1); | 405 | oc->refresh_rate, oc->custom_mode == 1); |
404 | } else if (!wl_list_empty(&wlr_output->modes)) { | 406 | } else if (!wl_list_empty(&wlr_output->modes)) { |
405 | sway_log(SWAY_DEBUG, "Set preferred mode"); | 407 | sway_log(SWAY_DEBUG, "Set preferred mode"); |
406 | struct wlr_output_mode *preferred_mode = | 408 | struct wlr_output_mode *preferred_mode = |
407 | wlr_output_preferred_mode(wlr_output); | 409 | wlr_output_preferred_mode(wlr_output); |
408 | wlr_output_set_mode(wlr_output, preferred_mode); | 410 | wlr_output_state_set_mode(pending, preferred_mode); |
409 | 411 | ||
410 | if (!wlr_output_test(wlr_output)) { | 412 | if (!wlr_output_test_state(wlr_output, pending)) { |
411 | sway_log(SWAY_DEBUG, "Preferred mode rejected, " | 413 | sway_log(SWAY_DEBUG, "Preferred mode rejected, " |
412 | "falling back to another mode"); | 414 | "falling back to another mode"); |
413 | struct wlr_output_mode *mode; | 415 | struct wlr_output_mode *mode; |
@@ -416,8 +418,8 @@ static void queue_output_config(struct output_config *oc, | |||
416 | continue; | 418 | continue; |
417 | } | 419 | } |
418 | 420 | ||
419 | wlr_output_set_mode(wlr_output, mode); | 421 | wlr_output_state_set_mode(pending, mode); |
420 | if (wlr_output_test(wlr_output)) { | 422 | if (wlr_output_test_state(wlr_output, pending)) { |
421 | break; | 423 | break; |
422 | } | 424 | } |
423 | } | 425 | } |
@@ -427,7 +429,7 @@ static void queue_output_config(struct output_config *oc, | |||
427 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { | 429 | if (oc && (oc->subpixel != WL_OUTPUT_SUBPIXEL_UNKNOWN || config->reloading)) { |
428 | sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name, | 430 | sway_log(SWAY_DEBUG, "Set %s subpixel to %s", oc->name, |
429 | sway_wl_output_subpixel_to_string(oc->subpixel)); | 431 | sway_wl_output_subpixel_to_string(oc->subpixel)); |
430 | wlr_output_set_subpixel(wlr_output, oc->subpixel); | 432 | wlr_output_state_set_subpixel(pending, oc->subpixel); |
431 | } | 433 | } |
432 | 434 | ||
433 | enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL; | 435 | enum wl_output_transform tr = WL_OUTPUT_TRANSFORM_NORMAL; |
@@ -439,7 +441,7 @@ static void queue_output_config(struct output_config *oc, | |||
439 | } | 441 | } |
440 | if (wlr_output->transform != tr) { | 442 | if (wlr_output->transform != tr) { |
441 | sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, tr); | 443 | sway_log(SWAY_DEBUG, "Set %s transform to %d", oc->name, tr); |
442 | wlr_output_set_transform(wlr_output, tr); | 444 | wlr_output_state_set_transform(pending, tr); |
443 | } | 445 | } |
444 | 446 | ||
445 | // Apply the scale last before the commit, because the scale auto-detection | 447 | // Apply the scale last before the commit, because the scale auto-detection |
@@ -448,18 +450,18 @@ static void queue_output_config(struct output_config *oc, | |||
448 | if (oc && oc->scale > 0) { | 450 | if (oc && oc->scale > 0) { |
449 | scale = oc->scale; | 451 | scale = oc->scale; |
450 | } else { | 452 | } else { |
451 | scale = compute_default_scale(wlr_output); | 453 | scale = compute_default_scale(wlr_output, pending); |
452 | sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale); | 454 | sway_log(SWAY_DEBUG, "Auto-detected output scale: %f", scale); |
453 | } | 455 | } |
454 | if (scale != wlr_output->scale) { | 456 | if (scale != wlr_output->scale) { |
455 | sway_log(SWAY_DEBUG, "Set %s scale to %f", wlr_output->name, scale); | 457 | sway_log(SWAY_DEBUG, "Set %s scale to %f", wlr_output->name, scale); |
456 | wlr_output_set_scale(wlr_output, scale); | 458 | wlr_output_state_set_scale(pending, scale); |
457 | } | 459 | } |
458 | 460 | ||
459 | if (oc && oc->adaptive_sync != -1) { | 461 | if (oc && oc->adaptive_sync != -1) { |
460 | sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name, | 462 | sway_log(SWAY_DEBUG, "Set %s adaptive sync to %d", wlr_output->name, |
461 | oc->adaptive_sync); | 463 | oc->adaptive_sync); |
462 | wlr_output_enable_adaptive_sync(wlr_output, oc->adaptive_sync == 1); | 464 | wlr_output_state_set_adaptive_sync_enabled(pending, oc->adaptive_sync == 1); |
463 | } | 465 | } |
464 | 466 | ||
465 | if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { | 467 | if (oc && oc->render_bit_depth != RENDER_BIT_DEPTH_DEFAULT) { |
@@ -467,8 +469,8 @@ static void queue_output_config(struct output_config *oc, | |||
467 | assert(fmts); | 469 | assert(fmts); |
468 | 470 | ||
469 | for (size_t i = 0; fmts[i] != DRM_FORMAT_INVALID; i++) { | 471 | for (size_t i = 0; fmts[i] != DRM_FORMAT_INVALID; i++) { |
470 | wlr_output_set_render_format(wlr_output, fmts[i]); | 472 | wlr_output_state_set_render_format(pending, fmts[i]); |
471 | if (wlr_output_test(wlr_output)) { | 473 | if (wlr_output_test_state(wlr_output, pending)) { |
472 | break; | 474 | break; |
473 | } | 475 | } |
474 | 476 | ||
@@ -489,14 +491,15 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { | |||
489 | // Flag to prevent the output mode event handler from calling us | 491 | // Flag to prevent the output mode event handler from calling us |
490 | output->enabling = (!oc || oc->enabled); | 492 | output->enabling = (!oc || oc->enabled); |
491 | 493 | ||
492 | queue_output_config(oc, output); | 494 | struct wlr_output_state pending = {0}; |
495 | queue_output_config(oc, output, &pending); | ||
493 | 496 | ||
494 | if (!oc || oc->dpms_state != DPMS_OFF) { | 497 | if (!oc || oc->dpms_state != DPMS_OFF) { |
495 | output->current_mode = wlr_output->pending.mode; | 498 | output->current_mode = pending.mode; |
496 | } | 499 | } |
497 | 500 | ||
498 | sway_log(SWAY_DEBUG, "Committing output %s", wlr_output->name); | 501 | sway_log(SWAY_DEBUG, "Committing output %s", wlr_output->name); |
499 | if (!wlr_output_commit(wlr_output)) { | 502 | if (!wlr_output_commit_state(wlr_output, &pending)) { |
500 | // Failed to commit output changes, maybe the output is missing a CRTC. | 503 | // Failed to commit output changes, maybe the output is missing a CRTC. |
501 | // Leave the output disabled for now and try again when the output gets | 504 | // Leave the output disabled for now and try again when the output gets |
502 | // the mode we asked for. | 505 | // the mode we asked for. |
@@ -579,10 +582,9 @@ bool test_output_config(struct output_config *oc, struct sway_output *output) { | |||
579 | return false; | 582 | return false; |
580 | } | 583 | } |
581 | 584 | ||
582 | queue_output_config(oc, output); | 585 | struct wlr_output_state pending = {0}; |
583 | bool ok = wlr_output_test(output->wlr_output); | 586 | queue_output_config(oc, output, &pending); |
584 | wlr_output_rollback(output->wlr_output); | 587 | return wlr_output_test_state(output->wlr_output, &pending); |
585 | return ok; | ||
586 | } | 588 | } |
587 | 589 | ||
588 | static void default_output_config(struct output_config *oc, | 590 | static void default_output_config(struct output_config *oc, |