Skip to content

Commit

Permalink
Add arguments to set the desired resolution.
Browse files Browse the repository at this point in the history
This adds the --desired-width and --desired-height arguments which
tell kmscon what resolution the user *desires*. They are specifically
called desired because it is not guaranteed that this resolution will
be used: it will only work if the exact width and height match a
supported mode as reported by the system, and it will only work in
DRM mode (kmscon does not generally support modesetting in fbdev).

Additionally, it might not be possible to use the mode if there is not
enough memory to store the framebuffers. Using `video=<width>x<height>` on
the kernel's command line was enough to make sure that sufficient memory
was available on my machine. In this case, if we try to use the desired
mode then the user will be presented with a blank screen.

In either of the above cases, kmscon will revert to using the default
mode, which is what kmscon always uses prior to this patch.
  • Loading branch information
skyvine committed Jun 21, 2023
1 parent 607b6fa commit 151d817
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 13 deletions.
21 changes: 21 additions & 0 deletions docs/man/kmscon.1.xml.in
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,27 @@
only be used to debug render engines. (default: off)</para>
</listitem>
</varlistentry>

<varlistentry>
<term><option>--desired-width {pixels}</option></term>
<term><option>--desired-height {pixels}</option></term>
<listitem>
<para>Set the desired width and height of the output. The given width
and height must match a supported more exactly for this option to have
any effect; if there is no supported mode that matches exactly, or if there is
an error when using the desired mode, then the default mode (first valid mode
found) will be used.</para>

<para>Modesetting is only supported in DRM mode, so these options do
nothing with fbdev. However, fbset can still be used to externally set
the mode when fbdev is in use.</para>

<para>Other system components may need configuration in order to use the desired
mode effectively. For example, the `video={width}x{height}` kernel parameter may
be required in order to ensure that there is enough memory to store the
framebuffers for a large resolution.</para>
</listitem>
</varlistentry>
</variablelist>

<para>Font Options:</para>
Expand Down
21 changes: 15 additions & 6 deletions src/kmscon_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,19 @@ static void print_help()
"\t Create new terminal session\n"
"\n"
"Video Options:\n"
"\t --drm [on] Use DRM if available\n"
"\t --hwaccel [off] Use 3D hardware-acceleration if\n"
"\t available\n"
"\t --gpus={all,aux,primary}[all] GPU selection mode\n"
"\t --render-engine <eng> [-] Console renderer\n"
"\t --render-timing [off] Print renderer timing information\n"
"\t --drm [on] Use DRM if available\n"
"\t --hwaccel [off] Use 3D hardware-acceleration if\n"
"\t available\n"
"\t --gpus={all,aux,primary} [all] GPU selection mode\n"
"\t --render-engine <eng> [-] Console renderer\n"
"\t --render-timing [off] Print renderer timing information\n"
"\t --desired-width <pixels> [0]\n"
"\t --desired-height <pixels> [0] Set the desired width/height of\n"
"\t the output. If the desired mode\n"
"\t is not available or encounters an\n"
"\t error, a default mode will be\n"
"\t used. See the man page for\n"
"\t additional details.\n"
"\n"
"Font Options:\n"
"\t --font-engine <engine> [pango]\n"
Expand Down Expand Up @@ -734,6 +741,8 @@ int kmscon_conf_new(struct conf_ctx **out)
CONF_OPTION_BOOL(0, "hwaccel", &conf->hwaccel, false),
CONF_OPTION(0, 0, "gpus", &conf_gpus, NULL, NULL, NULL, &conf->gpus, KMSCON_GPU_ALL),
CONF_OPTION_STRING(0, "render-engine", &conf->render_engine, NULL),
CONF_OPTION_UINT(0, "desired-width", &conf->desired_width, 0),
CONF_OPTION_UINT(0, "desired-height", &conf->desired_height, 0),

/* Font Options */
CONF_OPTION_STRING(0, "font-engine", &conf->font_engine, "pango"),
Expand Down
3 changes: 3 additions & 0 deletions src/kmscon_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ struct kmscon_conf_t {
unsigned int gpus;
/* render engine */
char *render_engine;
/* screen resolution */
unsigned int desired_width;
unsigned int desired_height;

/* Font Options */
/* font engine */
Expand Down
7 changes: 5 additions & 2 deletions src/kmscon_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,16 @@ static int app_seat_add_video(struct app_seat *seat,
mode = UTERM_VIDEO_FBDEV;
}

ret = uterm_video_new(&vid->video, seat->app->eloop, node, mode);
ret = uterm_video_new(&vid->video, seat->app->eloop, node, mode,
seat->conf->desired_width, seat->conf->desired_height);
if (ret) {
if (mode == UTERM_VIDEO_DRM3D) {
log_info("cannot create drm3d device %s on seat %s (%d); trying drm2d mode",
vid->node, seat->name, ret);
ret = uterm_video_new(&vid->video, seat->app->eloop,
node, UTERM_VIDEO_DRM2D);
node, UTERM_VIDEO_DRM2D,
seat->conf->desired_width,
seat->conf->desired_height);
if (ret)
goto err_node;
} else {
Expand Down
10 changes: 10 additions & 0 deletions src/kmscon_terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ static void do_clear_margins(struct screen *scr)
sw, dh);
}

static int font_set(struct kmscon_terminal *term);

static void do_redraw_screen(struct screen *scr)
{
int ret;
Expand All @@ -129,6 +131,14 @@ static void do_redraw_screen(struct screen *scr)
kmscon_text_render(scr->txt);

ret = uterm_display_swap(scr->disp, false);

if (ret == -EAGAIN) {
uterm_display_deactivate(scr->disp);
uterm_display_activate(scr->disp, NULL);
font_set(scr->term);
ret = uterm_display_swap(scr->disp, false);
}

if (ret) {
log_warning("cannot swap display %p", scr->disp);
return;
Expand Down
23 changes: 23 additions & 0 deletions src/uterm_drm_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,11 @@ int uterm_drm_display_swap(struct uterm_display *disp, uint32_t fb,
ret = drmModePageFlip(vdrm->fd, ddrm->crtc_id, fb,
DRM_MODE_PAGE_FLIP_EVENT, disp);
if (ret) {
if (disp->desired_mode != disp->default_mode) {
disp->desired_mode = disp->default_mode;
log_debug("Unable to page-flip desired mode! Switching to default mode.");
return -EAGAIN;
}
log_error("cannot page-flip on DRM-CRTC (%d): %m",
errno);
return -EFAULT;
Expand Down Expand Up @@ -616,9 +621,27 @@ static void bind_display(struct uterm_video *video, drmModeRes *res,
if (!disp->default_mode)
disp->default_mode = mode;

if (video->desired_width != 0 &&
video->desired_height != 0 &&
mode->ops->get_width(mode) == video->desired_width &&
mode->ops->get_height(mode) == video->desired_height)
disp->desired_mode = mode;

uterm_mode_unref(mode);
}

if (!disp->desired_mode) {
disp->desired_mode = disp->default_mode;
}

log_debug("Default mode %dx%d",
disp->default_mode->ops->get_width(disp->default_mode),
disp->default_mode->ops->get_height(disp->default_mode));

log_debug("Desired mode %dx%d",
disp->desired_mode->ops->get_width(disp->desired_mode),
disp->desired_mode->ops->get_height(disp->desired_mode));

if (shl_dlist_empty(&disp->modes)) {
log_warn("no valid mode for display found");
ret = -EFAULT;
Expand Down
8 changes: 6 additions & 2 deletions src/uterm_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,7 @@ int uterm_display_activate(struct uterm_display *disp, struct uterm_mode *mode)
return -EINVAL;

if (!mode)
mode = disp->default_mode;
mode = disp->desired_mode;

return VIDEO_CALL(disp->ops->activate, 0, disp, mode);
}
Expand Down Expand Up @@ -544,7 +544,8 @@ int uterm_display_fake_blendv(struct uterm_display *disp,

SHL_EXPORT
int uterm_video_new(struct uterm_video **out, struct ev_eloop *eloop,
const char *node, const struct uterm_video_module *mod)
const char *node, const struct uterm_video_module *mod,
unsigned int desired_width, unsigned int desired_height)
{
struct uterm_video *video;
int ret;
Expand Down Expand Up @@ -572,6 +573,9 @@ int uterm_video_new(struct uterm_video **out, struct ev_eloop *eloop,
if (ret)
goto err_hook;

video->desired_width = desired_width;
video->desired_height = desired_height;

ev_eloop_ref(video->eloop);
log_info("new device %p", video);
*out = video;
Expand Down
3 changes: 2 additions & 1 deletion src/uterm_video.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ int uterm_display_fake_blendv(struct uterm_display *disp,
/* video interface */

int uterm_video_new(struct uterm_video **out, struct ev_eloop *eloop,
const char *node, const struct uterm_video_module *mod);
const char *node, const struct uterm_video_module *mod,
unsigned int desired_width, unsigned int desired_height);
void uterm_video_ref(struct uterm_video *video);
void uterm_video_unref(struct uterm_video *video);

Expand Down
4 changes: 4 additions & 0 deletions src/uterm_video_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ struct uterm_display {
struct shl_hook *hook;
struct shl_dlist modes;
struct uterm_mode *default_mode;
struct uterm_mode *desired_mode;
struct uterm_mode *current_mode;
int dpms;

Expand Down Expand Up @@ -159,6 +160,9 @@ struct uterm_video {
struct shl_dlist displays;
struct shl_hook *hook;

unsigned int desired_width;
unsigned int desired_height;

const struct uterm_video_module *mod;
const struct video_ops *ops;
void *data;
Expand Down
12 changes: 10 additions & 2 deletions tests/test_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ struct {
bool fbdev;
bool test;
char *dev;
unsigned int desired_width;
unsigned int desired_height;
} output_conf;

static int blit_outputs(struct uterm_video *video)
Expand Down Expand Up @@ -187,6 +189,8 @@ struct conf_option options[] = {
CONF_OPTION_BOOL(0, "fbdev", &output_conf.fbdev, false),
CONF_OPTION_BOOL(0, "test", &output_conf.test, false),
CONF_OPTION_STRING(0, "dev", &output_conf.dev, NULL),
CONF_OPTION_UINT(0, "desired-width", &output_conf.desired_width, 0),
CONF_OPTION_UINT(0, "desired-height", &output_conf.desired_height, 0),
};

int main(int argc, char **argv)
Expand Down Expand Up @@ -215,12 +219,16 @@ int main(int argc, char **argv)

log_notice("Creating video object using %s...", node);

ret = uterm_video_new(&video, eloop, node, mode);
ret = uterm_video_new(&video, eloop, node, mode,
output_conf.desired_width,
output_conf.desired_height);
if (ret) {
if (mode == UTERM_VIDEO_DRM3D) {
log_notice("cannot create drm device; trying drm2d mode");
ret = uterm_video_new(&video, eloop, node,
UTERM_VIDEO_DRM2D);
UTERM_VIDEO_DRM2D,
output_conf.desired_width,
output_conf.desired_height);
if (ret)
goto err_exit;
} else {
Expand Down

0 comments on commit 151d817

Please sign in to comment.