diff --git a/NEWS.md b/NEWS.md index 997f4068..2e0a6109 100644 --- a/NEWS.md +++ b/NEWS.md @@ -264,9 +264,9 @@ Note to package maintainers: This release requires wayland version >=1.22.90 - Add theme option window.button.hover.bg.color [#3365] @johanmalm - Implement scrollable window-switcher OSD [#3291] @tokyo4j - Support the `NextWindow` options listed below [#3271] @tokyo4j - - `` - - `` - - `` + - `` + - `` + - `` - Add config option `*` for setting the active workspace on startup. [#3265] @5trixs0f @@ -314,7 +314,7 @@ Note to package maintainers: This release requires wayland version >=1.22.90 and get keyboard focus so that they can be operated with the keyboard. An example use-case is the xfce4-panel applications-menu being opened by the command xfce4-popup-applicationsmenu. [#3165] @johanmalm - - On popup destory, return focus to whoever had it before the popop [#3165] + - On popup destroy, return focus to whoever had it before the popop [#3165] @johanmalm @tokyo4j - Unshade window if selected from client-list-combined-menu [#3345] @Amodio - Show non-dialog child windows in window-switcher [#3339] @tokyo4j @@ -348,7 +348,7 @@ A big thank you to all involved in this release. ### Added -- Add `` to optionally order windows by age +- Add `` to optionally order windows by age rather than most recent focus. @mbroemme [#3229] - Replace `` with `` to provide more granular control when configuring the size of snapping areas @@ -379,7 +379,7 @@ A big thank you to all involved in this release. [#3134] - labnag: add --keyboard-focus option @tokyo4j [#3120] - Allow window switcher to temporarily unshade windows using config option - `` @Amodio @Consolatis [#3124] + `` @Amodio @Consolatis [#3124] - For the 'classic' style window-switcher, add the following theme options: - `osd.window-switcher.style-classic.item.active.border.color` - `osd.window-switcher.style-classic.item.active.bg.color` @@ -409,7 +409,7 @@ A big thank you to all involved in this release. client surface. Fixes a regression in 885919f. @tokyo4j [#3211] - Set all foreign-toplevel initial states correctly. This is not believed to fix any particular user-issue, but just feels safer. @jlindgren90 [#3217] -- Update layer-shell client top layer visiblity on unmap instead of destroy +- Update layer-shell client top layer visibility on unmap instead of destroy because it is possible for fullscreen xwayland windows to be unmapped without being destroyed, and in this case the top layer visibility needs to be updated to unhide other layer-shell clients like panels. @jlindgren90 [#3199] @@ -421,7 +421,7 @@ A big thank you to all involved in this release. @elviosak [#3146] [#3168] - Work around client-side rounding issues at right/bottom pixel. This fixes an issue with some clients (notably Qt ones) where cursor coordinates in the - rightmost or bottom fixel are incorrectly rounded up putting them outside the + rightmost or bottom pixel are incorrectly rounded up putting them outside the surface bounds. The issue has been particularly noticeable with layer-shell clients like lxqt-panel. @jlindgren90 [#3157] [#2379] [#3099] Note: This also avoids a similar server-side rounding issue with some @@ -469,7 +469,7 @@ A big thank you to all involved in this release. when a window is using fullscreen mode. @johanmalm [#3158] - Call labnag with on-demand keyboard interactivity by default @tokyo4j [#3120] - Temporarily unshade windows when switching windows. Restore old behaviour with - `` @Amodio @Consolatis [#3124] + `` @Amodio @Consolatis [#3124] - In the classic style window-switcher, the default color of the selected window item has been changed to inherit the border color but with 15% opacity @tokyo4j [#3118] @@ -488,7 +488,7 @@ A big thank you to all involved in this release. ``. @tokyo4j [#2981] - Add `toggle` option to `GoToDesktop` action. This has the effect of going back to the last desktop if already on the target. @RainerKuemmerle [#3024] -- Add `` to allow hiding titlebar +- Add `` to allow hiding titlebar when window is maximized. @CosmicFusion @tokyo4j [#3015] - Use client-send-to-menu as 'Workspace' submenu in built-in client-menu @johanmalm [#2995] @@ -539,7 +539,7 @@ A big thank you to all involved in this release. - Change default keybind `W-` to combine cardinal directions to support resizing of windows to fill a quarter of an output. This only affects users who do not use an `rc.xml` (thereby using default keybinds) or use the - `` option. Previous behavior can be restored by setting + `` option. Previous behavior can be restored by setting `combine="no"` as shown below. [#3081] @tokyo4j ``` @@ -638,7 +638,7 @@ window.*.title.bg.colorTo.splitTo: window rule to enable this. @Consolatis @tokyo4j [#2840] - Add config option ``. This enables autoscroll (middle-click to scroll up/down) in Chromium and electron based clients - without inadvertantly pasting the primary clipboard. @johanmalm [#2832] + without inadvertently pasting the primary clipboard. @johanmalm [#2832] - Bump `xdg_shell` version from 3 to 6 @tokyo4j [#2814] - Bump `wl_compositor` version from 5 to 6 @tokyo4j [#2812] - Support tablet tool mouse buttons @jp7677 [#2778] @@ -715,7 +715,7 @@ window.*.title.bg.colorTo.splitTo: agnostic on choice of launcher. - `A-` for `MoveToEdge` because `Alt-` keybinds should be for clients to use and this one results in frequent user complaints because it prevents - some common usage patterns like alt-left/right in web browers. + some common usage patterns like alt-left/right in web browsers. - Change default titlebar menu button from a dot to an arrow @johanmalm [#2844] - When `dragLock` is set to `yes`, the drag no longer expires after a short delay (known as `Sticky` mode) as recommended by libinput [#2803]. The timeout @@ -750,7 +750,7 @@ release. - Localize desktop-entry application names used by the window switcher via `desktop_entry_name` or the `%n` specifier @tokyo4j [#2653] - Add `HideCursor` action @jp7677 [#2633] -- Support application icons in window-switcher using `` +- Support application icons in window-switcher using `` and use this by default. @tokyo4j [#2621] - Support application icons in client-list-combined-menu @tokyo4j [#2617] - Support the use of the keypad-enter key when using menu. @zeusgoose [#2610] @@ -887,7 +887,7 @@ Notes to package maintainers: closing a popup did not move the pointer focus to the main toplevel until the cursor was moved. [#2443] - Improve algorithm for menu placement with xdg-positioner [#2408] -- Do not forward IME key-release without correspinding key-press to avoid stuck +- Do not forward IME key-release without corresponding key-press to avoid stuck keys [#2437] ### Changed @@ -949,7 +949,7 @@ Notes to package maintainers: ```xml - + ``` @@ -966,8 +966,8 @@ menu.border.color: #aaaaaa ```xml - - + + ``` @@ -1097,7 +1097,7 @@ Notes to package maintainers: - Support the openbox style menus listed below. Written-by: @droc12345 1. `client-list-combined-menu` shows windows across all workspaces. This can be used with a mouse/key bind using: - `` [#2101] + `` [#2101] 2. `client-send-to` shows all workspaces that the current window can be sent to. This can additional be used within a client menu using: `` [#2152] @@ -1256,14 +1256,14 @@ have been attributed with a 'Written-by' against each relevant log entry. ```xml cascade - + ``` - Support relative tablet motion. Written-by: @jp7677 [#1962] ```xml - + ``` ### Fixed @@ -1347,7 +1347,7 @@ joint effort by @spl237 and @Consolatis. - Respect `menu.overlap.x` when using pipemenus. [#1940] - Do not try to restore windows to very small width/height on unmaximize. This fixes a bug with Thonny (Python IDE made with Tk). [#1938] -- Conditially set squared server-side decoration (SSD) corners when a view is +- Conditionally set squared server-side decoration (SSD) corners when a view is tiled. Written-by: @jp7677 [#1926] - Remember initial direction when starting window-cycling with `PreviousView`. Also make the toggling of direction when shift is pressed relative to the @@ -1371,7 +1371,7 @@ joint effort by @spl237 and @Consolatis. Chromium and Steam. [#1861] - Session-lock: fix flashing & update cursor shape. [#1858] - Remove tearing-controller listeners on destroy. [#1853] -- Handle invalid `ForEach` and `If` action cofigs. [#1838] +- Handle invalid `ForEach` and `If` action configs. [#1838] - Delay startup of applications until event loop is ready. This avoids race conditions when using autostart scripts that trigger a labwc SIGHUP. [#1588] - With `SendToDesktop` action follow=no option, ensure the topmost window is @@ -1388,7 +1388,7 @@ joint effort by @spl237 and @Consolatis. - Remove subprojects/seatd.wrap as no longer needed - Action `MoveToCursor` is deprecated in favour of: - ``. + ``. ## 0.7.2 - 2024-05-10 @@ -1405,7 +1405,7 @@ contributions from others as noted in the log. ### Added - Add `` to prevent clicks with small movements - from inadvertantly closing a menu or selecting a menu item. This is the + from inadvertently closing a menu or selecting a menu item. This is the equivalent of `` on Openbox. [#1760] - Support drop-shadows (disabled by default) for windows using server-side decorations. Written-by: @cillian64 @@ -1433,7 +1433,7 @@ window.inactive.shadow.color: #00000040 ```xml - + @@ -1475,7 +1475,7 @@ osd.window-switcher.width: 75% yes|no - + ``` @@ -1638,7 +1638,7 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff ```xml - + ``` @@ -1646,7 +1646,7 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff is already used by the action itself). [#1589] ```xml - + ``` - Do not deactivate window when giving keyboard focus to a non-view @@ -1711,8 +1711,8 @@ osd.window-switcher.preview.border.color: #ffffff,#00a2ff,#ffffff Written-by: @jp7677 ```xml - - + + ``` - Add tablet support including: @@ -1925,7 +1925,7 @@ relating to surface focus and keyboard issues, amongst others. - Allow referencing the current workspace in actions, for example: ```xml - + ``` ### Fixed @@ -2081,7 +2081,7 @@ relating to surface focus and keyboard issues, amongst others. ```xml - + ``` @@ -2148,9 +2148,9 @@ relating to surface focus and keyboard issues, amongst others. ```xml - + - + ``` @@ -2235,7 +2235,7 @@ Unless otherwise stated all contributions are by the core-devs ```xml - + @@ -2499,7 +2499,7 @@ reported, tested and fixed issues. Particular mentions go to @bi4k8, actions to be de-coupled from buttons. As a result, "Drag" and "DoubleClick" actions previously defined against "TitleBar" should now come under the "Title" context, for example: - `` + `` - Remove default alt-escape keybind for Exit because too many people have exited the compositor by mistake trying to get out of alt-tab cycling or similar. diff --git a/docs/labwc-config.5.scd b/docs/labwc-config.5.scd index 8ea88d8f..240f7043 100644 --- a/docs/labwc-config.5.scd +++ b/docs/labwc-config.5.scd @@ -175,6 +175,7 @@ this is for compatibility with Openbox. no no yes + no no no yes @@ -240,6 +241,11 @@ this is for compatibility with Openbox. 'pkill kanshi ; wlopm --off \*' resume 'kanshi & wlopm --on \*' ``` +** [yes|no] + Automatically enable HDR support on outputs when configuring them, + where supported by the particular output device and display. Default + is no. + ** [yes|no] Try to re-use the existing output mode (resolution / refresh rate). This may prevent unnecessary screenblank delays when starting labwc diff --git a/docs/rc.xml.all b/docs/rc.xml.all index 9755530b..54c9e300 100644 --- a/docs/rc.xml.all +++ b/docs/rc.xml.all @@ -13,6 +13,7 @@ no no yes + no no no yes diff --git a/include/common/macros.h b/include/common/macros.h index 25226261..f3ceee82 100644 --- a/include/common/macros.h +++ b/include/common/macros.h @@ -62,7 +62,11 @@ #define BOUNDED_INT(a) ((a) < INT_MAX && (a) > INT_MIN) #endif -#define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) \ - (WLR_VERSION_NUM >= (((major) << 16) | ((minor) << 8) | (micro))) +#define _LAB_CALC_WLR_VERSION_NUM(major, minor, micro) (((major) << 16) | ((minor) << 8) | (micro)) + +#define LAB_WLR_VERSION_AT_LEAST(major, minor, micro) ( \ + server.wlr_version >= _LAB_CALC_WLR_VERSION_NUM(major, minor, micro)) + +#define LAB_WLR_VERSION_LOWER(major, minor, micro) (!LAB_WLR_VERSION_AT_LEAST(major, minor, micro)) #endif /* LABWC_MACROS_H */ diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 3ef7bd67..9c2183a8 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -36,6 +36,12 @@ enum tearing_mode { LAB_TEARING_FULLSCREEN_FORCED, }; +enum render_bit_depth { + LAB_RENDER_BIT_DEPTH_DEFAULT = 0, + LAB_RENDER_BIT_DEPTH_8, + LAB_RENDER_BIT_DEPTH_10, +}; + enum tiling_events_mode { LAB_TILING_EVENTS_NEVER = 0, LAB_TILING_EVENTS_REGION = 1 << 0, @@ -74,6 +80,7 @@ struct rcxml { int gap; enum adaptive_sync_mode adaptive_sync; enum tearing_mode allow_tearing; + enum render_bit_depth target_render_depth; bool auto_enable_outputs; bool reuse_output_mode; uint32_t allowed_interfaces; diff --git a/include/labwc.h b/include/labwc.h index dc4c1311..edde2771 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -148,6 +148,8 @@ struct seat { }; struct server { + uint32_t wlr_version; + struct wl_display *wl_display; struct wl_event_loop *wl_event_loop; /* Can be used for timer events */ diff --git a/include/output.h b/include/output.h index 89d8be04..c17defa4 100644 --- a/include/output.h +++ b/include/output.h @@ -71,6 +71,9 @@ struct wlr_box output_usable_area_in_layout_coords(struct output *output); void handle_output_power_manager_set_mode(struct wl_listener *listener, void *data); void output_enable_adaptive_sync(struct output *output, bool enabled); +void output_enable_hdr(struct output *output, struct wlr_output_state *os, + bool enabled, bool silent); +void output_state_setup_hdr(struct output *output, bool silent); /** * Notifies whether a fullscreen view is displayed on the given output. diff --git a/src/config/rcxml.c b/src/config/rcxml.c index d0bb76db..0514b6c7 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1080,6 +1080,16 @@ set_tearing_mode(const char *str, enum tearing_mode *variable) } } +static void +set_hdr_mode(const char *str, enum render_bit_depth *variable) +{ + if (parse_bool(str, -1) == 1) { + *variable = LAB_RENDER_BIT_DEPTH_10; + } else { + *variable = LAB_RENDER_BIT_DEPTH_8; + } +} + /* Returns true if the node's children should also be traversed */ static bool entry(xmlNode *node, char *nodename, char *content) @@ -1144,6 +1154,8 @@ entry(xmlNode *node, char *nodename, char *content) set_adaptive_sync_mode(content, &rc.adaptive_sync); } else if (!strcasecmp(nodename, "allowTearing.core")) { set_tearing_mode(content, &rc.allow_tearing); + } else if (!strcasecmp(nodename, "Hdr.core")) { + set_hdr_mode(content, &rc.target_render_depth); } else if (!strcasecmp(nodename, "autoEnableOutputs.core")) { set_bool(content, &rc.auto_enable_outputs); } else if (!strcasecmp(nodename, "reuseOutputMode.core")) { @@ -1518,6 +1530,7 @@ rcxml_init(void) rc.gap = 0; rc.adaptive_sync = LAB_ADAPTIVE_SYNC_DISABLED; rc.allow_tearing = LAB_TEARING_DISABLED; + rc.target_render_depth = LAB_RENDER_BIT_DEPTH_DEFAULT; rc.auto_enable_outputs = true; rc.reuse_output_mode = false; rc.allowed_interfaces = UINT32_MAX; diff --git a/src/cycle/cycle.c b/src/cycle/cycle.c index 14682c9f..0f183ddc 100644 --- a/src/cycle/cycle.c +++ b/src/cycle/cycle.c @@ -9,6 +9,7 @@ #include "common/mem.h" #include "common/scene-helpers.h" #include "config/rcxml.h" +#include "config/types.h" #include "labwc.h" #include "node.h" #include "output.h" @@ -322,6 +323,27 @@ handle_osd_tree_destroy(struct wl_listener *listener, void *data) free(osd_output); } +static enum lab_view_criteria +get_view_criteria(struct cycle_filter *filter) +{ + enum lab_view_criteria criteria = + LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER + | LAB_VIEW_CRITERIA_NO_DIALOG; + if (filter->workspace == CYCLE_WORKSPACE_CURRENT) { + criteria |= LAB_VIEW_CRITERIA_CURRENT_WORKSPACE; + } + return criteria; +} + +static const char * +get_cycle_app_id(struct cycle_filter *filter) +{ + if (filter->app_id == CYCLE_APP_ID_CURRENT && server.active_view) { + return server.active_view->app_id; + } + return NULL; +} + static struct wl_list *prev(struct wl_list *elm) { return elm->prev; } static struct wl_list *next(struct wl_list *elm) { return elm->next; } @@ -331,17 +353,10 @@ cycle_immediate(enum lab_cycle_dir direction, struct cycle_filter filter) if (wl_list_empty(&server.views)) { return; } - enum lab_view_criteria criteria = - LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER - | LAB_VIEW_CRITERIA_NO_DIALOG; - if (filter.workspace == CYCLE_WORKSPACE_CURRENT) { - criteria |= LAB_VIEW_CRITERIA_CURRENT_WORKSPACE; - } + + enum lab_view_criteria criteria = get_view_criteria(&filter); uint64_t cycle_outputs = get_outputs_by_filter(filter.output); - const char *cycle_app_id = NULL; - if (filter.app_id == CYCLE_APP_ID_CURRENT && server.active_view) { - cycle_app_id = server.active_view->app_id; - } + const char *cycle_app_id = get_cycle_app_id(&filter); struct wl_list *head = &server.views; struct wl_list *(*iter)(struct wl_list *list); @@ -381,20 +396,9 @@ cycle_immediate(enum lab_cycle_dir direction, struct cycle_filter filter) static bool init_cycle(struct cycle_filter filter) { - enum lab_view_criteria criteria = - LAB_VIEW_CRITERIA_NO_SKIP_WINDOW_SWITCHER - | LAB_VIEW_CRITERIA_NO_DIALOG; - if (filter.workspace == CYCLE_WORKSPACE_CURRENT) { - criteria |= LAB_VIEW_CRITERIA_CURRENT_WORKSPACE; - } - - uint64_t cycle_outputs = - get_outputs_by_filter(filter.output); - - const char *cycle_app_id = NULL; - if (filter.app_id == CYCLE_APP_ID_CURRENT && server.active_view) { - cycle_app_id = server.active_view->app_id; - } + enum lab_view_criteria criteria = get_view_criteria(&filter); + uint64_t cycle_outputs = get_outputs_by_filter(filter.output); + const char *cycle_app_id = get_cycle_app_id(&filter); struct view *view; for_each_view(view, &server.views, criteria) { diff --git a/src/main.c b/src/main.c index 373f4480..53f85623 100644 --- a/src/main.c +++ b/src/main.c @@ -4,8 +4,10 @@ #include #include #include +#include #include "common/fd-util.h" #include "common/font.h" +#include "common/macros.h" #include "common/spawn.h" #include "config/rcxml.h" #include "config/session.h" @@ -65,12 +67,15 @@ static void print_version(void) { #define FEATURE_ENABLED(feature) (HAVE_##feature ? "+" : "-") - printf("labwc %s (%sxwayland %snls %srsvg %slibsfdo)\n", + printf("labwc %s (%sxwayland %snls %srsvg %slibsfdo) running on wlroots %d.%d.%d\n", LABWC_VERSION, FEATURE_ENABLED(XWAYLAND), FEATURE_ENABLED(NLS), FEATURE_ENABLED(RSVG), - FEATURE_ENABLED(LIBSFDO) + FEATURE_ENABLED(LIBSFDO), + wlr_version_get_major(), + wlr_version_get_minor(), + wlr_version_get_micro() ); #undef FEATURE_ENABLED } @@ -164,6 +169,12 @@ main(int argc, char *argv[]) char *primary_client = NULL; enum wlr_log_importance verbosity = WLR_ERROR; + server.wlr_version = _LAB_CALC_WLR_VERSION_NUM( + wlr_version_get_major(), + wlr_version_get_minor(), + wlr_version_get_micro() + ); + int c; while (1) { int index = 0; diff --git a/src/output-state.c b/src/output-state.c index 7da1108b..37ebde8a 100644 --- a/src/output-state.c +++ b/src/output-state.c @@ -24,6 +24,7 @@ output_state_init(struct output *output) backup_config, output->wlr_output); wlr_output_head_v1_state_apply(&backup_head->state, &output->pending); + wlr_output_configuration_v1_destroy(backup_config); } diff --git a/src/output.c b/src/output.c index aea35062..29a2d5a0 100644 --- a/src/output.c +++ b/src/output.c @@ -9,6 +9,7 @@ #define _POSIX_C_SOURCE 200809L #include "output.h" #include +#include #include #include #include @@ -51,6 +52,150 @@ #include #endif +static uint32_t output_formats_8bit[] = { + /* 32 bpp RGB with 8 bit component width */ + DRM_FORMAT_XRGB8888, + DRM_FORMAT_XBGR8888, + DRM_FORMAT_RGBX8888, + DRM_FORMAT_BGRX8888, + + DRM_FORMAT_ARGB8888, + DRM_FORMAT_ABGR8888, + DRM_FORMAT_RGBA8888, + DRM_FORMAT_BGRA8888, + + /* 24 bpp RGB */ + DRM_FORMAT_RGB888, + DRM_FORMAT_BGR888, +}; + +uint32_t output_formats_10bit[] = { + /* 32 bpp RGB with 10 bit component width */ + DRM_FORMAT_XRGB2101010, + DRM_FORMAT_XBGR2101010, + DRM_FORMAT_RGBX1010102, + DRM_FORMAT_BGRX1010102, + + DRM_FORMAT_ARGB2101010, + DRM_FORMAT_ABGR2101010, + DRM_FORMAT_RGBA1010102, + DRM_FORMAT_BGRA1010102, +}; + +static bool +output_set_render_format(struct output *output, uint32_t candidates[], size_t count) +{ + for (size_t i = 0; i < count; i++) { + wlr_output_state_set_render_format(&output->pending, candidates[i]); + if (wlr_output_test_state(output->wlr_output, &output->pending)) { + return true; + } + } + return false; +} + +static bool +output_format_in_candidates(uint32_t render_format, uint32_t candidates[], size_t count) +{ + for (size_t i = 0; i < count; i++) { + if (candidates[i] == render_format) { + return true; + } + } + return false; +} + +static enum render_bit_depth +bit_depth_from_format(uint32_t render_format) +{ + if (output_format_in_candidates(render_format, output_formats_10bit, + ARRAY_SIZE(output_formats_10bit))) { + return LAB_RENDER_BIT_DEPTH_10; + } else if (output_format_in_candidates(render_format, output_formats_8bit, + ARRAY_SIZE(output_formats_8bit))) { + return LAB_RENDER_BIT_DEPTH_8; + } + return LAB_RENDER_BIT_DEPTH_DEFAULT; +} + +static enum render_bit_depth +get_config_render_bit_depth(void) +{ + return rc.target_render_depth; +} + +static bool +output_supports_hdr(const struct wlr_output *output, const char **unsupported_reason_ptr) +{ + const char *unsupported_reason = NULL; + if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020)) { + unsupported_reason = "BT2020 primaries not supported by output"; + } else if (!(output->supported_transfer_functions & + WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ)) { + unsupported_reason = "PQ transfer function not supported by output"; + } else if (!server.renderer->features.output_color_transform) { + unsupported_reason = "renderer doesn't support output color transforms"; + } + if (unsupported_reason_ptr) { + *unsupported_reason_ptr = unsupported_reason; + } + return !unsupported_reason; +} + +void +output_state_setup_hdr(struct output *output, bool silent) +{ + uint32_t render_format = output->wlr_output->render_format; + const char *unsupported_reason = NULL; + bool hdr_supported = output_supports_hdr(output->wlr_output, + &unsupported_reason); + bool hdr_succeeded = false; + + enum render_bit_depth render_bit_depth = get_config_render_bit_depth(); + if (render_bit_depth == LAB_RENDER_BIT_DEPTH_DEFAULT) { + render_bit_depth = bit_depth_from_format(render_format); + } + + if (!hdr_supported && render_bit_depth == LAB_RENDER_BIT_DEPTH_10) { + if (!silent) { + wlr_log(WLR_INFO, "Cannot enable HDR on output %s: %s", + output->wlr_output->name, unsupported_reason); + } + render_bit_depth = LAB_RENDER_BIT_DEPTH_8; + } + + if (render_bit_depth == LAB_RENDER_BIT_DEPTH_10 && + bit_depth_from_format(render_format) == render_bit_depth) { + /* 10-bit was set successfully before, try to save some + * tests by reusing the format + */ + hdr_succeeded = true; + } else if (render_bit_depth == LAB_RENDER_BIT_DEPTH_10) { + hdr_succeeded = output_set_render_format(output, output_formats_10bit, + ARRAY_SIZE(output_formats_10bit)); + if (!hdr_succeeded) { + if (!silent) { + wlr_log(WLR_INFO, "No 10 bit color formats" + " supported, HDR disabled."); + } + if (!output_set_render_format(output, output_formats_8bit, + ARRAY_SIZE(output_formats_8bit))) { + if (!silent) { + wlr_log(WLR_ERROR, "No 8 bit color formats" + " supported either!"); + } + } + } + } else { + if (!output_set_render_format(output, output_formats_8bit, + ARRAY_SIZE(output_formats_8bit)) && !silent) { + wlr_log(WLR_ERROR, "No 8 bit color formats supported!"); + } + } + + output_enable_hdr(output, &output->pending, hdr_succeeded, silent); +} + bool output_get_tearing_allowance(struct output *output) { @@ -371,10 +516,7 @@ configure_new_output(struct output *output) output_enable_adaptive_sync(output, true); } - output_state_commit(output); - - wlr_output_effective_resolution(wlr_output, - &output->usable_area.width, &output->usable_area.height); + output_state_setup_hdr(output, false); /* * Wait until wlr_output_layout_add_auto() returns before @@ -384,6 +526,19 @@ configure_new_output(struct output *output) server.pending_output_layout_change++; add_output_to_layout(output); server.pending_output_layout_change--; + + /* + * Commit the output this way instead, HDR needs a buffer, and + * this commit must be called after the output is added to the + * layout above. + */ + lab_wlr_scene_output_commit(output->scene_output, &output->pending); + + /* + * Collect the effective resolution after the final commit. + */ + wlr_output_effective_resolution(wlr_output, + &output->usable_area.width, &output->usable_area.height); } static uint64_t @@ -653,6 +808,7 @@ output_config_apply(struct wlr_output_configuration_v1 *config) wlr_output_state_set_transform(os, head->state.transform); output_enable_adaptive_sync(output, head->state.adaptive_sync_enabled); + output_state_setup_hdr(output, false); } if (!output_state_commit(output)) { /* @@ -666,6 +822,19 @@ output_config_apply(struct wlr_output_configuration_v1 *config) break; } + if (output_enabled) { + /* + * The above commit was likely made without an image + * buffer attached. This will break applying HDR color + * transformation, since image descriptions must be + * committed with a buffer attached. Queue the HDR mode + * again if output is enabled, but make it silent, + * since it would have emitted messages already when + * called above. + */ + output_state_setup_hdr(output, true); + } + /* * Add or remove output from layout only if the commit went * through. Note that at startup, the output may have already @@ -1136,3 +1305,34 @@ output_set_has_fullscreen_view(struct output *output, bool has_fullscreen_view) output_enable_adaptive_sync(output, has_fullscreen_view); output_state_commit(output); } + +void +output_enable_hdr(struct output *output, struct wlr_output_state *os, + bool enabled, bool silent) +{ + if (enabled && !output_supports_hdr(output->wlr_output, NULL)) { + enabled = false; + } + + if (!enabled) { + if (output->wlr_output->supported_primaries != 0 || + output->wlr_output->supported_transfer_functions != 0) { + if (!silent) { + wlr_log(WLR_DEBUG, "Disabling HDR on output %s", + output->wlr_output->name); + } + wlr_output_state_set_image_description(os, NULL); + } + return; + } + + if (!silent) { + wlr_log(WLR_DEBUG, "Enabling HDR on output %s", + output->wlr_output->name); + } + const struct wlr_output_image_description image_desc = { + .primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020, + .transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ, + }; + wlr_output_state_set_image_description(os, &image_desc); +}