mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-25 13:14:13 -04:00
opt: Reconstruct the output commit logic
This commit is contained in:
parent
fde0eee0a5
commit
09e241121e
6 changed files with 112 additions and 103 deletions
61
src/action/monitor.h
Normal file
61
src/action/monitor.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
bool mango_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;
|
||||
bool committed = false;
|
||||
|
||||
bool frame_allow_tearing = check_tearing_frame_allow(m);
|
||||
|
||||
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 (frame_allow_tearing) {
|
||||
state->tearing_page_flip = true;
|
||||
} else {
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
|
||||
// 测试是否支持撕裂
|
||||
if (state->tearing_page_flip == true) {
|
||||
if (!wlr_output_test_state(wlr_output, state)) {
|
||||
// 如果 DRM 拒绝(例如当前输出/驱动不支持撕裂),降级关闭撕裂
|
||||
state->tearing_page_flip = false;
|
||||
}
|
||||
}
|
||||
|
||||
// 提交状态
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_INFO, "Failed to commit output %s", m->wlr_output->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return committed;
|
||||
}
|
||||
|
||||
bool mango_output_commit(Monitor *m) {
|
||||
|
||||
bool committed = wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||
if (committed) {
|
||||
wlr_output_state_finish(&m->pending);
|
||||
wlr_output_state_init(&m->pending);
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Failed to commit frame");
|
||||
}
|
||||
return committed;
|
||||
}
|
||||
|
|
@ -4054,8 +4054,6 @@ void reapply_monitor_rules(void) {
|
|||
if (!m->wlr_output->enabled)
|
||||
continue;
|
||||
|
||||
wlr_output_state_init(&m->pending);
|
||||
|
||||
for (ji = 0; ji < config.monitor_rules_count; ji++) {
|
||||
if (config.monitor_rules_count < 1)
|
||||
break;
|
||||
|
|
@ -4078,16 +4076,14 @@ void reapply_monitor_rules(void) {
|
|||
wlr_output_state_set_enabled(&m->pending, true);
|
||||
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, false);
|
||||
bool success = wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||
if (!success) { // 多尝试一次
|
||||
output_state_setup_hdr(m, true);
|
||||
}
|
||||
} else {
|
||||
wlr_output_commit_state(m->wlr_output, &m->pending);
|
||||
output_state_setup_hdr(m, false, &m->pending);
|
||||
}
|
||||
|
||||
wlr_output_state_finish(&m->pending);
|
||||
if (!(mango_scene_output_commit(m->scene_output, &m->pending))) {
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, true, &m->pending);
|
||||
}
|
||||
}
|
||||
wlr_output_effective_resolution(m->wlr_output, &m->m.width,
|
||||
&m->m.height);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1944,11 +1944,11 @@ int32_t togglejump(const Arg *arg) {
|
|||
|
||||
int32_t disable_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_state state = {0};
|
||||
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&state, false);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
wlr_output_state_set_enabled(&m->pending, false);
|
||||
mango_output_commit(m);
|
||||
m->asleep = 1;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
|
|
@ -1959,11 +1959,10 @@ int32_t disable_monitor(const Arg *arg) {
|
|||
|
||||
int32_t enable_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_state state = {0};
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&state, true);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
wlr_output_state_set_enabled(&m->pending, true);
|
||||
mango_output_commit(m);
|
||||
m->asleep = 0;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
|
|
@ -1974,11 +1973,10 @@ int32_t enable_monitor(const Arg *arg) {
|
|||
|
||||
int32_t toggle_monitor(const Arg *arg) {
|
||||
Monitor *m = NULL;
|
||||
struct wlr_output_state state = {0};
|
||||
wl_list_for_each(m, &mons, link) {
|
||||
if (match_monitor_spec(arg->v, m)) {
|
||||
wlr_output_state_set_enabled(&state, !m->wlr_output->enabled);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
wlr_output_state_set_enabled(&m->pending, !m->wlr_output->enabled);
|
||||
mango_output_commit(m);
|
||||
m->asleep = !m->wlr_output->enabled;
|
||||
updatemons(NULL, NULL);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
52
src/mango.c
52
src/mango.c
|
|
@ -953,9 +953,14 @@ static void global_draw_group_bar(Client *c, int32_t x, int32_t y,
|
|||
static void client_reparent_group(Client *c);
|
||||
static void client_change_mon(Client *c, Monitor *m);
|
||||
static void check_vrr_enable(Client *c);
|
||||
static void output_state_setup_hdr(Monitor *m, bool silent);
|
||||
static void output_state_setup_hdr(Monitor *m, bool silent,
|
||||
struct wlr_output_state *state);
|
||||
static void output_enable_hdr(Monitor *m, struct wlr_output_state *os,
|
||||
bool enabled, bool silent);
|
||||
static bool mango_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||
struct wlr_output_state *state);
|
||||
static bool mango_output_commit(Monitor *m);
|
||||
static bool check_tearing_frame_allow(Monitor *m);
|
||||
|
||||
#include "data/static_keymap.h"
|
||||
#include "dispatch/bind_declare.h"
|
||||
|
|
@ -1165,6 +1170,7 @@ static struct wl_event_source *sync_keymap;
|
|||
#endif
|
||||
|
||||
#include "action/client.h"
|
||||
#include "action/monitor.h"
|
||||
#include "animation/client.h"
|
||||
#include "animation/common.h"
|
||||
#include "animation/layer.h"
|
||||
|
|
@ -3520,14 +3526,9 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
wlr_output_state_set_enabled(&m->pending, 1);
|
||||
|
||||
if (m->hdr_enable) {
|
||||
output_state_setup_hdr(m, false);
|
||||
output_state_setup_hdr(m, false, &m->pending);
|
||||
}
|
||||
|
||||
wlr_output_commit_state(wlr_output, &m->pending);
|
||||
wlr_output_state_finish(&m->pending);
|
||||
|
||||
wlr_output_effective_resolution(m->wlr_output, &m->m.width, &m->m.height);
|
||||
|
||||
wl_list_insert(&mons, &m->link);
|
||||
|
||||
m->pertag = calloc(1, sizeof(Pertag));
|
||||
|
|
@ -3575,6 +3576,9 @@ void createmon(struct wl_listener *listener, void *data) {
|
|||
else
|
||||
wlr_output_layout_add(output_layout, wlr_output, m->m.x, m->m.y);
|
||||
|
||||
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) {
|
||||
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);
|
||||
|
|
@ -4142,6 +4146,7 @@ void requestmonstate(struct wl_listener *listener, void *data) {
|
|||
const struct wlr_output_event_request_state *event = data;
|
||||
|
||||
if (event->state->committed == WLR_OUTPUT_STATE_MODE) {
|
||||
|
||||
switch (event->state->mode_type) {
|
||||
case WLR_OUTPUT_STATE_MODE_FIXED:
|
||||
wlr_output_state_set_mode(&m->pending, event->state->mode);
|
||||
|
|
@ -5298,15 +5303,13 @@ void handle_iamge_copy_capture_new_session(struct wl_listener *listener,
|
|||
|
||||
void powermgrsetmode(struct wl_listener *listener, void *data) {
|
||||
struct wlr_output_power_v1_set_mode_event *event = data;
|
||||
struct wlr_output_state state = {0};
|
||||
Monitor *m = event->output->data;
|
||||
|
||||
if (!m)
|
||||
return;
|
||||
|
||||
wlr_output_state_set_enabled(&state, event->mode);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
|
||||
wlr_output_state_set_enabled(&m->pending, event->mode);
|
||||
mango_output_commit(m);
|
||||
m->asleep = !event->mode;
|
||||
updatemons(NULL, NULL);
|
||||
}
|
||||
|
|
@ -5363,7 +5366,6 @@ void rendermon(struct wl_listener *listener, void *data) {
|
|||
LayerSurface *l = NULL, *tmpl = NULL;
|
||||
int32_t i;
|
||||
struct wl_list *layer_list;
|
||||
bool frame_allow_tearing = false;
|
||||
struct timespec now;
|
||||
bool need_more_frames = false;
|
||||
|
||||
|
|
@ -5374,8 +5376,6 @@ void rendermon(struct wl_listener *listener, void *data) {
|
|||
if (!m->wlr_output->enabled || !allow_frame_scheduling)
|
||||
return;
|
||||
|
||||
frame_allow_tearing = check_tearing_frame_allow(m);
|
||||
|
||||
// 绘制层和淡出效果
|
||||
for (i = 0; i < LENGTH(m->layers); i++) {
|
||||
layer_list = &m->layers[i];
|
||||
|
|
@ -5406,12 +5406,7 @@ void rendermon(struct wl_listener *listener, void *data) {
|
|||
monitor_stop_skip_frame_timer(m);
|
||||
}
|
||||
|
||||
// 只有在需要帧时才构建和提交状态
|
||||
if (config.allow_tearing && frame_allow_tearing) {
|
||||
apply_tear_state(m);
|
||||
} else {
|
||||
wlr_scene_output_commit(m->scene_output, NULL);
|
||||
}
|
||||
mango_scene_output_commit(m->scene_output, &m->pending);
|
||||
|
||||
skip:
|
||||
// 发送帧完成通知
|
||||
|
|
@ -6669,7 +6664,6 @@ void check_keep_idle_inhibit(Client *c) {
|
|||
|
||||
void check_vrr_enable(Client *c) {
|
||||
|
||||
struct wlr_output_state state = {0};
|
||||
Monitor *m = c && c->mon ? c->mon : selmon;
|
||||
|
||||
if (!m)
|
||||
|
|
@ -6677,8 +6671,8 @@ void check_vrr_enable(Client *c) {
|
|||
|
||||
if (!c && m && !m->iscleanuping && m->is_vrr_opening &&
|
||||
!m->vrr_global_enable) {
|
||||
disable_adaptive_sync(m, &state);
|
||||
wlr_output_commit_state(m->wlr_output, &state);
|
||||
disable_adaptive_sync(m, &m->pending);
|
||||
mango_output_commit(m);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -6687,17 +6681,17 @@ void check_vrr_enable(Client *c) {
|
|||
|
||||
if (VISIBLEON(c, c->mon) && c->vrr_only_fullscreen && c->isfullscreen &&
|
||||
!c->mon->is_vrr_opening) {
|
||||
enable_adaptive_sync(c->mon, &state);
|
||||
wlr_output_commit_state(c->mon->wlr_output, &state);
|
||||
enable_adaptive_sync(c->mon, &m->pending);
|
||||
mango_output_commit(m);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!c->mon->is_vrr_opening && c->mon->vrr_global_enable) {
|
||||
enable_adaptive_sync(c->mon, &state);
|
||||
wlr_output_commit_state(c->mon->wlr_output, &state);
|
||||
enable_adaptive_sync(c->mon, &m->pending);
|
||||
mango_output_commit(m);
|
||||
} else if (c->mon->is_vrr_opening && !c->mon->vrr_global_enable) {
|
||||
disable_adaptive_sync(c->mon, &state);
|
||||
wlr_output_commit_state(c->mon->wlr_output, &state);
|
||||
disable_adaptive_sync(c->mon, &m->pending);
|
||||
mango_output_commit(m);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue