mirror of
https://github.com/DreamMaoMao/maomaowm.git
synced 2026-06-29 13:14:48 -04:00
feat: hdr support
This commit is contained in:
parent
085d65c219
commit
5fb6b230a0
8 changed files with 211 additions and 63 deletions
|
|
@ -12,6 +12,7 @@ description: Advanced settings for XWayland, focus behavior, and system integrat
|
||||||
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
| `allow_lock_transparent` | `0` | Allow the lock screen to be transparent. |
|
||||||
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
| `allow_shortcuts_inhibit` | `1` | Allow shortcuts to be inhibited by clients. |
|
||||||
| `vrr` | - | Set via [monitor rule](/docs/configuration/monitors#monitor-rules). |
|
| `vrr` | - | Set via [monitor rule](/docs/configuration/monitors#monitor-rules). |
|
||||||
|
| `hdr_hdr_depth` | `0`/`1`/`2` | Set the hdr depth for the current display. `0` is Default, `1` is HDR8, `2` is HDR10. |
|
||||||
|
|
||||||
## Focus & Input
|
## Focus & Input
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ monitorrule=name:Values,Parameter:Values,Parameter:Values
|
||||||
| `y` | integer | 0-99999 | Y position |
|
| `y` | integer | 0-99999 | Y position |
|
||||||
| `scale` | float | 0.01-100.0 | Monitor scale |
|
| `scale` | float | 0.01-100.0 | Monitor scale |
|
||||||
| `vrr` | integer | 0, 1 | Enable variable refresh rate |
|
| `vrr` | integer | 0, 1 | Enable variable refresh rate |
|
||||||
|
| `hdr` | integer | 0, 1 | Enable hdr support |
|
||||||
| `rr` | integer | 0-7 | Monitor transform |
|
| `rr` | integer | 0-7 | Monitor transform |
|
||||||
| `custom` | integer | 0, 1 | Enable custom mode (not supported on all displays — may cause black screen) |
|
| `custom` | integer | 0, 1 | Enable custom mode (not supported on all displays — may cause black screen) |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -265,4 +265,9 @@ void client_set_group_mon(Client *c, Monitor *m) {
|
||||||
client_change_mon(cur, m);
|
client_change_mon(cur, m);
|
||||||
cur = cur->group_next;
|
cur = cur->group_next;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_client_focus_change(Client *c) {
|
||||||
|
check_keep_idle_inhibit(c);
|
||||||
|
check_vrr_enable(c);
|
||||||
}
|
}
|
||||||
|
|
@ -22,6 +22,11 @@ enum { NUM_TYPE_MINUS, NUM_TYPE_PLUS, NUM_TYPE_DEFAULT };
|
||||||
|
|
||||||
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
|
enum { KEY_TYPE_CODE, KEY_TYPE_SYM };
|
||||||
|
|
||||||
|
enum render_bit_depth {
|
||||||
|
MANGO_RENDER_BIT_DEPTH_DEFAULT = 0,
|
||||||
|
MANGO_RENDER_BIT_DEPTH_8,
|
||||||
|
MANGO_RENDER_BIT_DEPTH_10,
|
||||||
|
};
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t keycode1;
|
uint32_t keycode1;
|
||||||
uint32_t keycode2;
|
uint32_t keycode2;
|
||||||
|
|
@ -112,6 +117,7 @@ typedef struct {
|
||||||
float refresh; // Refresh rate
|
float refresh; // Refresh rate
|
||||||
int32_t vrr; // variable refresh rate
|
int32_t vrr; // variable refresh rate
|
||||||
int32_t custom; // enable custom mode
|
int32_t custom; // enable custom mode
|
||||||
|
int32_t hdr; // enable hdr mode
|
||||||
} ConfigMonitorRule;
|
} ConfigMonitorRule;
|
||||||
|
|
||||||
// 修改后的宏定义
|
// 修改后的宏定义
|
||||||
|
|
@ -391,6 +397,8 @@ typedef struct {
|
||||||
struct xkb_keymap *keymap;
|
struct xkb_keymap *keymap;
|
||||||
DecorateDrawData jumplabeldata;
|
DecorateDrawData jumplabeldata;
|
||||||
DecorateDrawData tabdata;
|
DecorateDrawData tabdata;
|
||||||
|
|
||||||
|
int32_t hdr_depth;
|
||||||
} Config;
|
} Config;
|
||||||
|
|
||||||
typedef int32_t (*FuncType)(const Arg *);
|
typedef int32_t (*FuncType)(const Arg *);
|
||||||
|
|
@ -1464,6 +1472,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
config->drag_floating_refresh_interval = atof(value);
|
config->drag_floating_refresh_interval = atof(value);
|
||||||
} else if (strcmp(key, "allow_tearing") == 0) {
|
} else if (strcmp(key, "allow_tearing") == 0) {
|
||||||
config->allow_tearing = atoi(value);
|
config->allow_tearing = atoi(value);
|
||||||
|
} else if (strcmp(key, "hdr_depth") == 0) {
|
||||||
|
config->hdr_depth = atoi(value);
|
||||||
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
} else if (strcmp(key, "allow_shortcuts_inhibit") == 0) {
|
||||||
config->allow_shortcuts_inhibit = atoi(value);
|
config->allow_shortcuts_inhibit = atoi(value);
|
||||||
} else if (strcmp(key, "allow_lock_transparent") == 0) {
|
} else if (strcmp(key, "allow_lock_transparent") == 0) {
|
||||||
|
|
@ -2047,6 +2057,7 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->height = -1;
|
rule->height = -1;
|
||||||
rule->refresh = 0.0f;
|
rule->refresh = 0.0f;
|
||||||
rule->vrr = 0;
|
rule->vrr = 0;
|
||||||
|
rule->hdr = 0;
|
||||||
rule->custom = 0;
|
rule->custom = 0;
|
||||||
|
|
||||||
bool parse_error = false;
|
bool parse_error = false;
|
||||||
|
|
@ -2085,6 +2096,8 @@ bool parse_option(Config *config, char *key, char *value) {
|
||||||
rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f);
|
rule->refresh = CLAMP_FLOAT(atof(val), 0.001f, 1000.0f);
|
||||||
} else if (strcmp(key, "vrr") == 0) {
|
} else if (strcmp(key, "vrr") == 0) {
|
||||||
rule->vrr = CLAMP_INT(atoi(val), 0, 1);
|
rule->vrr = CLAMP_INT(atoi(val), 0, 1);
|
||||||
|
} else if (strcmp(key, "hdr") == 0) {
|
||||||
|
rule->hdr = CLAMP_INT(atoi(val), 0, 1);
|
||||||
} else if (strcmp(key, "custom") == 0) {
|
} else if (strcmp(key, "custom") == 0) {
|
||||||
rule->custom = CLAMP_INT(atoi(val), 0, 1);
|
rule->custom = CLAMP_INT(atoi(val), 0, 1);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -3421,6 +3434,7 @@ void override_config(void) {
|
||||||
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
config.drag_tile_to_tile = CLAMP_INT(config.drag_tile_to_tile, 0, 1);
|
||||||
config.drag_tile_small = CLAMP_INT(config.drag_tile_small, 0, 1);
|
config.drag_tile_small = CLAMP_INT(config.drag_tile_small, 0, 1);
|
||||||
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
config.allow_tearing = CLAMP_INT(config.allow_tearing, 0, 2);
|
||||||
|
config.hdr_depth = CLAMP_INT(config.hdr_depth, 0, 2);
|
||||||
config.allow_shortcuts_inhibit =
|
config.allow_shortcuts_inhibit =
|
||||||
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
CLAMP_INT(config.allow_shortcuts_inhibit, 0, 1);
|
||||||
config.allow_lock_transparent =
|
config.allow_lock_transparent =
|
||||||
|
|
@ -3588,6 +3602,7 @@ void set_value_default() {
|
||||||
config.drag_tile_refresh_interval = 8.0f;
|
config.drag_tile_refresh_interval = 8.0f;
|
||||||
config.drag_floating_refresh_interval = 8.0f;
|
config.drag_floating_refresh_interval = 8.0f;
|
||||||
config.allow_tearing = TEARING_DISABLED;
|
config.allow_tearing = TEARING_DISABLED;
|
||||||
|
config.hdr_depth = MANGO_RENDER_BIT_DEPTH_DEFAULT;
|
||||||
config.allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
config.allow_shortcuts_inhibit = SHORTCUTS_INHIBIT_ENABLE;
|
||||||
config.allow_lock_transparent = 0;
|
config.allow_lock_transparent = 0;
|
||||||
config.no_border_when_single = 0;
|
config.no_border_when_single = 0;
|
||||||
|
|
@ -3868,13 +3883,12 @@ void reapply_monitor_rules(void) {
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
int32_t ji, vrr, custom;
|
int32_t ji, vrr, custom;
|
||||||
int32_t mx, my;
|
int32_t mx, my;
|
||||||
struct wlr_output_state state;
|
|
||||||
|
|
||||||
wl_list_for_each(m, &mons, link) {
|
wl_list_for_each(m, &mons, link) {
|
||||||
if (!m->wlr_output->enabled)
|
if (!m->wlr_output->enabled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
wlr_output_state_init(&state);
|
wlr_output_state_init(&m->pending);
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -3887,16 +3901,31 @@ void reapply_monitor_rules(void) {
|
||||||
my = mr->y == INT32_MAX ? m->m.y : mr->y;
|
my = mr->y == INT32_MAX ? m->m.y : mr->y;
|
||||||
vrr = mr->vrr >= 0 ? mr->vrr : 0;
|
vrr = mr->vrr >= 0 ? mr->vrr : 0;
|
||||||
custom = mr->custom >= 0 ? mr->custom : 0;
|
custom = mr->custom >= 0 ? mr->custom : 0;
|
||||||
|
m->hdr_enable = mr->hdr >= 0 ? mr->hdr : 0;
|
||||||
|
|
||||||
(void)apply_rule_to_state(m, mr, &state, vrr, custom);
|
(void)apply_rule_to_state(m, mr, &m->pending, vrr, custom);
|
||||||
wlr_output_layout_add(output_layout, m->wlr_output, mx, my);
|
wlr_output_layout_add(output_layout, m->wlr_output, mx, my);
|
||||||
wlr_output_commit_state(m->wlr_output, &state);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_output_state_finish(&state);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
wlr_output_state_finish(&m->pending);
|
||||||
|
wlr_output_effective_resolution(m->wlr_output, &m->m.width,
|
||||||
|
&m->m.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
updatemons(NULL, NULL);
|
updatemons(NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
#include "dwl-ipc.h"
|
#include "dwl-ipc.h"
|
||||||
#include "ext-workspace.h"
|
#include "ext-workspace.h"
|
||||||
#include "foreign-toplevel.h"
|
#include "foreign-toplevel.h"
|
||||||
|
#include "hdr.h"
|
||||||
#include "tablet.h"
|
#include "tablet.h"
|
||||||
#include "tearing.h"
|
#include "tearing.h"
|
||||||
#include "text-input.h"
|
#include "text-input.h"
|
||||||
|
|
|
||||||
128
src/ext-protocol/hdr.h
Normal file
128
src/ext-protocol/hdr.h
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
#include <drm_fourcc.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
|
static uint32_t output_formats_8bit[] = {
|
||||||
|
DRM_FORMAT_XRGB8888, DRM_FORMAT_XBGR8888, DRM_FORMAT_RGBX8888,
|
||||||
|
DRM_FORMAT_BGRX8888, DRM_FORMAT_ARGB8888, DRM_FORMAT_ABGR8888,
|
||||||
|
DRM_FORMAT_RGBA8888, DRM_FORMAT_BGRA8888, DRM_FORMAT_RGB888,
|
||||||
|
DRM_FORMAT_BGR888,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t output_formats_10bit[] = {
|
||||||
|
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(Monitor *m, uint32_t candidates[],
|
||||||
|
size_t count) {
|
||||||
|
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))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_format_in_candidates(uint32_t format, uint32_t candidates[],
|
||||||
|
size_t count) {
|
||||||
|
for (size_t i = 0; i < count; i++)
|
||||||
|
if (candidates[i] == 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 MANGO_RENDER_BIT_DEPTH_10;
|
||||||
|
if (output_format_in_candidates(render_format, output_formats_8bit,
|
||||||
|
ARRAY_SIZE(output_formats_8bit)))
|
||||||
|
return MANGO_RENDER_BIT_DEPTH_8;
|
||||||
|
return MANGO_RENDER_BIT_DEPTH_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool output_supports_hdr(const struct wlr_output *output,
|
||||||
|
const char **reason) {
|
||||||
|
const char *r = NULL;
|
||||||
|
if (!(output->supported_primaries & WLR_COLOR_NAMED_PRIMARIES_BT2020))
|
||||||
|
r = "BT2020 primaries not supported";
|
||||||
|
else if (!(output->supported_transfer_functions &
|
||||||
|
WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ))
|
||||||
|
r = "PQ transfer function not supported";
|
||||||
|
else if (!drw->features.output_color_transform)
|
||||||
|
r = "renderer doesn't support output color transforms";
|
||||||
|
if (reason)
|
||||||
|
*reason = r;
|
||||||
|
return !r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_enable_hdr(Monitor *m, struct wlr_output_state *os, bool enabled,
|
||||||
|
bool silent) {
|
||||||
|
if (enabled && !output_supports_hdr(m->wlr_output, NULL))
|
||||||
|
enabled = false;
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
if (m->wlr_output->supported_primaries ||
|
||||||
|
m->wlr_output->supported_transfer_functions) {
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_DEBUG, "Disabling HDR on output %s",
|
||||||
|
m->wlr_output->name);
|
||||||
|
wlr_output_state_set_image_description(os, NULL);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_DEBUG, "Enabling HDR on output %s", m->wlr_output->name);
|
||||||
|
struct wlr_output_image_description desc = {
|
||||||
|
.primaries = WLR_COLOR_NAMED_PRIMARIES_BT2020,
|
||||||
|
.transfer_function = WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ,
|
||||||
|
};
|
||||||
|
wlr_output_state_set_image_description(os, &desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void output_state_setup_hdr(Monitor *m, bool silent) {
|
||||||
|
uint32_t render_format = m->wlr_output->render_format;
|
||||||
|
const char *unsupported_reason = NULL;
|
||||||
|
bool hdr_supported =
|
||||||
|
output_supports_hdr(m->wlr_output, &unsupported_reason);
|
||||||
|
bool hdr_succeeded = false;
|
||||||
|
|
||||||
|
enum render_bit_depth depth = config.hdr_depth;
|
||||||
|
if (depth == MANGO_RENDER_BIT_DEPTH_DEFAULT)
|
||||||
|
depth = bit_depth_from_format(render_format);
|
||||||
|
|
||||||
|
if (!hdr_supported && depth == MANGO_RENDER_BIT_DEPTH_10) {
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_INFO, "Cannot enable HDR on output %s: %s",
|
||||||
|
m->wlr_output->name, unsupported_reason);
|
||||||
|
depth = MANGO_RENDER_BIT_DEPTH_8;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depth == MANGO_RENDER_BIT_DEPTH_10 &&
|
||||||
|
bit_depth_from_format(render_format) == depth) {
|
||||||
|
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));
|
||||||
|
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)))
|
||||||
|
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)))
|
||||||
|
if (!silent)
|
||||||
|
wlr_log(WLR_ERROR, "No 8 bit color formats supported!");
|
||||||
|
}
|
||||||
|
|
||||||
|
output_enable_hdr(m, &m->pending, hdr_succeeded, silent);
|
||||||
|
}
|
||||||
|
|
@ -100,73 +100,44 @@ bool custom_wlr_scene_output_commit(struct wlr_scene_output *scene_output,
|
||||||
struct wlr_output *wlr_output = scene_output->output;
|
struct wlr_output *wlr_output = scene_output->output;
|
||||||
Monitor *m = wlr_output->data;
|
Monitor *m = wlr_output->data;
|
||||||
|
|
||||||
// 检查是否需要帧
|
if (!wlr_scene_output_needs_frame(scene_output))
|
||||||
if (!wlr_scene_output_needs_frame(scene_output)) {
|
|
||||||
wlr_log(WLR_DEBUG, "No frame needed for output %s", wlr_output->name);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
// 构建输出状态
|
// 构建状态,将场景的 Buffer 附着到 state 上
|
||||||
if (!wlr_scene_output_build_state(scene_output, state, NULL)) {
|
if (!wlr_scene_output_build_state(scene_output, state, NULL))
|
||||||
wlr_log(WLR_ERROR, "Failed to build output state for %s",
|
|
||||||
wlr_output->name);
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// 测试是否支持撕裂
|
||||||
|
if (!wlr_output_test_state(wlr_output, state)) {
|
||||||
|
// 如果 DRM 拒绝(例如当前输出/驱动不支持撕裂),降级关闭撕裂
|
||||||
|
state->tearing_page_flip = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试撕裂翻页
|
// 提交状态
|
||||||
if (state->tearing_page_flip) {
|
|
||||||
if (!wlr_output_test_state(wlr_output, state)) {
|
|
||||||
state->tearing_page_flip = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 尝试提交
|
|
||||||
bool committed = wlr_output_commit_state(wlr_output, state);
|
bool committed = wlr_output_commit_state(wlr_output, state);
|
||||||
|
|
||||||
// 如果启用撕裂翻页但提交失败,重试禁用撕裂翻页
|
|
||||||
if (!committed && state->tearing_page_flip) {
|
if (!committed && state->tearing_page_flip) {
|
||||||
wlr_log(WLR_DEBUG, "Retrying commit without tearing for %s",
|
// 重试一次
|
||||||
wlr_output->name);
|
|
||||||
state->tearing_page_flip = false;
|
state->tearing_page_flip = false;
|
||||||
committed = wlr_output_commit_state(wlr_output, state);
|
committed = wlr_output_commit_state(wlr_output, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理状态清理
|
|
||||||
if (committed) {
|
if (committed) {
|
||||||
wlr_log(WLR_DEBUG, "Successfully committed output %s",
|
|
||||||
wlr_output->name);
|
|
||||||
if (state == &m->pending) {
|
if (state == &m->pending) {
|
||||||
wlr_output_state_finish(&m->pending);
|
wlr_output_state_finish(&m->pending);
|
||||||
wlr_output_state_init(&m->pending);
|
wlr_output_state_init(&m->pending);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
wlr_log(WLR_ERROR, "Failed to commit output %s", wlr_output->name);
|
|
||||||
// 即使提交失败,也清理状态避免积累
|
|
||||||
if (state == &m->pending) {
|
|
||||||
wlr_output_state_finish(&m->pending);
|
|
||||||
wlr_output_state_init(&m->pending);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return committed;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void apply_tear_state(Monitor *m) {
|
void apply_tear_state(Monitor *m) {
|
||||||
if (wlr_scene_output_needs_frame(m->scene_output)) {
|
if (!wlr_scene_output_needs_frame(m->scene_output))
|
||||||
wlr_output_state_init(&m->pending);
|
return;
|
||||||
if (wlr_scene_output_build_state(m->scene_output, &m->pending, NULL)) {
|
|
||||||
struct wlr_output_state *pending = &m->pending;
|
|
||||||
pending->tearing_page_flip = true;
|
|
||||||
|
|
||||||
if (!custom_wlr_scene_output_commit(m->scene_output, pending)) {
|
wlr_output_state_init(&m->pending);
|
||||||
wlr_log(WLR_ERROR, "Failed to commit output %s",
|
m->pending.tearing_page_flip = true;
|
||||||
m->scene_output->output->name);
|
if (!custom_wlr_scene_output_commit(m->scene_output, &m->pending)) {
|
||||||
}
|
wlr_log(WLR_ERROR, "Failed to commit output %s",
|
||||||
} else {
|
m->scene_output->output->name);
|
||||||
wlr_log(WLR_ERROR, "Failed to build state for output %s",
|
|
||||||
m->scene_output->output->name);
|
|
||||||
wlr_output_state_finish(&m->pending);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
34
src/mango.c
34
src/mango.c
|
|
@ -586,6 +586,7 @@ struct Monitor {
|
||||||
int8_t carousel_anim_dir;
|
int8_t carousel_anim_dir;
|
||||||
bool vrr_global_enable;
|
bool vrr_global_enable;
|
||||||
bool is_vrr_opening;
|
bool is_vrr_opening;
|
||||||
|
bool hdr_enable;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
@ -947,6 +948,9 @@ static void global_draw_group_bar(Client *c, int32_t x, int32_t y,
|
||||||
static void client_reparent_group(Client *c);
|
static void client_reparent_group(Client *c);
|
||||||
static void client_change_mon(Client *c, Monitor *m);
|
static void client_change_mon(Client *c, Monitor *m);
|
||||||
static void check_vrr_enable(Client *c);
|
static void check_vrr_enable(Client *c);
|
||||||
|
static void output_state_setup_hdr(Monitor *m, bool silent);
|
||||||
|
static void output_enable_hdr(Monitor *m, struct wlr_output_state *os,
|
||||||
|
bool enabled, bool silent);
|
||||||
|
|
||||||
#include "data/static_keymap.h"
|
#include "data/static_keymap.h"
|
||||||
#include "dispatch/bind_declare.h"
|
#include "dispatch/bind_declare.h"
|
||||||
|
|
@ -3346,7 +3350,6 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
const ConfigMonitorRule *r;
|
const ConfigMonitorRule *r;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
int32_t ji, vrr, custom;
|
int32_t ji, vrr, custom;
|
||||||
struct wlr_output_state state;
|
|
||||||
Monitor *m = NULL;
|
Monitor *m = NULL;
|
||||||
bool custom_monitor_mode = false;
|
bool custom_monitor_mode = false;
|
||||||
|
|
||||||
|
|
@ -3374,6 +3377,8 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
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->wlr_output = wlr_output;
|
m->wlr_output = wlr_output;
|
||||||
m->wlr_output->data = m;
|
m->wlr_output->data = m;
|
||||||
|
|
||||||
|
|
@ -3394,9 +3399,9 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
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_init(&state);
|
wlr_output_state_init(&m->pending);
|
||||||
wlr_output_state_set_scale(&state, scale);
|
wlr_output_state_set_scale(&m->pending, scale);
|
||||||
wlr_output_state_set_transform(&state, rr);
|
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)
|
||||||
|
|
@ -3411,8 +3416,9 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
custom = r->custom >= 0 ? r->custom : 0;
|
custom = r->custom >= 0 ? r->custom : 0;
|
||||||
scale = r->scale;
|
scale = r->scale;
|
||||||
rr = r->rr;
|
rr = r->rr;
|
||||||
|
m->hdr_enable = r->hdr;
|
||||||
|
|
||||||
if (apply_rule_to_state(m, r, &state, vrr, custom)) {
|
if (apply_rule_to_state(m, r, &m->pending, vrr, custom)) {
|
||||||
custom_monitor_mode = true;
|
custom_monitor_mode = true;
|
||||||
}
|
}
|
||||||
break; // 只应用第一个匹配规则
|
break; // 只应用第一个匹配规则
|
||||||
|
|
@ -3420,7 +3426,7 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!custom_monitor_mode)
|
if (!custom_monitor_mode)
|
||||||
wlr_output_state_set_mode(&state,
|
wlr_output_state_set_mode(&m->pending,
|
||||||
wlr_output_preferred_mode(wlr_output));
|
wlr_output_preferred_mode(wlr_output));
|
||||||
|
|
||||||
/* Set up event listeners */
|
/* Set up event listeners */
|
||||||
|
|
@ -3429,9 +3435,16 @@ void createmon(struct wl_listener *listener, void *data) {
|
||||||
LISTEN(&wlr_output->events.request_state, &m->request_state,
|
LISTEN(&wlr_output->events.request_state, &m->request_state,
|
||||||
requestmonstate);
|
requestmonstate);
|
||||||
|
|
||||||
wlr_output_state_set_enabled(&state, 1);
|
wlr_output_state_set_enabled(&m->pending, 1);
|
||||||
wlr_output_commit_state(wlr_output, &state);
|
|
||||||
wlr_output_state_finish(&state);
|
if (m->hdr_enable) {
|
||||||
|
output_state_setup_hdr(m, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
wl_list_insert(&mons, &m->link);
|
||||||
|
|
||||||
|
|
@ -3908,8 +3921,7 @@ void focusclient(Client *c, int32_t lift) {
|
||||||
selmon->sel = c;
|
selmon->sel = c;
|
||||||
c->isfocusing = true;
|
c->isfocusing = true;
|
||||||
|
|
||||||
check_keep_idle_inhibit(c);
|
handle_client_focus_change(c);
|
||||||
check_vrr_enable(c);
|
|
||||||
|
|
||||||
if (last_focus_client && !last_focus_client->iskilling &&
|
if (last_focus_client && !last_focus_client->iskilling &&
|
||||||
last_focus_client != c) {
|
last_focus_client != c) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue