Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#128 allow exact refresh to milliHz #131

Merged
merged 6 commits into from
Sep 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion inc/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ struct UserMode {
bool max;
int32_t width;
int32_t height;
int32_t refresh_hz;
int32_t refresh_mhz;
bool warned_no_mode;
};

Expand Down
15 changes: 12 additions & 3 deletions inc/mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
#include <stdint.h>

#include "cfg.h"
#include "global.h"
#include "slist.h"
#include "wlr-output-management-unstable-v1.h"

struct Mode {
struct Head *head;
Expand All @@ -21,23 +23,30 @@ struct Mode {
struct ModesResRefresh {
int32_t width;
int32_t height;
int32_t refresh_hz;
int32_t refresh_mhz;
struct SList *modes;
};

struct Mode *mode_preferred(struct SList *modes, struct SList *modes_failed);

struct Mode *mode_max_preferred(struct SList *modes, struct SList *modes_failed);

int32_t mhz_to_hz(int32_t mhz);
// up to 3 d.p.
const char *mhz_to_hz_str(int32_t mhz);

// hz float string to milliHz, 0 on failure
int32_t hz_str_to_mhz(const char *hz_str);

// rounded integer
int32_t mhz_to_hz_rounded(int32_t mhz);

double mode_dpi(struct Mode *mode);

double mode_scale(struct Mode *mode);

struct SList *modes_res_refresh(struct SList *modes);

bool mrr_satisfies_user_mode(struct ModesResRefresh *mrr, struct UserMode *user_mode);
struct Mode *mode_init(struct Head *head, struct zwlr_output_mode_v1 *zwlr_mode, int32_t width, int32_t height, int32_t refresh_mhz, bool preferred);

void mode_free(void *mode);

Expand Down
15 changes: 8 additions & 7 deletions src/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "convert.h"
#include "global.h"
#include "info.h"
#include "mode.h"
#include "slist.h"
#include "log.h"
#include "marshalling.h"
Expand Down Expand Up @@ -88,7 +89,7 @@ bool cfg_equal_user_mode(const void *value, const void *data) {
return false;
}

if ((lhs->refresh_hz != -1 || rhs->refresh_hz != -1) && lhs->refresh_hz != rhs->refresh_hz) {
if ((lhs->refresh_mhz != -1 || rhs->refresh_mhz != -1) && lhs->refresh_mhz != rhs->refresh_mhz) {
return false;
}

Expand Down Expand Up @@ -162,8 +163,8 @@ bool invalid_user_mode(const void *value, const void *data) {
log_warn("\nIgnoring non-positive MODE %s HEIGHT %d", user_mode->name_desc, user_mode->height);
return true;
}
if (user_mode->refresh_hz != -1 && user_mode->refresh_hz <= 0) {
log_warn("\nIgnoring non-positive MODE %s HZ %d", user_mode->name_desc, user_mode->refresh_hz);
if (user_mode->refresh_mhz != -1 && user_mode->refresh_mhz <= 0) {
log_warn("\nIgnoring non-positive MODE %s HZ %s", user_mode->name_desc, mhz_to_hz_str(user_mode->refresh_mhz));
return true;
}

Expand Down Expand Up @@ -253,7 +254,7 @@ struct Cfg *clone_cfg(struct Cfg *from) {
to_user_mode->max = from_user_mode->max;
to_user_mode->width = from_user_mode->width;
to_user_mode->height = from_user_mode->height;
to_user_mode->refresh_hz = from_user_mode->refresh_hz;
to_user_mode->refresh_mhz = from_user_mode->refresh_mhz;
to_user_mode->warned_no_mode = from_user_mode->warned_no_mode;
slist_append(&to->user_modes, to_user_mode);
}
Expand Down Expand Up @@ -382,7 +383,7 @@ struct UserMode *cfg_user_mode_default(void) {
return cfg_user_mode_init(NULL, false, -1, -1, -1, false);
}

struct UserMode *cfg_user_mode_init(const char *name_desc, const bool max, const int32_t width, const int32_t height, const int32_t refresh_hz, const bool warned_no_mode) {
struct UserMode *cfg_user_mode_init(const char *name_desc, const bool max, const int32_t width, const int32_t height, const int32_t refresh_mhz, const bool warned_no_mode) {
struct UserMode *um = (struct UserMode*)calloc(1, sizeof(struct UserMode));

if (name_desc) {
Expand All @@ -391,7 +392,7 @@ struct UserMode *cfg_user_mode_init(const char *name_desc, const bool max, const
um->max = max;
um->width = width;
um->height = height;
um->refresh_hz = refresh_hz;
um->refresh_mhz = refresh_mhz;
um->warned_no_mode = warned_no_mode;

return um;
Expand Down Expand Up @@ -599,7 +600,7 @@ struct Cfg *merge_set(struct Cfg *to, struct Cfg *from) {
merged_user_mode->max = set_user_mode->max;
merged_user_mode->width = set_user_mode->width;
merged_user_mode->height = set_user_mode->height;
merged_user_mode->refresh_hz = set_user_mode->refresh_hz;
merged_user_mode->refresh_mhz = set_user_mode->refresh_mhz;
merged_user_mode->warned_no_mode = set_user_mode->warned_no_mode;
}

Expand Down
3 changes: 2 additions & 1 deletion src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "ipc.h"
#include "slist.h"
#include "log.h"
#include "mode.h"
#include "process.h"

#include "cli.h"
Expand Down Expand Up @@ -102,7 +103,7 @@ struct Cfg *parse_element(enum IpcCommand command, enum CfgElement element, int
parsed = parsed && ((user_mode->height = atoi(argv[optind + 2])) > 0);
}
if (optind + 3 < argc) {
parsed = parsed && ((user_mode->refresh_hz = atoi(argv[optind + 3])) > 0);
parsed = parsed && ((user_mode->refresh_mhz = hz_str_to_mhz(argv[optind + 3])) > 0);
}
}
slist_append(&cfg->user_modes, user_mode);
Expand Down
14 changes: 7 additions & 7 deletions src/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ void info_user_mode_string(struct UserMode *user_mode, char *buf, size_t nbuf) {

if (user_mode->max) {
snprintf(buf, nbuf, "MAX");
} else if (user_mode->refresh_hz != -1) {
snprintf(buf, nbuf, "%dx%d@%dHz",
} else if (user_mode->refresh_mhz != -1) {
snprintf(buf, nbuf, "%dx%d@%sHz",
user_mode->width,
user_mode->height,
user_mode->refresh_hz
mhz_to_hz_str(user_mode->refresh_mhz)
);
} else {
snprintf(buf, nbuf, "%dx%d",
Expand All @@ -44,7 +44,7 @@ void info_mode_string(struct Mode *mode, char *buf, size_t nbuf) {
snprintf(buf, nbuf, "%dx%d@%dHz (%d,%03dmHz) %s",
mode->width,
mode->height,
mhz_to_hz(mode->refresh_mhz),
mhz_to_hz_rounded(mode->refresh_mhz),
mode->refresh_mhz / 1000,
mode->refresh_mhz % 1000,
mode->preferred ? "(preferred)" : ""
Expand Down Expand Up @@ -105,7 +105,7 @@ void print_modes_res_refresh(enum LogThreshold t, struct Head *head) {
mrr = i->val;

bp = buf;
bp += snprintf(bp, sizeof(buf) - (bp - buf), " mode: %5d x%5d @%4d Hz ", mrr->width, mrr->height, mrr->refresh_hz);
bp += snprintf(bp, sizeof(buf) - (bp - buf), " mode: %5d x%5d @%4d Hz ", mrr->width, mrr->height, mhz_to_hz_rounded(mrr->refresh_mhz));

for (struct SList *j = mrr->modes; j; j = j->nex) {
mode = j->val;
Expand Down Expand Up @@ -257,8 +257,8 @@ void print_cfg_commands(enum LogThreshold t, struct Cfg *cfg) {

if (user_mode->max) {
snprintf(buf, sizeof(buf), "MAX");
} else if (user_mode->refresh_hz != -1) {
snprintf(buf, sizeof(buf), "%d %d %d", user_mode->width, user_mode->height, user_mode->refresh_hz);
} else if (user_mode->refresh_mhz != -1) {
snprintf(buf, sizeof(buf), "%d %d %s", user_mode->width, user_mode->height, mhz_to_hz_str(user_mode->refresh_mhz));
} else {
snprintf(buf, sizeof(buf), "%d %d", user_mode->width, user_mode->height);
}
Expand Down
32 changes: 19 additions & 13 deletions src/marshalling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -201,15 +201,17 @@ YAML::Emitter& operator << (YAML::Emitter& e, struct Cfg& cfg) {
e << YAML::Key << "MODE" << YAML::BeginSeq; // MODE
for (struct SList *i = cfg.user_modes; i; i = i->nex) {
struct UserMode *user_mode = (struct UserMode*)i->val;
e << YAML::BeginMap; // mode
e << YAML::Key << "NAME_DESC" << YAML::Value << user_mode->name_desc;
if (user_mode->max) {
e << YAML::Key << "MAX" << YAML::Value << true;
} else {
e << YAML::Key << "WIDTH" << YAML::Value << user_mode->width;
e << YAML::Key << "HEIGHT" << YAML::Value << user_mode->height;
if (user_mode->refresh_hz != -1) {
e << YAML::Key << "HZ" << YAML::Value << user_mode->refresh_hz;
if (user_mode) {
e << YAML::BeginMap; // mode
e << YAML::Key << "NAME_DESC" << YAML::Value << user_mode->name_desc;
if (user_mode->max) {
e << YAML::Key << "MAX" << YAML::Value << true;
} else {
e << YAML::Key << "WIDTH" << YAML::Value << user_mode->width;
e << YAML::Key << "HEIGHT" << YAML::Value << user_mode->height;
if (user_mode->refresh_mhz != -1) {
e << YAML::Key << "HZ" << YAML::Value << mhz_to_hz_str(user_mode->refresh_mhz);
}
}
}
e << YAML::EndMap; // mode
Expand Down Expand Up @@ -468,9 +470,13 @@ struct CfgValidated*& operator << (struct CfgValidated*& cfg_validated, const YA
cfg_user_mode_free(user_mode);
continue;
}
if (mode["HZ"] && !parse_node_val_int(mode, "HZ", &user_mode->refresh_hz, "MODE", user_mode->name_desc)) {
cfg_user_mode_free(user_mode);
continue;
if (mode["HZ"]) {
float hz = 0;
if (!parse_node_val_float(mode, "HZ", &hz, "MODE", user_mode->name_desc)) {
cfg_user_mode_free(user_mode);
continue;
}
user_mode->refresh_mhz = hz_str_to_mhz(mode["HZ"].as<std::string>().c_str());
}

slist_remove_all_free(&cfg->user_modes, cfg_equal_user_mode_name, user_mode, cfg_user_mode_free);
Expand Down Expand Up @@ -601,7 +607,7 @@ struct UserMode*& operator << (struct UserMode*& user_mode, const YAML::Node& no
TI(user_mode->name_desc = strdup(node["NAME_DESC"].as<std::string>().c_str()));
TI(user_mode->width = node["WIDTH"].as<int>());
TI(user_mode->height = node["HEIGHT"].as<int>());
TI(user_mode->refresh_hz = node["HZ"].as<int>());
TI(user_mode->refresh_mhz = hz_str_to_mhz(node["HZ"].as<std::string>().c_str()));
TI(user_mode->max = node["MAX"].as<bool>());

return user_mode;
Expand Down
54 changes: 50 additions & 4 deletions src/mode.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#include <math.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

#include "mode.h"

#include "cfg.h"
#include "head.h"
#include "slist.h"
#include "wlr-output-management-unstable-v1.h"

struct Mode *mode_preferred(struct SList *modes, struct SList *modes_failed) {
struct Mode *mode = NULL;
Expand Down Expand Up @@ -55,7 +58,20 @@ struct Mode *mode_max_preferred(struct SList *modes, struct SList *modes_failed)
return max;
}

int32_t mhz_to_hz(int32_t mhz) {
const char *mhz_to_hz_str(int32_t mhz) {
static char buf[64];
snprintf(buf, 64, "%g", ((float)mhz) / 1000);
return buf;
}

int32_t hz_str_to_mhz(const char *hz_str) {
if (!hz_str)
return 0;

return lround(atof(hz_str) * 1000);
}

int32_t mhz_to_hz_rounded(int32_t mhz) {
return (mhz + 500) / 1000;
}

Expand All @@ -69,7 +85,18 @@ bool equal_mode_res_hz(const void *a, const void *b) {

return lhs->width == rhs->width &&
lhs->height == rhs->height &&
mhz_to_hz(lhs->refresh_mhz) == mhz_to_hz(rhs->refresh_mhz);
mhz_to_hz_rounded(lhs->refresh_mhz) == mhz_to_hz_rounded(rhs->refresh_mhz);
}

bool equal_mode_user_mode_res_refresh(const void *a, const void *b) {
if (!a || !b) {
return false;
}

struct Mode *lhs = (struct Mode*)a;
struct UserMode *rhs = (struct UserMode*)b;

return lhs->width == rhs->width && lhs->height == rhs->height && lhs->refresh_mhz == rhs->refresh_mhz;
}

bool greater_than_res_refresh(const void *a, const void *b) {
Expand Down Expand Up @@ -107,7 +134,7 @@ bool mrr_satisfies_user_mode(struct ModesResRefresh *mrr, struct UserMode *user_
return user_mode->max ||
(mrr->width == user_mode->width &&
mrr->height == user_mode->height &&
(user_mode->refresh_hz == -1 || mrr->refresh_hz == user_mode->refresh_hz));
(user_mode->refresh_mhz == -1 || mhz_to_hz_rounded(mrr->refresh_mhz) == mhz_to_hz_rounded(user_mode->refresh_mhz)));
}

double mode_dpi(struct Mode *mode) {
Expand Down Expand Up @@ -144,7 +171,7 @@ struct SList *modes_res_refresh(struct SList *modes) {
mrr = calloc(1, sizeof(struct ModesResRefresh));
mrr->width = mode->width;
mrr->height = mode->height;
mrr->refresh_hz = mhz_to_hz(mode->refresh_mhz);
mrr->refresh_mhz = mode->refresh_mhz;
slist_append(&mrrs, mrr);
}

Expand All @@ -162,6 +189,12 @@ struct Mode *mode_user_mode(struct SList *modes, struct SList *modes_failed, str

struct SList *i, *j;

// exact res and refresh
struct Mode *mode_exact = slist_find_equal_val(modes, equal_mode_user_mode_res_refresh, user_mode);
if (mode_exact && !slist_find_equal_val(modes_failed, NULL, mode_exact)) {
return mode_exact;
}

// highest mode matching the user mode
struct SList *mrrs = modes_res_refresh(modes);
for (i = mrrs; i; i = i->nex) {
Expand All @@ -181,6 +214,19 @@ struct Mode *mode_user_mode(struct SList *modes, struct SList *modes_failed, str
return NULL;
}

struct Mode *mode_init(struct Head *head, struct zwlr_output_mode_v1 *zwlr_mode, int32_t width, int32_t height, int32_t refresh_mhz, bool preferred) {
struct Mode *mode = calloc(1, sizeof(struct Mode));

mode->head = head;
mode->zwlr_mode = zwlr_mode;
mode->width = width;
mode->height = height;
mode->refresh_mhz = refresh_mhz;
mode->preferred = preferred;

return mode;
}

void mode_free(void *data) {
struct Mode *mode = data;

Expand Down
2 changes: 1 addition & 1 deletion tst/cfg/validate-fix-mode.log
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Ignoring non-positive MODE negative width WIDTH -99

Ignoring non-positive MODE negative height HEIGHT -99

Ignoring non-positive MODE negative hz HZ -99
Ignoring non-positive MODE negative hz HZ -12.34

Ignoring invalid MODE missing width missing WIDTH

Expand Down
2 changes: 1 addition & 1 deletion tst/info/print-cfg-commands-ok.log
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ way-displays -s AUTO_SCALE OFF
way-displays -s SCALE 'one' 1.000
way-displays -s SCALE 'two' 2.346

way-displays -s MODE 'all' 1 2 3
way-displays -s MODE 'all' 1 2 12.34
way-displays -s MODE 'res' 4 5
way-displays -s MODE 'max' MAX

Expand Down
2 changes: 1 addition & 1 deletion tst/marshalling/cfg-all.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ MODE:
- NAME_DESC: five
WIDTH: 1920
HEIGHT: 1080
HZ: 60
HZ: 12.34
- NAME_DESC: six
WIDTH: 2560
HEIGHT: 1440
Expand Down
2 changes: 1 addition & 1 deletion tst/marshalling/ipc-request-cfg-set.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ CFG:
- NAME_DESC: five
WIDTH: 1920
HEIGHT: 1080
HZ: 60
HZ: 12.34
- NAME_DESC: six
WIDTH: 2560
HEIGHT: 1440
Expand Down
2 changes: 1 addition & 1 deletion tst/marshalling/ipc-responses-map.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ CFG:
- NAME_DESC: five
WIDTH: 1920
HEIGHT: 1080
HZ: 60
HZ: 12.34
- NAME_DESC: six
WIDTH: 2560
HEIGHT: 1440
Expand Down
2 changes: 1 addition & 1 deletion tst/tst-cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ void validate_fix__mode(void **state) {

slist_append(&s->from->user_modes, cfg_user_mode_init("negative height", false, 1, -99, 3, false));

slist_append(&s->from->user_modes, cfg_user_mode_init("negative hz", false, 1, 2, -99, false));
slist_append(&s->from->user_modes, cfg_user_mode_init("negative hz", false, 1, 2, -12340, false));

slist_append(&s->from->user_modes, cfg_user_mode_init("missing width", false, -1, 2, 3, false));

Expand Down
Loading