fix: error state set in createmon for hdr

This commit is contained in:
DreamMaoMao 2026-07-12 08:13:43 +08:00
parent bcb4f12e0b
commit 685a46ef1c
3 changed files with 100 additions and 59 deletions

View file

@ -113,18 +113,21 @@ void output_state_setup_hdr(Monitor *m, bool silent,
if (!silent) if (!silent)
wlr_log(WLR_INFO, wlr_log(WLR_INFO,
"No 10 bit color formats supported, HDR disabled."); "No 10 bit color formats supported, HDR disabled.");
if (!output_set_render_format(m, output_formats_8bit, hdr_succeeded = output_set_render_format(
ARRAY_SIZE(output_formats_8bit), m, output_formats_8bit, ARRAY_SIZE(output_formats_8bit), state);
state)) if (!hdr_succeeded) {
if (!silent) if (!silent)
wlr_log(WLR_ERROR, "No 8 bit color formats either!"); wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
}
} }
} else { } else {
// 明确要求8位或自动降级 // 明确要求8位或自动降级
if (!output_set_render_format(m, output_formats_8bit, hdr_succeeded = output_set_render_format(
ARRAY_SIZE(output_formats_8bit), state)) m, output_formats_8bit, ARRAY_SIZE(output_formats_8bit), state);
if (!hdr_succeeded) {
if (!silent) if (!silent)
wlr_log(WLR_ERROR, "No 8 bit color formats supported!"); wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
}
} }
output_enable_hdr(m, state, hdr_succeeded, silent); output_enable_hdr(m, state, hdr_succeeded, silent);

View file

@ -1225,7 +1225,7 @@ void pre_caculate_before_arrange(Monitor *m, bool want_animation,
void // 17 void // 17
arrange(Monitor *m, bool want_animation, bool from_view) { arrange(Monitor *m, bool want_animation, bool from_view) {
if (!m) if (!m || m->iscleanuping)
return; return;
if (!m->wlr_output->enabled) if (!m->wlr_output->enabled)

View file

@ -3432,8 +3432,6 @@ bool apply_rule_to_state(Monitor *m, const ConfigMonitorRule *rule,
} }
void createmon(struct wl_listener *listener, void *data) { void createmon(struct wl_listener *listener, void *data) {
/* This event is raised by the backend when a new output (aka a display or
* monitor) becomes available. */
struct wlr_output *wlr_output = data; struct wlr_output *wlr_output = data;
const ConfigMonitorRule *r; const ConfigMonitorRule *r;
uint32_t i; uint32_t i;
@ -3464,7 +3462,6 @@ void createmon(struct wl_listener *listener, void *data) {
m->carousel_anim_dir = 0; m->carousel_anim_dir = 0;
m->vrr_global_enable = false; m->vrr_global_enable = false;
m->is_vrr_opening = false; m->is_vrr_opening = false;
m->hdr_enable = false; m->hdr_enable = false;
m->prefer_disable = false; m->prefer_disable = false;
@ -3483,12 +3480,14 @@ void createmon(struct wl_listener *listener, void *data) {
m->is_in_hotarea = 0; m->is_in_hotarea = 0;
m->m.x = INT32_MAX; m->m.x = INT32_MAX;
m->m.y = INT32_MAX; m->m.y = INT32_MAX;
// 临时 pending 状态,用于匹配规则时暂存设置
struct wlr_output_state pending;
wlr_output_state_init(&pending);
float scale = 1; float scale = 1;
enum wl_output_transform rr = WL_OUTPUT_TRANSFORM_NORMAL; enum wl_output_transform rr = WL_OUTPUT_TRANSFORM_NORMAL;
wlr_output_state_set_scale(&pending, scale);
wlr_output_state_init(&m->pending); wlr_output_state_set_transform(&pending, rr);
wlr_output_state_set_scale(&m->pending, scale);
wlr_output_state_set_transform(&m->pending, rr);
for (ji = 0; ji < config.monitor_rules_count; ji++) { for (ji = 0; ji < config.monitor_rules_count; ji++) {
if (config.monitor_rules_count < 1) if (config.monitor_rules_count < 1)
@ -3500,7 +3499,7 @@ void createmon(struct wl_listener *listener, void *data) {
m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x; m->m.x = r->x == INT32_MAX ? INT32_MAX : r->x;
m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y; m->m.y = r->y == INT32_MAX ? INT32_MAX : r->y;
if (apply_rule_to_state(m, r, &m->pending)) { if (apply_rule_to_state(m, r, &pending)) {
custom_monitor_mode = true; custom_monitor_mode = true;
} }
break; // 只应用第一个匹配规则 break; // 只应用第一个匹配规则
@ -3508,25 +3507,88 @@ void createmon(struct wl_listener *listener, void *data) {
} }
if (!custom_monitor_mode) if (!custom_monitor_mode)
wlr_output_state_set_mode(&m->pending, wlr_output_state_set_mode(&pending,
wlr_output_preferred_mode(wlr_output)); wlr_output_preferred_mode(wlr_output));
/* Set up event listeners */ // ===================================================
LISTEN(&wlr_output->events.frame, &m->frame, rendermon); // 构建最终的输出状态,包含 HDR并通过 scene 提交
LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon); // ===================================================
LISTEN(&wlr_output->events.request_state, &m->request_state, struct wlr_output_state state;
requestmonstate); wlr_output_state_init(&state);
// 启用/禁用
if (m->prefer_disable) { if (m->prefer_disable) {
wlr_output_state_set_enabled(&m->pending, false); wlr_output_state_set_enabled(&state, false);
} else { } else {
wlr_output_state_set_enabled(&m->pending, true); wlr_output_state_set_enabled(&state, true);
} }
mango_output_commit(m); // 模式设置
if (pending.committed & WLR_OUTPUT_STATE_MODE) {
if (pending.mode_type == WLR_OUTPUT_STATE_MODE_FIXED) {
wlr_output_state_set_mode(&state, pending.mode);
} else if (pending.mode_type == WLR_OUTPUT_STATE_MODE_CUSTOM) {
wlr_output_state_set_custom_mode(&state, pending.custom_mode.width,
pending.custom_mode.height,
pending.custom_mode.refresh);
}
} else {
// 兜底,使用首选模式
struct wlr_output_mode *pref = wlr_output_preferred_mode(wlr_output);
if (pref)
wlr_output_state_set_mode(&state, pref);
}
// 缩放、变换
if (pending.committed & WLR_OUTPUT_STATE_SCALE)
wlr_output_state_set_scale(&state, pending.scale);
if (pending.committed & WLR_OUTPUT_STATE_TRANSFORM)
wlr_output_state_set_transform(&state, pending.transform);
// 自适应同步 (VRR)
if (pending.committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED)
wlr_output_state_set_adaptive_sync_enabled(
&state, pending.adaptive_sync_enabled);
// HDR 设置
if (m->hdr_enable) {
output_state_setup_hdr(m, false, &state);
}
// 创建 scene_output如果尚未创建
m->scene_output = wlr_scene_output_create(scene, wlr_output);
// 通过 scene 构建最终提交状态(初始化 swapchain
struct wlr_scene_output_state_options opts = {
.swapchain = NULL, // 让 scene 自动创建
.color_transform = NULL,
};
wlr_scene_output_build_state(m->scene_output, &state, &opts);
wlr_output_commit_state(wlr_output, &state);
wlr_output_state_finish(&state);
wlr_output_state_finish(&pending);
// 加入布局
struct wlr_output_layout_output *layout_output;
if (m->m.x == INT32_MAX || m->m.y == INT32_MAX)
layout_output = wlr_output_layout_add_auto(output_layout, wlr_output);
else
layout_output =
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
wlr_scene_output_layout_add_output(scene_layout, layout_output,
m->scene_output);
// 获取有效分辨率
wlr_output_effective_resolution(wlr_output, &m->m.width, &m->m.height);
// 加入全局 monitor 链表
wl_list_insert(&mons, &m->link); wl_list_insert(&mons, &m->link);
// 初始化 Pertag 等
m->pertag = calloc(1, sizeof(Pertag)); m->pertag = calloc(1, sizeof(Pertag));
for (int i = 0; i < LENGTH(tags) + 1; i++) for (int i = 0; i < LENGTH(tags) + 1; i++)
m->pertag->scroller_state[i] = NULL; m->pertag->scroller_state[i] = NULL;
@ -3548,49 +3610,17 @@ void createmon(struct wl_listener *listener, void *data) {
m->pertag->ltidxs[i] = &layouts[0]; m->pertag->ltidxs[i] = &layouts[0];
} }
// apply tag rule // 应用 tag rule
parse_tagrule(m); parse_tagrule(m);
/* The xdg-protocol specifies:
*
* If the fullscreened surface is not opaque, the compositor must make
* sure that other screen content not part of the same surface tree (made
* up of subsurfaces, popups or similarly coupled surfaces) are not
* visible below the fullscreened surface.
*
*/
/* Adds this to the output layout in the order it was configured.
*
* The output layout utility automatically adds a wl_output global to the
* display, which Wayland clients can see to find out information about the
* output (such as DPI, scale factor, manufacturer, etc).
*/
struct wlr_output_layout_output *layout_output;
m->scene_output = wlr_scene_output_create(scene, wlr_output);
if (m->m.x == INT32_MAX || m->m.y == INT32_MAX)
layout_output = wlr_output_layout_add_auto(output_layout, wlr_output);
else
layout_output =
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
wlr_scene_output_layout_add_output(scene_layout, layout_output,
m->scene_output);
if (m->hdr_enable) {
output_state_setup_hdr(m, false, &m->pending);
}
mango_scene_output_commit(m->scene_output, &m->pending);
wlr_output_effective_resolution(m->wlr_output, &m->m.width, &m->m.height);
if (config.blur) { if (config.blur) {
m->blur = wlr_scene_optimized_blur_create(&scene->tree, 0, 0); m->blur = wlr_scene_optimized_blur_create(&scene->tree, 0, 0);
wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y); wlr_scene_node_set_position(&m->blur->node, m->m.x, m->m.y);
wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]); wlr_scene_node_reparent(&m->blur->node, layers[LyrBlur]);
wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height); wlr_scene_optimized_blur_set_size(m->blur, m->m.width, m->m.height);
} }
// ext workspace group
m->ext_group = wlr_ext_workspace_group_handle_v1_create( m->ext_group = wlr_ext_workspace_group_handle_v1_create(
ext_manager, EXT_WORKSPACE_ENABLE_CAPS); ext_manager, EXT_WORKSPACE_ENABLE_CAPS);
wlr_ext_workspace_group_handle_v1_output_enter(m->ext_group, m->wlr_output); wlr_ext_workspace_group_handle_v1_output_enter(m->ext_group, m->wlr_output);
@ -3599,6 +3629,14 @@ void createmon(struct wl_listener *listener, void *data) {
add_workspace_by_tag(i, m); add_workspace_by_tag(i, m);
} }
updatemons(NULL, NULL);
// 设置监听器
LISTEN(&wlr_output->events.frame, &m->frame, rendermon);
LISTEN(&wlr_output->events.destroy, &m->destroy, cleanupmon);
LISTEN(&wlr_output->events.request_state, &m->request_state,
requestmonstate);
printstatus(IPC_WATCH_ARRANGGE); printstatus(IPC_WATCH_ARRANGGE);
} }