Skip to content

Commit fa92900

Browse files
committed
Display (Linux): detect preferred resolution and refresh rate
1 parent 3d5133e commit fa92900

File tree

10 files changed

+186
-100
lines changed

10 files changed

+186
-100
lines changed

src/detection/displayserver/displayserver.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ FFDisplayResult* ffdsAppendDisplay(
77
double refreshRate,
88
uint32_t scaledWidth,
99
uint32_t scaledHeight,
10+
uint32_t preferredWidth,
11+
uint32_t preferredHeight,
12+
double preferredRefreshRate,
1013
uint32_t rotation,
1114
FFstrbuf* name,
1215
FFDisplayType type,
@@ -25,6 +28,9 @@ FFDisplayResult* ffdsAppendDisplay(
2528
display->refreshRate = refreshRate;
2629
display->scaledWidth = scaledWidth;
2730
display->scaledHeight = scaledHeight;
31+
display->preferredWidth = preferredWidth;
32+
display->preferredHeight = preferredHeight;
33+
display->preferredRefreshRate = preferredRefreshRate;
2834
display->rotation = rotation;
2935
ffStrbufInitMove(&display->name, name);
3036
display->type = type;

src/detection/displayserver/displayserver.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,20 @@ typedef enum __attribute__((__packed__)) FFDisplayHdrStatus
5858

5959
typedef struct FFDisplayResult
6060
{
61-
uint32_t width;
62-
uint32_t height;
63-
double refreshRate;
64-
uint32_t scaledWidth;
65-
uint32_t scaledHeight;
61+
uint32_t width; // in px
62+
uint32_t height; // in px
63+
double refreshRate; // in Hz
64+
uint32_t scaledWidth; // in px
65+
uint32_t scaledHeight; // in px
66+
uint32_t preferredWidth; // in px
67+
uint32_t preferredHeight; // in px
68+
double preferredRefreshRate; // in Hz
6669
FFstrbuf name;
6770
FFDisplayType type;
6871
uint32_t rotation;
6972
uint64_t id; // platform dependent
70-
uint32_t physicalWidth;
71-
uint32_t physicalHeight;
73+
uint32_t physicalWidth; // in mm
74+
uint32_t physicalHeight; // in mm
7275
bool primary;
7376
const char* platformApi;
7477
uint8_t bitDepth;
@@ -97,6 +100,9 @@ FFDisplayResult* ffdsAppendDisplay(
97100
double refreshRate,
98101
uint32_t scaledWidth,
99102
uint32_t scaledHeight,
103+
uint32_t preferredWidth,
104+
uint32_t preferredHeight,
105+
double preferredRefreshRate,
100106
uint32_t rotation,
101107
FFstrbuf* name,
102108
FFDisplayType type,

src/detection/displayserver/linux/drm.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
8484
width, height,
8585
refreshRate,
8686
0, 0,
87+
0, 0,
88+
0,
8789
0,
8890
&name,
8991
ffdsGetDisplayType(plainName),
@@ -298,24 +300,30 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
298300
ffdrmModeFreeEncoder(encoder);
299301
}
300302

301-
if (width == 0 || height == 0)
303+
uint32_t preferredWidth = 0, preferredHeight = 0, preferredRefreshRate = 0;
304+
305+
for (int iMode = 0; iMode < conn->count_modes; ++iMode)
302306
{
303-
// NVIDIA DRM driver seems incomplete and conn->encoder_id == 0
304-
// Assume preferred resolution is used as what we do in drmParseSys
305-
for (int iMode = 0; iMode < conn->count_modes; ++iMode)
306-
{
307-
drmModeModeInfo* mode = &conn->modes[iMode];
307+
drmModeModeInfo* mode = &conn->modes[iMode];
308308

309-
if (mode->type & DRM_MODE_TYPE_PREFERRED)
310-
{
311-
width = mode->hdisplay;
312-
height = mode->vdisplay;
313-
refreshRate = mode->vrefresh;
314-
break;
315-
}
309+
if (mode->type & DRM_MODE_TYPE_PREFERRED)
310+
{
311+
preferredWidth = mode->hdisplay;
312+
preferredHeight = mode->vdisplay;
313+
preferredRefreshRate = mode->vrefresh;
314+
break;
316315
}
317316
}
318317

318+
// NVIDIA DRM driver seems incomplete and conn->encoder_id == 0
319+
// Assume preferred resolution is used as what we do in drmParseSys
320+
if (width == 0 || height == 0)
321+
{
322+
width = preferredWidth;
323+
height = preferredHeight;
324+
refreshRate = preferredRefreshRate;
325+
}
326+
319327

320328
ffStrbufClear(&name);
321329
uint16_t myear = 0, mweak = 0;
@@ -382,6 +390,9 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
382390
refreshRate,
383391
0,
384392
0,
393+
preferredWidth,
394+
preferredHeight,
395+
preferredRefreshRate,
385396
0,
386397
&name,
387398
conn->connector_type == DRM_MODE_CONNECTOR_eDP || conn->connector_type == DRM_MODE_CONNECTOR_LVDS

src/detection/displayserver/linux/wayland/global-output.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@
66

77
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
88
{
9-
if(!(flags & WL_OUTPUT_MODE_CURRENT))
10-
return;
11-
129
WaylandDisplay* display = data;
13-
display->width = width;
14-
display->height = height;
15-
display->refreshRate = refreshRate;
10+
11+
if (flags & WL_OUTPUT_MODE_CURRENT)
12+
{
13+
display->width = width;
14+
display->height = height;
15+
display->refreshRate = refreshRate;
16+
}
17+
if (flags & WL_OUTPUT_MODE_PREFERRED)
18+
{
19+
display->preferredWidth = width;
20+
display->preferredHeight = height;
21+
display->preferredRefreshRate = refreshRate;
22+
}
1623
}
1724

1825
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
@@ -79,9 +86,6 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
7986

8087
WaylandDisplay display = {
8188
.parent = wldata,
82-
.width = 0,
83-
.height = 0,
84-
.refreshRate = 0,
8589
.scale = 1,
8690
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
8791
.type = FF_DISPLAY_TYPE_UNKNOWN,
@@ -118,6 +122,9 @@ void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* regist
118122
display.refreshRate / 1000.0,
119123
(uint32_t) (display.width / display.scale),
120124
(uint32_t) (display.height / display.scale),
125+
(uint32_t) display.preferredWidth,
126+
(uint32_t) display.preferredHeight,
127+
display.preferredRefreshRate / 1000.0,
121128
rotation,
122129
display.edidName.length
123130
? &display.edidName

src/detection/displayserver/linux/wayland/kde-output.c

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,33 @@ typedef struct WaylandKdeMode
1111
int32_t width;
1212
int32_t height;
1313
int32_t refreshRate;
14+
bool preferred;
1415
struct kde_output_device_mode_v2* pMode;
1516
} WaylandKdeMode;
1617

17-
static void waylandKdeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height)
18+
static void waylandKdeModeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height)
1819
{
1920
WaylandKdeMode* mode = (WaylandKdeMode*) data;
2021
mode->width = width;
2122
mode->height = height;
2223
}
2324

24-
static void waylandKdeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate)
25+
static void waylandKdeModeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate)
2526
{
2627
WaylandKdeMode* mode = (WaylandKdeMode*) data;
2728
mode->refreshRate = rate;
2829
}
2930

31+
static void waylandKdeModePreferredListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_)
32+
{
33+
WaylandKdeMode* mode = (WaylandKdeMode*) data;
34+
mode->preferred = true;
35+
}
36+
3037
static const struct kde_output_device_mode_v2_listener modeListener = {
31-
.size = waylandKdeSizeListener,
32-
.refresh = waylandKdeRefreshListener,
33-
.preferred = (void*) stubListener,
38+
.size = waylandKdeModeSizeListener,
39+
.refresh = waylandKdeModeRefreshListener,
40+
.preferred = waylandKdeModePreferredListener,
3441
.removed = (void*) stubListener,
3542
};
3643

@@ -40,7 +47,7 @@ static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output
4047
if (!wldata->internal) return;
4148

4249
WaylandKdeMode* newMode = ffListAdd((FFlist*) wldata->internal);
43-
newMode->pMode = mode;
50+
*newMode = (WaylandKdeMode) { .pMode = mode };
4451

4552
// Strangely, the listener is called only in this function, but not in `waylandKdeCurrentModeListener`
4653
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
@@ -52,18 +59,24 @@ static void waylandKdeCurrentModeListener(void* data, FF_MAYBE_UNUSED struct kde
5259
WaylandDisplay* wldata = (WaylandDisplay*) data;
5360
if (!wldata->internal) return;
5461

55-
WaylandKdeMode* current = NULL;
62+
int set = 0;
5663
FF_LIST_FOR_EACH(WaylandKdeMode, m, *(FFlist*) wldata->internal)
5764
{
5865
if (m->pMode == mode)
5966
{
60-
current = m;
61-
break;
67+
wldata->width = m->width;
68+
wldata->height = m->height;
69+
wldata->refreshRate = m->refreshRate;
70+
if (++set == 2) break;
71+
}
72+
else if (m->preferred)
73+
{
74+
wldata->preferredWidth = m->width;
75+
wldata->preferredHeight = m->height;
76+
wldata->preferredRefreshRate = m->refreshRate;
77+
if (++set == 2) break;
6278
}
6379
}
64-
wldata->width = current->width;
65-
wldata->height = current->height;
66-
wldata->refreshRate = current->refreshRate;
6780
}
6881

6982
static void waylandKdeScaleListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, wl_fixed_t scale)
@@ -164,9 +177,6 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry,
164177
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandKdeMode));
165178
WaylandDisplay display = {
166179
.parent = wldata,
167-
.width = 0,
168-
.height = 0,
169-
.refreshRate = 0,
170180
.scale = 1,
171181
.transform = WL_OUTPUT_TRANSFORM_NORMAL,
172182
.type = FF_DISPLAY_TYPE_UNKNOWN,
@@ -191,6 +201,9 @@ void ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry,
191201
display.refreshRate / 1000.0,
192202
(uint32_t) (display.width / display.scale),
193203
(uint32_t) (display.height / display.scale),
204+
(uint32_t) display.preferredWidth,
205+
(uint32_t) display.preferredHeight,
206+
display.preferredRefreshRate / 1000.0,
194207
rotation,
195208
display.edidName.length
196209
? &display.edidName

src/detection/displayserver/linux/wayland/wayland.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,12 @@ typedef struct WaylandDisplay
3636
WaylandData* parent;
3737
int32_t width;
3838
int32_t height;
39+
int32_t refreshRate;
40+
int32_t preferredWidth;
41+
int32_t preferredHeight;
42+
int32_t preferredRefreshRate;
3943
int32_t physicalWidth;
4044
int32_t physicalHeight;
41-
int32_t refreshRate;
4245
double scale;
4346
enum wl_output_transform transform;
4447
FFDisplayType type;

0 commit comments

Comments
 (0)