opt: Reconstruct the output commit logic

This commit is contained in:
DreamMaoMao 2026-06-25 10:37:52 +08:00
parent a7838855a8
commit 444e0decea
6 changed files with 112 additions and 103 deletions

View file

@ -16,10 +16,11 @@ static uint32_t output_formats_10bit[] = {
};
static bool output_set_render_format(Monitor *m, uint32_t candidates[],
size_t count) {
size_t count,
struct wlr_output_state *state) {
for (size_t i = 0; i < count; i++) {
wlr_output_state_set_render_format(&m->pending, candidates[i]);
if (wlr_output_test_state(m->wlr_output, &m->pending))
wlr_output_state_set_render_format(state, candidates[i]);
if (wlr_output_test_state(m->wlr_output, state))
return true;
}
return false;
@ -83,7 +84,8 @@ void output_enable_hdr(Monitor *m, struct wlr_output_state *os, bool enabled,
wlr_output_state_set_image_description(os, &desc);
}
void output_state_setup_hdr(Monitor *m, bool silent) {
void output_state_setup_hdr(Monitor *m, bool silent,
struct wlr_output_state *state) {
uint32_t render_format = m->wlr_output->render_format;
const char *unsupported_reason = NULL;
bool hdr_supported =
@ -106,23 +108,24 @@ void output_state_setup_hdr(Monitor *m, bool silent) {
hdr_succeeded = true; // 上次已经成功设置10位直接复用
} else if (depth == MANGO_RENDER_BIT_DEPTH_10) {
hdr_succeeded = output_set_render_format(
m, output_formats_10bit, ARRAY_SIZE(output_formats_10bit));
m, output_formats_10bit, ARRAY_SIZE(output_formats_10bit), state);
if (!hdr_succeeded) {
if (!silent)
wlr_log(WLR_INFO,
"No 10 bit color formats supported, HDR disabled.");
if (!output_set_render_format(m, output_formats_8bit,
ARRAY_SIZE(output_formats_8bit)))
ARRAY_SIZE(output_formats_8bit),
state))
if (!silent)
wlr_log(WLR_ERROR, "No 8 bit color formats either!");
}
} else {
// 明确要求8位或自动降级
if (!output_set_render_format(m, output_formats_8bit,
ARRAY_SIZE(output_formats_8bit)))
ARRAY_SIZE(output_formats_8bit), state))
if (!silent)
wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
}
output_enable_hdr(m, &m->pending, hdr_succeeded, silent);
output_enable_hdr(m, state, hdr_succeeded, silent);
}

View file

@ -1,3 +1,4 @@
#include <stdbool.h>
#include <wlr/types/wlr_tearing_control_v1.h>
struct tearing_controller {
@ -64,6 +65,9 @@ bool check_tearing_frame_allow(Monitor *m) {
return false;
}
if (!selmon)
return false;
Client *c = selmon->sel;
/* tearing is only allowed for the output with the active client */
@ -94,50 +98,3 @@ bool check_tearing_frame_allow(Monitor *m) {
/* honor tearing as requested by action */
return c->force_tearing == STATE_ENABLED;
}
bool custom_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
struct wlr_output_state *state) {
struct wlr_output *wlr_output = scene_output->output;
Monitor *m = wlr_output->data;
if (!wlr_scene_output_needs_frame(scene_output))
return true;
// 构建状态,将场景的 Buffer 附着到 state 上
if (!wlr_scene_output_build_state(scene_output, state, NULL))
return false;
// 测试是否支持撕裂
if (!wlr_output_test_state(wlr_output, state)) {
// 如果 DRM 拒绝(例如当前输出/驱动不支持撕裂),降级关闭撕裂
state->tearing_page_flip = false;
}
// 提交状态
bool committed = wlr_output_commit_state(wlr_output, state);
if (!committed && state->tearing_page_flip) {
// 重试一次
state->tearing_page_flip = false;
committed = wlr_output_commit_state(wlr_output, state);
}
if (committed) {
if (state == &m->pending) {
wlr_output_state_finish(&m->pending);
wlr_output_state_init(&m->pending);
}
}
return committed;
}
void apply_tear_state(Monitor *m) {
if (!wlr_scene_output_needs_frame(m->scene_output))
return;
wlr_output_state_init(&m->pending);
m->pending.tearing_page_flip = true;
if (!custom_wlr_scene_output_commit(m->scene_output, &m->pending)) {
wlr_log(WLR_ERROR, "Failed to commit output %s",
m->scene_output->output->name);
}
}