From 1392ff8d3b96da943133b87888767c6725a241bd Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 12 Sep 2026 20:29:13 +0300 Subject: [PATCH 01/47] kdrive: Add a closure field to `KdScreenInfo` Signed-off-by: stefan11111 --- hw/kdrive/ephyr/ephyrinit.c | 2 +- hw/kdrive/src/kdrive.c | 4 ++-- hw/kdrive/src/kdrive.h | 3 ++- hw/kdrive/src/kinfo.c | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 992f3e7c927..d1ac8791273 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -139,7 +139,7 @@ processScreenOrOutputArg(const char *screen_size, const char *output, char *pare unsigned long p_id = 0; Bool use_geometry; - screen = KdScreenInfoAdd(card); + screen = KdScreenInfoAdd(card, NULL); KdParseScreen(screen, screen_size); screen->driver = calloc(1, sizeof(EphyrScrPriv)); if (!screen->driver) diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index d45ce83f096..43ae6d860ac 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -495,7 +495,7 @@ KdProcessArgument(int argc, char **argv, int i) card = KdCardInfoLast(); } if (card) { - screen = KdScreenInfoAdd(card); + screen = KdScreenInfoAdd(card, NULL); KdParseScreen(screen, screen_arg); } else { ErrorF("No matching card found!\n"); @@ -1127,7 +1127,7 @@ KdInitOutput(int argc, char **argv) /* Add at least one screen */ if (!card->screenList) { - screen = KdScreenInfoAdd(card); + screen = KdScreenInfoAdd(card, NULL); KdParseScreen(screen, 0); } diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h index 4c87d609813..880919ff61a 100644 --- a/hw/kdrive/src/kdrive.h +++ b/hw/kdrive/src/kdrive.h @@ -91,6 +91,7 @@ typedef struct _KdScreenInfo { struct _KdScreenInfo *next; KdCardInfo *card; ScreenPtr pScreen; + void *closure; void *driver; Rotation randr; /* rotation and reflection */ int x; @@ -455,7 +456,7 @@ KdCardInfo *KdCardInfoLast(void); void KdCardInfoDispose(KdCardInfo * ci); -KdScreenInfo *KdScreenInfoAdd(KdCardInfo * ci); +KdScreenInfo *KdScreenInfoAdd(KdCardInfo * ci, void *closure); void KdScreenInfoDispose(KdScreenInfo * si); diff --git a/hw/kdrive/src/kinfo.c b/hw/kdrive/src/kinfo.c index 4d8b0fda110..da5e2a49903 100644 --- a/hw/kdrive/src/kinfo.c +++ b/hw/kdrive/src/kinfo.c @@ -70,7 +70,7 @@ KdCardInfoDispose(KdCardInfo * ci) } KdScreenInfo * -KdScreenInfoAdd(KdCardInfo * ci) +KdScreenInfoAdd(KdCardInfo * ci, void *closure) { KdScreenInfo *si, **prev; int n; @@ -80,6 +80,7 @@ KdScreenInfoAdd(KdCardInfo * ci) return 0; for (prev = &ci->screenList, n = 0; *prev; prev = &(*prev)->next, n++); *prev = si; + si->closure = closure; si->next = 0; si->card = ci; si->mynum = n; From 0e9631c6c2d47670ff72722bd119c86ee52009dc Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sun, 13 Sep 2026 01:13:23 +0300 Subject: [PATCH 02/47] kdrive: Add Xmodesetting X server Tiny X server for KMS devices More or less a direct import of https://github.com/tinycorelinux/tinyx/pull/20 with Xfbdev-like glamor acceleration, which we get for cheap Signed-off-by: stefan11111 --- hw/kdrive/meson.build | 14 +- hw/kdrive/modesetting/Xmodesetting.man | 84 ++ hw/kdrive/modesetting/meson.build | 43 + hw/kdrive/modesetting/modesetting.c | 1115 ++++++++++++++++++++++++ hw/kdrive/modesetting/modesetting.h | 82 ++ hw/kdrive/modesetting/ms_glamor.c | 105 +++ hw/kdrive/modesetting/msinit.c | 216 +++++ meson.build | 6 +- meson_options.txt | 2 + 9 files changed, 1663 insertions(+), 4 deletions(-) create mode 100644 hw/kdrive/modesetting/Xmodesetting.man create mode 100644 hw/kdrive/modesetting/meson.build create mode 100644 hw/kdrive/modesetting/modesetting.c create mode 100644 hw/kdrive/modesetting/modesetting.h create mode 100644 hw/kdrive/modesetting/ms_glamor.c create mode 100644 hw/kdrive/modesetting/msinit.c diff --git a/hw/kdrive/meson.build b/hw/kdrive/meson.build index 4a69306a5e8..8781153c555 100644 --- a/hw/kdrive/meson.build +++ b/hw/kdrive/meson.build @@ -1,7 +1,8 @@ -build_kdrive = build_xephyr or build_xfake or build_xfbdev +build_kdrive = build_xephyr or build_xfake or build_xfbdev or build_xmodesetting +want_kdrive_linux = build_xfbdev or build_xmodesetting need_kdrive_linux = build_xfbdev -build_kdrive_linux = (host_machine.system() == 'linux') and need_kdrive_linux +build_kdrive_linux = (host_machine.system() == 'linux') and want_kdrive_linux build_kdrive_kbd = false build_kdrive_mouse = false @@ -21,7 +22,7 @@ if build_kdrive_linux subdir('os/linux') endif -build_stub = build_xfake +build_stub = build_xfake or ((not build_kdrive_linux) and want_kdrive_linux) if build_stub subdir('os/stub') endif @@ -42,6 +43,13 @@ if build_xfbdev subdir('fbdev') endif +if build_xmodesetting + if (not build_gbm) or (not libdrm_dep.found()) + error('Xmodesetting needs libdrm and libgbm') + endif + subdir('modesetting') +endif + if build_kdrive xkdrive_man = configure_file( input: 'Xkdrive.man', diff --git a/hw/kdrive/modesetting/Xmodesetting.man b/hw/kdrive/modesetting/Xmodesetting.man new file mode 100644 index 00000000000..ca3641b384b --- /dev/null +++ b/hw/kdrive/modesetting/Xmodesetting.man @@ -0,0 +1,84 @@ +.TH Xmodesetting 1 __vendorversion__ +.SH NAME +Xmodesetting \- KMS device tiny X server +.SH SYNOPSIS +.B Xmodesetting +.RI [ :display ] +.RI [ option ...] +.SH DESCRIPTION +.B Xmodesetting +is a generic X server for KMS devices. +.SH OPTIONS +.B Xmodesetting +accepts the common options of the Xkdrive family of servers. Please +see Xkdrive(@appmansuffix@). + +.B Xmodesetting +also accepts the following additional options: +.TP 8 +.B -dev "" +sets the KMS scanout device path the X server will use. +If no -dri option was passed, this device will also be used for rendering +.TP 8 +.B -noshadow +disables the ShadowFB layer on supported hw, may slightly increase performance. +May also lead to flickering. + +.SH CONFIGURATION +. +Like all kdrive X servers, +.B Xmodesetting +doesn't read any configuration file. +Instead, all configuration is done via command-line arguments. + +.B Xmodesetting +is intended to provide a reasonable configuration out-of-the-box, with no special configuration. +Simply running +.B xinit -- /path/to/Xmodesetting +should provide a default configuration that is able to provide a usable display. +This default configuration is rather simplistic, with the aim of working +almost anywhere, while sacrificing performance. + +For regular use, a shell script or similar can be created to invoke xinit and pass all the necessary command-line arguments. + +In the most general form, the configuration of +.B Xmodesetting +looks like this: +.B xinit -- /path/to/Xmodesetting [server_args] [screen_0_args] -screen [geom] [screen_1_args] -screen [geom] ... [screen_n_args] -screen [geom] [screen_n_args] + +Arguments whose effect is intended to affect the entire X server instead of a particular screen (e.g. +xinerama) can be added anywhere, +but they are usually added before the arguments of the first screen. + +If a single X11 screen is desired, with no special geometry, +.B Xmodesetting +supports using an implicit first screen, like so: +.B xinit -- /path/to/Xmodesetting [server_args] [screen_args] + +Below are listed some example configurations, intended to serve as a guide for configuring +.B Xmodesetting. + +A single X11 screen with DRI3 running on a different card than the framebuffer, with an explicit glvendor and with only OpenGL ES contexts allowed: +.B xinit -- /usr/bin/Xmodesetting :1 -fb /dev/fb0 -glvendor nvidia -dri /dev/dri/card1 -force-es + +Two X11 screens with DRI3 support, with the first screen on the left, the second screen on the right: +.B xinit -- /usr/bin/Xmodesetting -dri /dev/dri/card1 -fb /dev/fb0 -screen 1920x1080 -fb /dev/fb1 -dri /dev/dri/card1 -screen 1920x1080 + +Two X11 screens with DRI3 support, with the first screen on the left, the second screen on the right, using xinerama: +.B xinit -- /usr/bin/Xmodesetting +xinerama -dri /dev/dri/card1 -fb /dev/fb0 -screen 1920x1080 -fb /dev/fb1 -dri /dev/dri/card1 -screen 1920x1080 + +Two X11 screens, the first one below the second one: +.B xinit -- /usr/bin/Xmodesetting -fb /dev/fb0 -origin 0,1080 -screen 1920x1080 -fb /dev/fb1 -origin 0,0 -screen 1920x1080 + +.SH KEYBOARD +.B Xmodesetting +supports the common special key combinations of the Xkdrive family of servers. Please +see Xkdrive(@appmansuffix@). + +.SH SEE ALSO +X(@miscmansuffix@), Xserver(@appmansuffix@), Xkdrive(@appmansuffix@), xdm(@appmansuffix@), xinit(@appmansuffix@). +.SH AUTHORS +The +.B Xmodesetting +server was written by stefan11111. + +Is was inspired by the Xfbdev X server, written by Keith Packard. diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build new file mode 100644 index 00000000000..3e336460fdd --- /dev/null +++ b/hw/kdrive/modesetting/meson.build @@ -0,0 +1,43 @@ +srcs = [ + 'modesetting.c', + 'msinit.c', + '../../stubs/ddxBeforeReset.c', +] + +ms_glamor = [] +if build_glamor + srcs += 'ms_glamor.c' + ms_glamor += glamor +endif + +xmodesetting_server = executable( + 'Xmodesetting', + srcs, + include_directories: [ + inc, + include_directories('../src'), + include_directories('../os/linux'), + include_directories('../os/stub'), + ], + dependencies: [ common_dep, libdrm_dep, gbm_dep ], + link_with: [ + libxserver_main, + ms_glamor, + kdrive, + linux, + libxserver_fb, + libxserver, + libxserver_glx, + libxserver_config, + libxserver_xkeyboard_stubs, + libglxvnd, + ], + install: true, +) + +xmodesetting_man = configure_file( + input: 'Xmodesetting.man', + output: 'Xmodesetting.1', + configuration: manpage_config, +) +install_man(xmodesetting_man) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c new file mode 100644 index 00000000000..87633997c1b --- /dev/null +++ b/hw/kdrive/modesetting/modesetting.c @@ -0,0 +1,1115 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" +#include + +#include + +#ifdef XV +#include "kxv.h" +#endif + +typedef struct { + drmModeConnector *connector; + drmModeRes *resources; + drmModeModeInfo *mode; + + void *map_data; + void *map_addr; + + uint32_t conn_id; + uint32_t crtc_id; + uint32_t fb_id; +} gbm_user_data_t; + +static Bool msMapFramebuffer(KdScreenInfo * screen); + +static inline void* +gbm_bo_get_map(struct gbm_bo *bo) +{ + gbm_user_data_t *data = gbm_bo_get_user_data(bo); + return data ? data->map_addr : NULL; +} + +static void +destroy_user_data(struct gbm_bo *bo, void *_data) +{ + struct gbm_device *gbm = gbm_bo_get_device(bo); + int fd = gbm_device_get_fd(gbm); + gbm_user_data_t* data = _data; + if (!data) { + return; + } + + if (data->fb_id) { + drmModeRmFB(fd, data->fb_id); + } + + if (data->map_data) { + gbm_bo_unmap(bo, data->map_data); + } + + if (data->connector) { + drmModeFreeConnector(data->connector); + } + + if (data->resources) { + drmModeFreeResources(data->resources); + } + + free(data); +} + +static inline int +gbm_bo_map_all(struct gbm_bo *bo, gbm_user_data_t *data) +{ + uint32_t stride = 0; + + if (!bo || !data) { + return FALSE; + } + + if (data->map_addr) { + return TRUE; + } + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + + /* must be NULL before the map call */ + data->map_data = NULL; + + /* While reading from gpu memory is often very slow, we do allow it */ + data->map_addr = gbm_bo_map(bo, 0, 0, width, height, + GBM_BO_TRANSFER_READ_WRITE, + &stride, &data->map_data); + + return !!data->map_addr; +} + +static inline int +gbm_bo_map_or_free(struct gbm_bo *bo, gbm_user_data_t *data) +{ + if (gbm_bo_map_all(bo, data)) { + return TRUE; + } + + if (bo) { + gbm_bo_destroy(bo); + } + return FALSE; +} + +static inline struct gbm_bo* +gbm_bo_create_and_map_once(struct gbm_device *gbm, + gbm_user_data_t *data, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags) +{ + struct gbm_bo *ret = NULL; + + if (!data) { + return NULL; + } + + ret = gbm_bo_create(gbm, width, height, format, flags); + if (ret && gbm_bo_map_or_free(ret, data)) { + return ret; + } + + return NULL; +} + +static struct gbm_bo* +gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, int w, int h) +{ + uint32_t width = data->mode ? data->mode->hdisplay : w; + uint32_t height = data->mode ? data->mode->vdisplay : h; + + uint32_t format = GBM_FORMAT_XRGB8888; +#if 0 + uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_FRONT_RENDERING; + uint32_t flags2 = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; +#endif + uint32_t flags_dumb = GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE; + + struct gbm_bo *bo = NULL; + +#if 0 /* non-dumb buffers require unmap + map to flush writes, which is far slower than ShadowFB */ + bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags); + if (!bo) { + bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags2); + } +#endif + if (!bo) { + bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags_dumb); + } + + return bo; +} + +static int +gbm_bo_create_fb(struct gbm_bo *bo) +{ + struct gbm_device *gbm = gbm_bo_get_device(bo); + int fd = gbm_device_get_fd(gbm); + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t pitch = gbm_bo_get_stride(bo); + uint32_t handle = gbm_bo_get_handle(bo).u32; + uint32_t fb_id = 0; + + int ret = drmModeAddFB(fd, width, height, 24, 32, pitch, handle, &fb_id); + return ret ? 0 : fb_id; +} + +static int +modesetting_grade_mode(drmModeModeInfo *mode, uint32_t req_w, uint32_t req_h, uint32_t req_rate) +{ + int score = 1; + + if (req_w && (req_w == mode->hdisplay)) { + score += 10; + } + + if (req_h && (req_h == mode->vdisplay)) { + score += 10; + } + + if (req_rate && (req_rate == mode->vrefresh)) { + score += 5; + } + + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + score++; + } + + return score; +} + +static drmModeModeInfo* +modesetting_find_mode(drmModeConnector *conn, uint32_t req_w, uint32_t req_h, uint32_t req_rate) +{ + drmModeModeInfo *best_mode = NULL; + int best_score = 0; + + for (int i = 0; i < conn->count_modes; i++) { + drmModeModeInfo *mode = &conn->modes[i]; + int score; + + score = modesetting_grade_mode(mode, req_w, req_h, req_rate); + if (score <= best_score) { + continue; + } + + best_mode = mode; + best_score = score; + } + + return best_mode; +} + +static int +modesetting_grade_connector(drmModeConnector *conn) +{ + if (!conn->modes || !conn->count_modes) { + return 1; + } + + switch(conn->connection) { + case DRM_MODE_CONNECTED: + return 5; + case DRM_MODE_UNKNOWNCONNECTION: + return 4; + case DRM_MODE_DISCONNECTED: + return 3; + } + + /* unreachable */ + return 2; +} + +static drmModeConnector* +modesetting_find_connector(drmModeRes *res, int fd, uint32_t *conn_id) +{ + drmModeConnector *best_connector = NULL; + int best_score = 0; + + for (int i = 0; i < res->count_connectors; i++) { + drmModeConnector *conn; + int id; + int score; + id = res->connectors[i]; + conn = drmModeGetConnector(fd, id); + if (!conn) { + continue; + } + + score = modesetting_grade_connector(conn); + if (score <= best_score) { + drmModeFreeConnector(conn); + continue; + } + + if (best_connector) { + drmModeFreeConnector(best_connector); + } + + best_connector = conn; + *conn_id = id; + best_score = score; + } + + return best_connector; +} + +/* From man drm-kms */ +static int +modeseting_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn) +{ + drmModeEncoder *enc; + unsigned int i, j; + + /* iterate all encoders of this connector */ + for (i = 0; i < conn->count_encoders; ++i) { + enc = drmModeGetEncoder(fd, conn->encoders[i]); + if (!enc) { + /* cannot retrieve encoder, ignoring... */ + continue; + } + + /* iterate all global CRTCs */ + for (j = 0; j < res->count_crtcs; ++j) { + /* check whether this CRTC works with the encoder */ + if (!(enc->possible_crtcs & (1 << j))) + continue; + + /* Here you need to check that no other connector + * currently uses the CRTC with id "crtc". If you intend + * to drive one connector only, then you can skip this + * step. Otherwise, simply scan your list of configured + * connectors and CRTCs whether this CRTC is already + * used. If it is, then simply continue the search here. */ + drmModeFreeEncoder(enc); + return res->crtcs[j]; + } + + drmModeFreeEncoder(enc); + } + + /* cannot find a suitable CRTC */ + return -ENOENT; +} + + +static struct gbm_bo* +modesetting_open(struct gbm_device *gbm, KdScreenInfo *screen) +{ + int fd = gbm_device_get_fd(gbm); + struct gbm_bo *ret = NULL; + gbm_user_data_t *data = NULL; + + data = calloc(1, sizeof(*data)); + if (!data) { + goto fail; + } + + drmSetMaster(fd); + + data->resources = drmModeGetResources(fd); + if (!data->resources) { + goto fail; + } + + data->connector = modesetting_find_connector(data->resources, fd, &data->conn_id); + if (!data->connector) { + goto fail; + } + + data->mode = modesetting_find_mode(data->connector, screen->width, screen->height, screen->rate); + if (!data->mode) { + LogMessage(X_WARNING, "Xmodesetting(%d): Could not find a supported mode\n", + screen->card->mynum); + LogMessage(X_WARNING, "Xmodesetting(%d): This likely means the video card has no connected outputs, or the requested mode is not supported\n", + screen->card->mynum); + } + + ret = gbm_bo_create_and_map(gbm, data, screen->width ? screen->width : 1920, screen->height ? screen->height : 1080); + if (!ret) { + goto fail; + } + + gbm_bo_set_user_data(ret, data, destroy_user_data); + + data->fb_id = gbm_bo_create_fb(ret); + if (!data->fb_id) { + goto fail; + } + + data->crtc_id = modeseting_find_crtc(fd, data->resources, data->connector); + if (data->crtc_id < 0) { + goto fail; + } + + return ret; + +fail: + if (ret) { + gbm_bo_destroy(ret); + /* destroy_user_data takes care of the rest */ + return NULL; + } + + if (data) { + if (data->connector) + drmModeFreeConnector(data->connector); + if (data->resources) + drmModeFreeResources(data->resources); + free(data); + } + + return NULL; +} + +static Bool +msSetMode(ScreenPtr pScreen, int rate) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + struct gbm_bo *new_bo; + int oldwidth, oldheight, oldrate; + + oldwidth = screen->width; + oldheight = screen->height; + oldrate = screen->rate; + + screen->width = pScreen->width; + screen->height = pScreen->height; + screen->rate = rate; + + new_bo = modesetting_open(priv->gbm, screen); + if (!new_bo) { + screen->width = oldwidth; + screen->height = oldheight; + screen->rate = oldrate; + return FALSE; + } + + gbm_bo_destroy(scrpriv->front); + scrpriv->front = new_bo; + return TRUE; +} + +static Bool msInitialize(KdCardInfo * card, msPriv * priv) +{ + MsScreenConf *config = card->closure; + int fd; + + if (config->dev_path) { + fd = open(config->dev_path, O_RDWR); + if (fd < 0) { + LogMessage(X_ERROR, "Xmodesetting(%d): Error opening KMS device %s: %s\n", + card->mynum, config->dev_path, strerror(errno)); + return FALSE; + } + LogMessage(X_INFO, "Xmodesetting(%d): Using KMS device: %s\n", + card->mynum, config->dev_path); + } else { + char devbuf[] = "/dev/dri/cardxx"; + fd = -1; + for (int i = 0; i < 64 && (fd < 0); i++) { + snprintf(devbuf, sizeof(devbuf), + "/dev/dri/card%d", i); + fd = open(devbuf, O_RDWR); + + if (fd >= 0) { + uint64_t check_dumb = 0; + + if (drmGetCap(fd, DRM_CAP_DUMB_BUFFER, &check_dumb) >= 0 && check_dumb) { + break; + } + + close(fd); + fd = -1; + } + } + if (fd < 0) { + ErrorF("Error opening kms devices /dev/dri/card[0-63]\n"); + return FALSE; + } + LogMessage(X_INFO, "Xmodesetting(%d): Using kms device: %s\n", card->mynum, devbuf); + } + + priv->gbm = gbm_create_device(fd); + if (!priv->gbm) { + ErrorF("Could not create a gbm device\n"); + close(fd); + return FALSE; + } + + return TRUE; +} + +Bool msCardInit(KdCardInfo * card) +{ + msPriv *priv; + + priv = calloc(1, sizeof(msPriv)); + if (!priv) + return FALSE; + + if (!msInitialize(card, priv)) { + free(priv); + return FALSE; + } + card->driver = priv; + + return TRUE; +} + +static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) +{ + msPriv *priv = screen->card->driver; + gbm_user_data_t *data = NULL; + + scrpriv->front = modesetting_open(priv->gbm, screen); + if (!scrpriv->front) { + return FALSE; + } + + data = gbm_bo_get_user_data(scrpriv->front); + + screen->width = gbm_bo_get_width(scrpriv->front); + screen->height = gbm_bo_get_height(scrpriv->front); + screen->rate = data->mode ? data->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ + + /* GBM_FORMAT_XRGB8888 */ + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0xff << 16; + screen->fb.greenMask = 0xff << 8; + screen->fb.blueMask = 0xff; + + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 32; + + scrpriv->randr = screen->randr; + return msMapFramebuffer(screen); +} + +Bool msScreenInit(KdScreenInfo * screen) +{ + msScrPriv *scrpriv; + + scrpriv = calloc(1, sizeof(msScrPriv)); + if (!scrpriv) + return FALSE; + + screen->driver = scrpriv; + if (!msScreenInitialize(screen, scrpriv)) { + screen->driver = 0; + free(scrpriv); + return FALSE; + } + return TRUE; +} + +static void *msWindowLinear(ScreenPtr pScreen, + CARD32 row, + CARD32 offset, int mode, CARD32 * size, void *closure) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + CARD8 *mem; + + if (!pScreenPriv->enabled) + return NULL; + + *size = gbm_bo_get_stride(priv->front); + mem = gbm_bo_get_map(priv->front); + return mem + row * (*size) + offset; +} + +static Bool msMapFramebuffer(KdScreenInfo * screen) +{ + msScrPriv *scrpriv = screen->driver; + KdPointerMatrix m; + MsScreenConf *config = screen->card->closure; + + unsigned long stride = gbm_bo_get_stride(scrpriv->front); + + if (config->shadow >= 0) { + scrpriv->shadow = config->shadow; + } else if (scrpriv->randr != RR_Rotate_0) { + scrpriv->shadow = TRUE; + } else { + scrpriv->shadow = FALSE; + } + + KdComputePointerMatrix(&m, scrpriv->randr, screen->width, screen->height); + + KdSetPointerMatrix(&m); + + screen->width = gbm_bo_get_width(scrpriv->front); + screen->height = gbm_bo_get_height(scrpriv->front); + + if (scrpriv->shadow) { + if (!KdShadowFbAlloc(screen, + scrpriv->randr & (RR_Rotate_90 | RR_Rotate_270))) { + return FALSE; + } + } else { + screen->fb.byteStride = stride; + screen->fb.pixelStride = stride / 4; + screen->fb.frameBuffer = gbm_bo_get_map(scrpriv->front); + } + + return TRUE; +} + +static void msSetScreenSizes(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + + if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) { + pScreen->width = gbm_bo_get_width(scrpriv->front); + pScreen->height = gbm_bo_get_height(scrpriv->front); + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } else { + pScreen->width = gbm_bo_get_height(scrpriv->front); + pScreen->height = gbm_bo_get_width(scrpriv->front); + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + } +} + +static Bool msUnmapFramebuffer(KdScreenInfo * screen) +{ + KdShadowFbFree(screen); + return TRUE; +} + +static Bool msSetShadow(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + ShadowUpdateProc update; + ShadowWindowProc window; + + window = msWindowLinear; + update = 0; + + if (scrpriv->randr) + update = shadowUpdateRotatePacked; + else + update = shadowUpdatePacked; + return KdShadowSet(pScreen, scrpriv->randr, update, window); +} + +static Bool msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + gbm_user_data_t *data = gbm_bo_get_user_data(scrpriv->front); + Rotation randr; + int n; + + *rotations = RR_Rotate_All | RR_Reflect_All; + + for (n = 0; n < pScreen->numDepths; n++) { + if (pScreen->allowedDepths[n].numVids) { + break; + } + } + + if (n == pScreen->numDepths) { + return FALSE; + } + + randr = KdSubRotation(scrpriv->randr, screen->randr); + + for (int i = 0; i < data->connector->count_modes; i++) { + drmModeModeInfo *mode = &data->connector->modes[i]; + RRScreenSizePtr pSize; + pSize = RRRegisterSize(pScreen, + mode->hdisplay, + mode->vdisplay, + screen->width_mm, screen->height_mm); + + RRRegisterRate(pScreen, pSize, mode->vrefresh); + + if (mode->hdisplay == screen->width && + mode->vdisplay == screen->height && + mode->vrefresh == screen->rate) { + RRSetCurrentConfig(pScreen, randr, mode->vrefresh, pSize); + } + } + + return TRUE; +} + +static Bool +msRandRSetConfig(ScreenPtr pScreen, + Rotation randr, int rate, RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + Bool wasEnabled = pScreenPriv->enabled; + msScrPriv oldscr; + int oldwidth; + int oldheight; + int oldmmwidth; + int oldmmheight; + int newwidth, newheight, newmmwidth, newmmheight; + + if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { + newwidth = pSize->width; + newheight = pSize->height; + newmmwidth = pSize->mmWidth; + newmmheight = pSize->mmHeight; + } else { + newwidth = pSize->height; + newheight = pSize->width; + newmmwidth = pSize->mmHeight; + newmmheight = pSize->mmWidth; + } + + if (wasEnabled) + KdDisableScreen(pScreen); + + oldscr = *scrpriv; + + oldwidth = screen->width; + oldheight = screen->height; + oldmmwidth = pScreen->mmWidth; + oldmmheight = pScreen->mmHeight; + + /* + * Set new configuration + */ + + scrpriv->randr = KdAddRotation(screen->randr, randr); + + pScreen->width = newwidth; + pScreen->height = newheight; + pScreen->mmWidth = newmmwidth; + pScreen->mmHeight = newmmheight; + + msUnmapFramebuffer(screen); + + if (!msSetMode(pScreen, rate)) + goto bail4; + + if (!msMapFramebuffer(screen)) + goto bail4; + + KdShadowUnset(screen->pScreen); + + if (!msSetShadow(screen->pScreen)) + goto bail4; + + msSetScreenSizes(screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) ((*pScreen->GetScreenPixmap)(pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder(pScreen, scrpriv->randr); + if (wasEnabled) + KdEnableScreen(pScreen); + + return TRUE; + +bail4: + msUnmapFramebuffer(screen); + *scrpriv = oldscr; + msMapFramebuffer(screen); + pScreen->width = oldwidth; + pScreen->height = oldheight; + pScreen->mmWidth = oldmmwidth; + pScreen->mmHeight = oldmmheight; + + if (wasEnabled) + KdEnableScreen(pScreen); + return FALSE; +} + +static Bool +msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + gbm_user_data_t *data = gbm_bo_get_user_data(scrpriv->front); + + *mmWidth = screen->width_mm; + *mmHeight = screen->height_mm; + + if (screen->requested_mm) { + return TRUE; + } + + if (((int)data->connector->mmWidth > 0) && ((int)data->connector->mmHeight > 0)) { + *mmWidth = data->connector->mmWidth; + *mmWidth = data->connector->mmHeight; + return TRUE; + } + + return FALSE; +} + +static Bool msRandRInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + int mmWidth, mmHeight; + + if (!RRScreenInit(pScreen)) { + return FALSE; + } + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = msRandRGetInfo; + pScrPriv->rrSetConfig = msRandRSetConfig; + + if (msGetPhysicalScreenSizes(pScreen, &mmWidth, &mmHeight)) { + RROutputPtr pOutput; + + /* Create the output */ + RRGetInfo(pScreen, TRUE); + + pOutput = RRFirstOutput(pScreen); + if (pOutput) { + RROutputSetPhysicalSize(pOutput, + mmWidth, + mmHeight); + } + } + + return TRUE; +} + +Bool msInitScreen(ScreenPtr pScreen) +{ + pScreen->CreateColormap = fbInitializeColormap; + return TRUE; +} + +Bool msFinishInitScreen(ScreenPtr pScreen) +{ + if (!shadowSetup(pScreen)) { + return FALSE; + } + + if (!msRandRInit(pScreen)) { + return FALSE; + } + + return TRUE; +} + +static void +msFixupDamageRegion(msScrPriv *scrpriv, int w, int h, drmModeClip *clip, BoxPtr rect) +{ + Rotation randr = scrpriv->randr & (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + + switch (randr) { + case RR_Rotate_0: + clip->x1 = rect->x1; + clip->x2 = rect->x2; + clip->y1 = rect->y1; + clip->y2 = rect->y2; + break; + case RR_Rotate_90: + clip->x1 = rect->y1; + clip->y1 = w - rect->x2; + clip->x2 = rect->y2; + clip->y2 = w - rect->x1; + break; + case RR_Rotate_180: + clip->x1 = w - rect->x2; + clip->y1 = h - rect->y2; + clip->x2 = w - rect->x1; + clip->y2 = h - rect->y1; + break; + case RR_Rotate_270: + clip->x1 = h - rect->y2; + clip->y1 = rect->x1; + clip->x2 = h - rect->y1; + clip->y2 = rect->x2; + break; + default: + clip->x1 = 0; + clip->y1 = 0; + clip->x2 = w; + clip->y2 = h; + break; + } +} + +/* Heavily inspired from the Xorg modesetting driver */ +static void +msBlockHandler(void *blockData, void *timeout) +{ + ScreenPtr pScreen = blockData; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + RegionPtr dirty; + drmModeClip full_clip; + struct gbm_device *gbm; + gbm_user_data_t *data; + int fd; + uint32_t width; + uint32_t height; + unsigned num_cliprects; + + gbm = gbm_bo_get_device(priv->front); + data = gbm_bo_get_user_data(priv->front); + fd = gbm_device_get_fd(gbm); + + width = gbm_bo_get_width(priv->front); + height = gbm_bo_get_height(priv->front); + + full_clip = (drmModeClip){.x1 = 0, .y1 = 0, .x2 = width, .y2 = height,}; + + if (!priv->damage) { + goto bail; + } + + dirty = DamageRegion(priv->damage); + + num_cliprects = REGION_NUM_RECTS(dirty); + + if (num_cliprects) { + drmModeClip *clip = calloc(num_cliprects, sizeof(drmModeClip)); + BoxPtr rect = REGION_RECTS(dirty); + int ret; + + if (!clip) { + goto bail; + } + + for (int i = 0; i < num_cliprects; i++) { + msFixupDamageRegion(priv, width, height, &clip[i], &rect[i]); + } + + /* TODO query connector property to see if this is needed */ + ret = drmModeDirtyFB(fd, data->fb_id, clip, num_cliprects); + + /* if we're swamping it with work, try one at a time */ + if (ret) { + for (int i = 0; i < num_cliprects; i++) { + ret = drmModeDirtyFB(fd, data->fb_id, &clip[i], 1); + if (ret) { + break; + } + } + } + + free(clip); + + if (ret) { + goto bail; + } + } + + DamageEmpty(priv->damage); + return; + +bail: + drmModeDirtyFB(fd, data->fb_id, &full_clip, 1); + if (priv->damage) { + DamageEmpty(priv->damage); + } +} + +static void +msWakeupHandler(void *blockData, int result) +{ +} + +Bool msCreateResources(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + struct gbm_device *gbm; + gbm_user_data_t *data; + int fd; + + gbm = gbm_bo_get_device(priv->front); + data = gbm_bo_get_user_data(priv->front); + fd = gbm_device_get_fd(gbm); + + if (!msSetShadow(pScreen)) { + return FALSE; + } + + /* Damage tracking not supported/needed */ + if (drmModeDirtyFB(fd, data->fb_id, NULL, 0) && + ((errno == EINVAL) || (errno == ENOSYS))) { + return TRUE; + } + + priv->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, + pScreen, rootPixmap); + + if (priv->damage) { + DamageRegister(&rootPixmap->drawable, priv->damage); + } + + if (!RegisterBlockAndWakeupHandlers(msBlockHandler, msWakeupHandler, pScreen)) { + if (priv->damage) { + DamageUnregister(priv->damage); + DamageDestroy(priv->damage); + priv->damage = NULL; + } + return FALSE; + } + + priv->blockHandler = TRUE; + + return TRUE; +} + +void msPreserve(KdCardInfo * card) +{ +} + +Bool msEnable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + + struct gbm_device *gbm = gbm_bo_get_device(priv->front); + gbm_user_data_t *data = gbm_bo_get_user_data(priv->front); + int fd = gbm_device_get_fd(gbm); + + drmSetMaster(fd); + + if (!data->mode) { + data->mode = modesetting_find_mode(data->connector, screen->width, screen->height, screen->rate); + } + if (data->mode && drmModeSetCrtc(fd, data->crtc_id, data->fb_id, 0, 0, &data->conn_id, 1, data->mode)) { + return FALSE; + } + +#ifdef XV + KdXVEnable (pScreen); +#endif + + return TRUE; +} + +#if 0 +Bool msDPMS(ScreenPtr pScreen, int mode) +{ + KdScreenPriv(pScreen); + msPriv *priv = pScreenPriv->card->driver; + static int oldmode = -1; + + if (mode == oldmode) + return TRUE; + + /* TODO: implement dpms */ + + return FALSE; +} +#endif + +void msDisable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + + struct gbm_device *gbm = gbm_bo_get_device(priv->front); + int fd = gbm_device_get_fd(gbm); + +#ifdef XV + KdXVDisable (pScreen); +#endif + + drmDropMaster(fd); +} + +void msRestore(KdCardInfo * card) +{ +} + +void msScreenFini(KdScreenInfo * screen) +{ + msScrPriv *priv = screen->driver; + + gbm_bo_destroy(priv->front); + free(priv); + screen->driver = NULL; +} + +void msCardFini(KdCardInfo * card) +{ + msPriv *priv = card->driver; + + struct gbm_device *gbm = priv->gbm; + int fd = gbm_device_get_fd(gbm); + + gbm_device_destroy(gbm); + close(fd); + free(priv); + card->driver = NULL; +} + +#if 0 +void +msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs) +{ +} + +void +msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) +{ +} +#endif + +void +msCloseScreen(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + + if (!priv->blockHandler) { + return; + } + + RemoveBlockAndWakeupHandlers(msBlockHandler, msWakeupHandler, pScreen); + if (priv->damage) { + DamageUnregister(priv->damage); + DamageDestroy(priv->damage); + } +} diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h new file mode 100644 index 00000000000..cd7f255e268 --- /dev/null +++ b/hw/kdrive/modesetting/modesetting.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#ifndef _MODESETTING_H_ +#define _MODESETTING_H_ +#include +#include + +#include +#include +#include + +#include "kglamor.h" + +#include "randrstr.h" + +typedef struct _msPriv { + struct gbm_device *gbm; + __u16 red[256]; + __u16 green[256]; + __u16 blue[256]; +} msPriv; + +typedef struct _msScrPriv { + struct gbm_bo *front; + DamagePtr damage; + Rotation randr; + Bool blockHandler; + Bool shadow; +#ifdef GLAMOR + int dri_fd; +#endif +} msScrPriv; + +typedef struct _msScreenConf { + const char *dev_path; + Bool shadow; + KdGlamorInfo glamor_info; + const char *dri_path; +} MsScreenConf; + +extern KdCardFuncs msFuncs; + +Bool msCardInit(KdCardInfo * card); + +Bool msScreenInit(KdScreenInfo * screen); + +Bool msInitScreen(ScreenPtr pScreen); + +Bool msFinishInitScreen(ScreenPtr pScreen); + +Bool msCreateResources(ScreenPtr pScreen); + +void msPreserve(KdCardInfo * card); + +Bool msEnable(ScreenPtr pScreen); + +Bool msDPMS(ScreenPtr pScreen, int mode); + +void msDisable(ScreenPtr pScreen); + +void msRestore(KdCardInfo * card); + +void msScreenFini(KdScreenInfo * screen); + +void msCardFini(KdCardInfo * card); + +#ifdef GLAMOR +Bool msInitAccel(ScreenPtr screen); + +void msEnableAccel(ScreenPtr screen); + +void msDisableAccel(ScreenPtr screen); + +void msFiniAccel(ScreenPtr screen); +#endif + +void msCloseScreen(ScreenPtr pScreen); + +#endif /* _MODESETTING_H_ */ diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c new file mode 100644 index 00000000000..48ab8c68742 --- /dev/null +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "present.h" +#include "Xext/present/present_priv.h" /* extern uint32_t FakeScreenFps; */ + +#include "modesetting.h" +#include "kglamor.h" + +#include "glamor.h" + +#include + +#include + +Bool +msInitAccel(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + msPriv *priv = screen->card->driver; + MsScreenConf *config = screen->card->closure; + int caps = GLAMOR_EGL_CAP_NONE; + int has_dri3; + + if (config->dri_path) { + scrpriv->dri_fd = open(config->dri_path, O_RDWR); + if (scrpriv->dri_fd >= 0) { +#ifdef WITH_LIBDRM + drmDropMaster(scrpriv->dri_fd); +#endif + } else { + LogMessage(X_WARNING, "Xmodesetting(%d): Could not open %s: %s\n", pScreen->myNum, config->dri_path, strerror(errno)); + } + } else { + scrpriv->dri_fd = dup(gbm_device_get_fd(priv->gbm)); + } + + config->glamor_info.dri_fd = scrpriv->dri_fd; + + if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { + if (scrpriv->dri_fd >= 0) { + close(scrpriv->dri_fd); + scrpriv->dri_fd = -1; + config->glamor_info.dri_fd = -1; + } + return FALSE; + } + +#define GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT (GLAMOR_EGL_CAP_DRI3_IMPORT | GLAMOR_EGL_CAP_DRI3_EXPORT) + has_dri3 = (caps & GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT) == GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT; + LogMessage(X_INFO, "Xmodesetting(%d): DRI3 %s initialized\n", pScreen->myNum, has_dri3 ? "" : "not"); + +#if 0 /* Not yet implemented */ + LogMessage(X_INFO, "Xmodesetting(%d): DRI3 explicit sync %s\n", pScreen->myNum, + (caps & GLAMOR_EGL_CAP_DRI3_SYNCOBJ) ? + "available" : "unavailable"); +#endif + + if (scrpriv->dri_fd >= 0) { + /* + * X clients use present to try to synchronize with the screen + * If no global fake rate was requested and the screen's rate is sane, + * use that instead of the 60 fps default + */ + if (!FakeScreenFps && (screen->rate >= 60) && (screen->rate <= 600)) { + FakeScreenFps = screen->rate; + present_screen_init(pScreen, NULL); + FakeScreenFps = 0; + } + } + + return TRUE; +} + +void +msEnableAccel(ScreenPtr pScreen) +{ + KdGlamorEnable(pScreen); +} + +void +msDisableAccel(ScreenPtr pScreen) +{ + KdGlamorDisable(pScreen); +} + +void +msFiniAccel(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + + KdGlamorFini(pScreen); + + if (scrpriv->dri_fd >= 0) { + close(scrpriv->dri_fd); + } +} diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c new file mode 100644 index 00000000000..89a3f04e1e4 --- /dev/null +++ b/hw/kdrive/modesetting/msinit.c @@ -0,0 +1,216 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#ifdef KDRIVE_LINUX +#include "klinux.h" +#else +#include "kstub.h" +#endif + +#include "modesetting.h" + +#include "dix/dix_priv.h" +#include "os/cmdline.h" +#include "os/ddx_priv.h" +#include "os/log_priv.h" + +#include + +static MsScreenConf *msCurrScreen = NULL; + +static const MsScreenConf msDefaultConfig = { + .dev_path = NULL, + .shadow = TRUE, + }; + +static void msLogScreenInfo(const MsScreenConf *config, int screen_num); + +static void +msLogInit(void) +{ + KdCardInfo *curr_card = kdCardInfo; + char *log_file = NULL; + const char *display_name = display ? display : ""; + if (asprintf(&log_file, DEFAULT_LOGDIR "/Xmodesetting.%s.log", display_name) < 0) { + LogInit(DEFAULT_LOGDIR "/Xkdrive.log", ".old"); + } else { + LogInit(log_file, ".old"); + free(log_file); + } + + LogMessage(X_INFO, "Xmodesetting: X11 server for KMS devices\n"); + LogMessage(X_INFO, "\n"); + LogMessage(X_INFO, "Xmodesetting: Configured screens info:\n"); + LogMessage(X_INFO, "\n"); + + if (curr_card) { + while(curr_card) { + msLogScreenInfo(curr_card->closure, curr_card->mynum); + curr_card = curr_card->next; + } + } else { + MsScreenConf msDummyConfig = msDefaultConfig; + msDummyConfig.glamor_info = kdGlamorDefault; + msLogScreenInfo(&msDummyConfig, 0); + } +} + +void +InitCard(char *name) +{ + msCurrScreen = XNFalloc(sizeof(*msCurrScreen)); + *msCurrScreen = msDefaultConfig; + msCurrScreen->glamor_info = kdGlamorDefault; + KdCardInfoAdd(&msFuncs, msCurrScreen); +} + +static void +msLogScreenInfo(const MsScreenConf *config, int screen_num) +{ + LogMessage(X_INFO, "Xmodesetting(%d): Screen %d:\n", screen_num, screen_num); + + LogMessage(X_INFO, "Xmodesetting(%d): kms device: %s\n", screen_num, + config->dev_path ? config->dev_path : "not passed"); + LogMessage(X_INFO, "Xmodesetting(%d): ShadowFB %s\n", screen_num, + config->shadow ? "enabled" : "disabled"); + + LogMessage(X_INFO, "Xmodesetting(%d): glvnd library: %s\n", screen_num, + config->glamor_info.glvnd ? config->glamor_info.glvnd : "not passed"); + + LogMessage(X_INFO, "Xmodesetting(%d): dri device: %s\n", screen_num, + config->dri_path ? config->dri_path : "none"); + + LogMessage(X_INFO, "Xmodesetting(%d): glamor OpenGL contexts %s\n", screen_num, + !config->glamor_info.force_es ? "allowed" : "forbidden"); + LogMessage(X_INFO, "Xmodesetting(%d): glamor GLES contexts %s\n", screen_num, + !config->glamor_info.force_gl ? "allowed" : "forbidden"); + + LogMessage(X_INFO, "Xmodesetting(%d): glamor render acceleration %s\n", screen_num, + !config->glamor_info.no_render_accel ? "enabled" : "disabled"); + LogMessage(X_INFO, "Xmodesetting(%d): glamor render acceleration %s on software renderers\n", screen_num, + config->glamor_info.force_render_accel ? "allowed" : "forbidden"); + LogMessage(X_INFO, "Xmodesetting(%d): glamor is %s libgbm \n", screen_num, + config->glamor_info.use_gbm ? "allowed to use" : "forbidden from using"); + + LogMessage(X_INFO, "Xmodesetting(%d): glamor X-Video support %s\n", screen_num, + config->glamor_info.use_xv ? "allowed" : "forbidden"); + LogMessage(X_INFO, "\n"); +} + +#if INPUTTHREAD +/** This function is called in Xserver/os/inputthread.c when starting + the input thread. */ +void +ddxInputThreadInit(void) +{ +} +#endif + +void +InitOutput(int argc, char **argv) +{ + KdInitOutput(argc, argv); +} + +void +InitInput(int argc, char **argv) +{ +#ifdef KDRIVE_LINUX + LinuxAddInputDrivers(); +#else + StubAddInputDrivers(); +#endif + KdInitInput(); +} + +void +CloseInput(void) +{ + KdCloseInput(); +} + +void +ddxUseMsg(void) +{ + KdGlamorUseMsg(); + ErrorF("\nXmodesetting Device Usage:\n"); + ErrorF + ("-dev KMS device to use. Defaults to /dev/dri/card0\n"); + ErrorF + ("-noshadow Disable the ShadowFB layer if possible\n"); + ErrorF("\n"); +} + +int +ddxProcessArgument(int argc, char **argv, int i) +{ + int glamor_arg; + + KdEnsureCard(argc, argv, i, !msCurrScreen); + + if (!strcmp(argv[i], "-dev")) { + if ((i + 1 < argc) && (argv[i + 1][0] != '-')) { + msCurrScreen->dev_path = argv[i + 1]; + return 2; + } + UseMsg(); + exit(1); + } + + if (!strcmp(argv[i], "-noshadow")) { + msCurrScreen->shadow = FALSE; + return 1; + } + + glamor_arg = KdGlamorParse(&msCurrScreen->glamor_info, &msCurrScreen->dri_path, argc, argv, i); + if (glamor_arg) { + return glamor_arg; + } + + return KdProcessArgument(argc, argv, i); +} + +void ddxInit(void) +{ + msLogInit(); +#ifdef KDRIVE_LINUX + KdOsInit(&LinuxFuncs); +#else + KdOsInit(&StubOsFuncs); +#endif +} + +KdCardFuncs msFuncs = { + .cardinit = msCardInit, + .scrinit = msScreenInit, + .initScreen = msInitScreen, + .finishInitScreen = msFinishInitScreen, + .createRes = msCreateResources, + .preserve = msPreserve, + .enable = msEnable, + .dpms = NULL, /* TODO: implement */ + .disable = msDisable, + .restore = msRestore, + .scrfini = msScreenFini, + .cardfini = msCardFini, + + /* no cursor funcs */ + +#ifdef GLAMOR + .initAccel = msInitAccel, + .enableAccel = msEnableAccel, + .disableAccel = msDisableAccel, + .finiAccel = msFiniAccel, +#endif + +#if 0 + .getColors = msGetColors, + .putColors = msPutColors, +#endif + + .closeScreen = msCloseScreen, +}; diff --git a/meson.build b/meson.build index 55a87f32bc1..e2b9857af70 100644 --- a/meson.build +++ b/meson.build @@ -288,13 +288,16 @@ build_xfake = get_option('xfake') build_xfbdev = get_option('xfbdev') +build_xmodesetting = get_option('xmodesetting') + build_xserver = (build_xorg or build_xnest or build_xvfb or build_xquartz or build_xephyr or build_xfake or - build_xfbdev) + build_xfbdev or + build_xmodesetting) summary({ 'Xorg': build_xorg, @@ -305,6 +308,7 @@ summary({ 'Xephyr': build_xephyr, 'Xfake': build_xfake, 'Xfbdev': build_xfbdev, + 'Xmodesetting': build_xmodesetting, }, section: 'DDX', bool_yn: true, diff --git a/meson_options.txt b/meson_options.txt index a011981ded2..e6966273c81 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -8,6 +8,8 @@ option('xfake', type: 'boolean', value: false, description: 'Enable the kdrive fake X server') option('xfbdev', type: 'boolean', value: false, description: 'Enable the kdrive framebuffer device X server') +option('xmodesetting', type: 'boolean', value: false, + description: 'Enable the kdrive KMS device X server') option('glamor', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', description: 'Enable glamor (default yes for Xorg builds)') option('xnest', type: 'combo', choices: ['true', 'false', 'auto'], value: 'auto', From c208d732df9d0b21318f64dfd78005d6b766cfae Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sun, 13 Sep 2026 20:38:48 +0300 Subject: [PATCH 03/47] kdrive/glamor: Replace `use_xv` by `no_xv` Make the default FALSE Signed-off-by: stefan11111 --- hw/kdrive/fbdev/fbinit.c | 2 +- hw/kdrive/modesetting/msinit.c | 2 +- hw/kdrive/src/kglamor.c | 6 +++--- hw/kdrive/src/kglamor.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/kdrive/fbdev/fbinit.c b/hw/kdrive/fbdev/fbinit.c index d9068eb53fe..a0a9bc4f3d0 100644 --- a/hw/kdrive/fbdev/fbinit.c +++ b/hw/kdrive/fbdev/fbinit.c @@ -108,7 +108,7 @@ fbdevLogScreenInfo(const FbScreenConf *config, int screen_num) config->glamor_info.use_gbm ? "allowed to use" : "forbidden from using"); LogMessage(X_INFO, "Xfbdev(%d): glamor X-Video support %s\n", screen_num, - config->glamor_info.use_xv ? "allowed" : "forbidden"); + config->glamor_info.no_xv ? "allowed" : "forbidden"); LogMessage(X_INFO, "\n"); } diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 89a3f04e1e4..90a2c14c3d2 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -97,7 +97,7 @@ msLogScreenInfo(const MsScreenConf *config, int screen_num) config->glamor_info.use_gbm ? "allowed to use" : "forbidden from using"); LogMessage(X_INFO, "Xmodesetting(%d): glamor X-Video support %s\n", screen_num, - config->glamor_info.use_xv ? "allowed" : "forbidden"); + config->glamor_info.no_xv ? "allowed" : "forbidden"); LogMessage(X_INFO, "\n"); } diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index db4c51f3b3f..1ab06f3e012 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -31,7 +31,7 @@ const KdGlamorInfo kdGlamorDefault = { .direct_dri3 = FALSE, .force_gl = FALSE, .force_es = FALSE, - .use_xv = TRUE, + .no_xv = FALSE, .no_render_accel = FALSE, .force_render_accel = FALSE, }; @@ -89,7 +89,7 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps) } #ifdef XV - if (info->use_xv) { + if (!info->no_xv) { kd_glamor_xv_init(pScreen); } #endif @@ -168,7 +168,7 @@ KdGlamorParse(KdGlamorInfo *info, const char **dri_path, int argc, char **argv, } if (!strcmp(argv[i], "-noxv")) { - info->use_xv = FALSE; + info->no_xv = TRUE; return 1; } diff --git a/hw/kdrive/src/kglamor.h b/hw/kdrive/src/kglamor.h index 85ae73bb1c8..10abdaa1eee 100644 --- a/hw/kdrive/src/kglamor.h +++ b/hw/kdrive/src/kglamor.h @@ -18,7 +18,7 @@ typedef struct { Bool force_es; /* If glamor should only create gles contexts */ /* Handled by KdGlamorInit */ - Bool use_xv; /* Enable X-Video support */ + Bool no_xv; /* Disable X-Video support */ Bool no_render_accel; /* Disable render acceleration */ Bool force_render_accel; /* Enable render acceleration on top of sw renderers */ } KdGlamorInfo; From 5a1a01932887c30fc1c17a0dedd6e57892894224 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 00:30:18 +0300 Subject: [PATCH 04/47] kdrive: Move more glamor-related stuff into kglamor Signed-off-by: stefan11111 --- hw/kdrive/fake/fake.h | 1 - hw/kdrive/fake/fake_glamor.c | 61 +---------------- hw/kdrive/fake/fakeinit.c | 4 +- hw/kdrive/fake/meson.build | 5 +- hw/kdrive/fbdev/fb_glamor.c | 62 +---------------- hw/kdrive/fbdev/fbdev.h | 1 - hw/kdrive/fbdev/fbinit.c | 7 +- hw/kdrive/fbdev/meson.build | 5 +- hw/kdrive/modesetting/meson.build | 3 - hw/kdrive/modesetting/ms_glamor.c | 55 ++------------- hw/kdrive/modesetting/msinit.c | 10 +-- hw/kdrive/src/kglamor.c | 110 ++++++++++++++++++++++++------ hw/kdrive/src/kglamor.h | 11 ++- hw/kdrive/src/meson.build | 2 +- 14 files changed, 119 insertions(+), 218 deletions(-) diff --git a/hw/kdrive/fake/fake.h b/hw/kdrive/fake/fake.h index 539a0eeaf95..7bee219e0e1 100644 --- a/hw/kdrive/fake/fake.h +++ b/hw/kdrive/fake/fake.h @@ -46,7 +46,6 @@ typedef struct _fakeScrPriv { typedef struct _fakeScreenConf { int shadow; KdGlamorInfo glamor_info; - const char *dri_path; } FakeScreenConf; extern KdCardFuncs fakeFuncs; diff --git a/hw/kdrive/fake/fake_glamor.c b/hw/kdrive/fake/fake_glamor.c index feb6f3a2442..eaba8fd5410 100644 --- a/hw/kdrive/fake/fake_glamor.c +++ b/hw/kdrive/fake/fake_glamor.c @@ -5,20 +5,9 @@ #include -#include "present.h" -#include "Xext/present/present_priv.h" /* extern uint32_t FakeScreenFps; */ - #include "fake.h" #include "kglamor.h" -#include "glamor.h" - -#ifdef WITH_LIBDRM -#include -#endif - -#include - Bool fakeInitAccel(ScreenPtr pScreen) { @@ -26,56 +15,8 @@ fakeInitAccel(ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; FakeScrPriv *scrpriv = screen->driver; FakeScreenConf *config = screen->card->closure; - int caps = GLAMOR_EGL_CAP_NONE; - int has_dri3; - - if (config->dri_path) { - scrpriv->dri_fd = open(config->dri_path, O_RDWR); - if (scrpriv->dri_fd >= 0) { -#ifdef WITH_LIBDRM - drmDropMaster(scrpriv->dri_fd); -#endif - } else { - LogMessage(X_WARNING, "Xfake(%d): Could not open %s: %s\n", pScreen->myNum, config->dri_path, strerror(errno)); - } - } else { - scrpriv->dri_fd = -1; - } - - config->glamor_info.dri_fd = scrpriv->dri_fd; - - if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { - if (scrpriv->dri_fd >= 0) { - close(scrpriv->dri_fd); - scrpriv->dri_fd = -1; - config->glamor_info.dri_fd = -1; - } - return FALSE; - } - -#define GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT (GLAMOR_EGL_CAP_DRI3_IMPORT | GLAMOR_EGL_CAP_DRI3_EXPORT) - has_dri3 = (caps & GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT) == GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT; - LogMessage(X_INFO, "Xfake(%d): DRI3 %s initialized\n", pScreen->myNum, has_dri3 ? "" : "not"); - -#if 0 /* Not yet implemented */ - LogMessage(X_INFO, "Xfake(%d): DRI3 explicit sync %s\n", pScreen->myNum, - (caps & GLAMOR_EGL_CAP_DRI3_SYNCOBJ) ? - "available" : "unavailable"); -#endif - - if (scrpriv->dri_fd >= 0) { - /* - * X clients use present to try to synchronize with the screen - * If no global fake rate was requested, use the highest value dix accepts (600) - */ - if (!FakeScreenFps) { - FakeScreenFps = 600; - present_screen_init(pScreen, NULL); - FakeScreenFps = 0; - } - } - return TRUE; + return KdGlamorInit(pScreen, &config->glamor_info, NULL, &scrpriv->dri_fd); } void diff --git a/hw/kdrive/fake/fakeinit.c b/hw/kdrive/fake/fakeinit.c index 1216d05a424..dad34178217 100644 --- a/hw/kdrive/fake/fakeinit.c +++ b/hw/kdrive/fake/fakeinit.c @@ -32,6 +32,7 @@ static FakeScreenConf *fakeCurrScreen = NULL; static const FakeScreenConf fakeDefaultConfig = { .shadow = -1, + .glamor_info = {.fake_rate = 600, .drop_master = TRUE,}, }; void @@ -39,7 +40,6 @@ InitCard(char *name) { fakeCurrScreen = XNFalloc(sizeof(*fakeCurrScreen)); *fakeCurrScreen = fakeDefaultConfig; - fakeCurrScreen->glamor_info = kdGlamorDefault; KdCardInfoAdd(&fakeFuncs, fakeCurrScreen); } @@ -100,7 +100,7 @@ ddxProcessArgument(int argc, char **argv, int i) return 1; } - glamor_arg = KdGlamorParse(&fakeCurrScreen->glamor_info, &fakeCurrScreen->dri_path, argc, argv, i); + glamor_arg = KdGlamorParse(&fakeCurrScreen->glamor_info, argc, argv, i); if (glamor_arg) { return glamor_arg; } diff --git a/hw/kdrive/fake/meson.build b/hw/kdrive/fake/meson.build index 2a8d7a7ac8a..dacf0c15b41 100644 --- a/hw/kdrive/fake/meson.build +++ b/hw/kdrive/fake/meson.build @@ -4,10 +4,8 @@ srcs = [ '../../stubs/ddxBeforeReset.c', ] -fake_glamor = [] if build_glamor srcs += 'fake_glamor.c' - fake_glamor += glamor endif xfake_server = executable( @@ -18,10 +16,9 @@ xfake_server = executable( include_directories('../src'), include_directories('../os/stub'), ], - dependencies: [ common_dep, libdrm_dep ], + dependencies: common_dep, link_with: [ libxserver_main, - fake_glamor, kdrive, stub, libxserver_fb, diff --git a/hw/kdrive/fbdev/fb_glamor.c b/hw/kdrive/fbdev/fb_glamor.c index f84c471151b..2a7b971deb4 100644 --- a/hw/kdrive/fbdev/fb_glamor.c +++ b/hw/kdrive/fbdev/fb_glamor.c @@ -5,20 +5,9 @@ #include -#include "present.h" -#include "Xext/present/present_priv.h" /* extern uint32_t FakeScreenFps; */ - #include "fbdev.h" #include "kglamor.h" -#include "glamor.h" - -#ifdef WITH_LIBDRM -#include -#endif - -#include - Bool fbdevInitAccel(ScreenPtr pScreen) { @@ -26,57 +15,12 @@ fbdevInitAccel(ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; FbdevScrPriv *scrpriv = screen->driver; FbScreenConf *config = screen->card->closure; - int caps = GLAMOR_EGL_CAP_NONE; - int has_dri3; - - if (config->dri_path) { - scrpriv->dri_fd = open(config->dri_path, O_RDWR); - if (scrpriv->dri_fd >= 0) { -#ifdef WITH_LIBDRM - drmDropMaster(scrpriv->dri_fd); -#endif - } else { - LogMessage(X_WARNING, "Xfbdev(%d): Could not open %s: %s\n", pScreen->myNum, config->dri_path, strerror(errno)); - } - } else { - scrpriv->dri_fd = -1; - } - config->glamor_info.dri_fd = scrpriv->dri_fd; - - if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { - if (scrpriv->dri_fd >= 0) { - close(scrpriv->dri_fd); - scrpriv->dri_fd = -1; - config->glamor_info.dri_fd = -1; - } - return FALSE; - } - -#define GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT (GLAMOR_EGL_CAP_DRI3_IMPORT | GLAMOR_EGL_CAP_DRI3_EXPORT) - has_dri3 = (caps & GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT) == GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT; - LogMessage(X_INFO, "Xfbdev(%d): DRI3 %s initialized\n", pScreen->myNum, has_dri3 ? "" : "not"); - -#if 0 /* Not yet implemented */ - LogMessage(X_INFO, "Xfbdev(%d): DRI3 explicit sync %s\n", pScreen->myNum, - (caps & GLAMOR_EGL_CAP_DRI3_SYNCOBJ) ? - "available" : "unavailable"); -#endif - - if (scrpriv->dri_fd >= 0) { - /* - * X clients use present to try to synchronize with the screen - * If no global fake rate was requested and the screen's rate is sane, - * use that instead of the 60 fps default - */ - if (!FakeScreenFps && (screen->rate >= 60) && (screen->rate <= 600)) { - FakeScreenFps = screen->rate; - present_screen_init(pScreen, NULL); - FakeScreenFps = 0; - } + if (screen->rate > 60) { + config->glamor_info.fake_rate = screen->rate; } - return TRUE; + return KdGlamorInit(pScreen, &config->glamor_info, NULL, &scrpriv->dri_fd); } void diff --git a/hw/kdrive/fbdev/fbdev.h b/hw/kdrive/fbdev/fbdev.h index 6313ced72c6..c044bf5138d 100644 --- a/hw/kdrive/fbdev/fbdev.h +++ b/hw/kdrive/fbdev/fbdev.h @@ -57,7 +57,6 @@ typedef struct _fbScreenConf { const char *fb_path; Bool shadow; KdGlamorInfo glamor_info; - const char *dri_path; } FbScreenConf; extern KdCardFuncs fbdevFuncs; diff --git a/hw/kdrive/fbdev/fbinit.c b/hw/kdrive/fbdev/fbinit.c index a0a9bc4f3d0..97a4d676b48 100644 --- a/hw/kdrive/fbdev/fbinit.c +++ b/hw/kdrive/fbdev/fbinit.c @@ -36,6 +36,7 @@ static FbScreenConf *fbCurrScreen = NULL; static const FbScreenConf fbDefaultConfig = { .fb_path = NULL, .shadow = TRUE, + .glamor_info = {.drop_master = TRUE,}, }; static void fbdevLogScreenInfo(const FbScreenConf *config, int screen_num); @@ -65,7 +66,6 @@ FbdevLogInit(void) } } else { FbScreenConf fbDummyConfig = fbDefaultConfig; - fbDummyConfig.glamor_info = kdGlamorDefault; fbdevLogScreenInfo(&fbDummyConfig, 0); } } @@ -75,7 +75,6 @@ InitCard(char *name) { fbCurrScreen = XNFalloc(sizeof(*fbCurrScreen)); *fbCurrScreen = fbDefaultConfig; - fbCurrScreen->glamor_info = kdGlamorDefault; KdCardInfoAdd(&fbdevFuncs, fbCurrScreen); } @@ -93,7 +92,7 @@ fbdevLogScreenInfo(const FbScreenConf *config, int screen_num) config->glamor_info.glvnd ? config->glamor_info.glvnd : "not passed"); LogMessage(X_INFO, "Xfbdev(%d): dri device: %s\n", screen_num, - config->dri_path ? config->dri_path : "none"); + config->glamor_info.dri_path ? config->glamor_info.dri_path : "none"); LogMessage(X_INFO, "Xfbdev(%d): glamor OpenGL contexts %s\n", screen_num, !config->glamor_info.force_es ? "allowed" : "forbidden"); @@ -173,7 +172,7 @@ ddxProcessArgument(int argc, char **argv, int i) return 1; } - glamor_arg = KdGlamorParse(&fbCurrScreen->glamor_info, &fbCurrScreen->dri_path, argc, argv, i); + glamor_arg = KdGlamorParse(&fbCurrScreen->glamor_info, argc, argv, i); if (glamor_arg) { return glamor_arg; } diff --git a/hw/kdrive/fbdev/meson.build b/hw/kdrive/fbdev/meson.build index e6940396f25..e059a3e7e8e 100644 --- a/hw/kdrive/fbdev/meson.build +++ b/hw/kdrive/fbdev/meson.build @@ -4,10 +4,8 @@ srcs = [ '../../stubs/ddxBeforeReset.c', ] -fbdev_glamor = [] if build_glamor srcs += 'fb_glamor.c' - fbdev_glamor += glamor endif xfbdev_server = executable( @@ -18,10 +16,9 @@ xfbdev_server = executable( include_directories('../src'), include_directories('../os/linux'), ], - dependencies: [ common_dep, libdrm_dep ], + dependencies: common_dep, link_with: [ libxserver_main, - fbdev_glamor, kdrive, linux, libxserver_fb, diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index 3e336460fdd..e6c2e35da50 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -4,10 +4,8 @@ srcs = [ '../../stubs/ddxBeforeReset.c', ] -ms_glamor = [] if build_glamor srcs += 'ms_glamor.c' - ms_glamor += glamor endif xmodesetting_server = executable( @@ -22,7 +20,6 @@ xmodesetting_server = executable( dependencies: [ common_dep, libdrm_dep, gbm_dep ], link_with: [ libxserver_main, - ms_glamor, kdrive, linux, libxserver_fb, diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 48ab8c68742..d2cecebdd20 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -5,75 +5,32 @@ #include -#include "present.h" -#include "Xext/present/present_priv.h" /* extern uint32_t FakeScreenFps; */ - #include "modesetting.h" #include "kglamor.h" #include "glamor.h" -#include - -#include - Bool msInitAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; msScrPriv *scrpriv = screen->driver; - msPriv *priv = screen->card->driver; MsScreenConf *config = screen->card->closure; int caps = GLAMOR_EGL_CAP_NONE; - int has_dri3; - if (config->dri_path) { - scrpriv->dri_fd = open(config->dri_path, O_RDWR); - if (scrpriv->dri_fd >= 0) { -#ifdef WITH_LIBDRM - drmDropMaster(scrpriv->dri_fd); -#endif - } else { - LogMessage(X_WARNING, "Xmodesetting(%d): Could not open %s: %s\n", pScreen->myNum, config->dri_path, strerror(errno)); - } - } else { - scrpriv->dri_fd = dup(gbm_device_get_fd(priv->gbm)); + if (screen->rate > 60) { + config->glamor_info.fake_rate = screen->rate; } - config->glamor_info.dri_fd = scrpriv->dri_fd; - - if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { - if (scrpriv->dri_fd >= 0) { - close(scrpriv->dri_fd); - scrpriv->dri_fd = -1; - config->glamor_info.dri_fd = -1; - } + if (!KdGlamorInit(pScreen, &config->glamor_info, &caps, &scrpriv->dri_fd)) { return FALSE; } -#define GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT (GLAMOR_EGL_CAP_DRI3_IMPORT | GLAMOR_EGL_CAP_DRI3_EXPORT) - has_dri3 = (caps & GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT) == GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT; - LogMessage(X_INFO, "Xmodesetting(%d): DRI3 %s initialized\n", pScreen->myNum, has_dri3 ? "" : "not"); - -#if 0 /* Not yet implemented */ - LogMessage(X_INFO, "Xmodesetting(%d): DRI3 explicit sync %s\n", pScreen->myNum, - (caps & GLAMOR_EGL_CAP_DRI3_SYNCOBJ) ? - "available" : "unavailable"); -#endif - - if (scrpriv->dri_fd >= 0) { - /* - * X clients use present to try to synchronize with the screen - * If no global fake rate was requested and the screen's rate is sane, - * use that instead of the 60 fps default - */ - if (!FakeScreenFps && (screen->rate >= 60) && (screen->rate <= 600)) { - FakeScreenFps = screen->rate; - present_screen_init(pScreen, NULL); - FakeScreenFps = 0; - } +#if 0 + if (caps & GLAMOR_EGL_CAP_TEXTURE_GBM_BO) { } +#endif return TRUE; } diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 90a2c14c3d2..6a040b55e04 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -25,6 +25,7 @@ static MsScreenConf *msCurrScreen = NULL; static const MsScreenConf msDefaultConfig = { .dev_path = NULL, .shadow = TRUE, + .glamor_info = {.use_gbm = TRUE,}, }; static void msLogScreenInfo(const MsScreenConf *config, int screen_num); @@ -54,7 +55,6 @@ msLogInit(void) } } else { MsScreenConf msDummyConfig = msDefaultConfig; - msDummyConfig.glamor_info = kdGlamorDefault; msLogScreenInfo(&msDummyConfig, 0); } } @@ -64,7 +64,6 @@ InitCard(char *name) { msCurrScreen = XNFalloc(sizeof(*msCurrScreen)); *msCurrScreen = msDefaultConfig; - msCurrScreen->glamor_info = kdGlamorDefault; KdCardInfoAdd(&msFuncs, msCurrScreen); } @@ -82,7 +81,7 @@ msLogScreenInfo(const MsScreenConf *config, int screen_num) config->glamor_info.glvnd ? config->glamor_info.glvnd : "not passed"); LogMessage(X_INFO, "Xmodesetting(%d): dri device: %s\n", screen_num, - config->dri_path ? config->dri_path : "none"); + config->glamor_info.dri_path ? config->glamor_info.dri_path : "none"); LogMessage(X_INFO, "Xmodesetting(%d): glamor OpenGL contexts %s\n", screen_num, !config->glamor_info.force_es ? "allowed" : "forbidden"); @@ -155,6 +154,9 @@ ddxProcessArgument(int argc, char **argv, int i) if (!strcmp(argv[i], "-dev")) { if ((i + 1 < argc) && (argv[i + 1][0] != '-')) { msCurrScreen->dev_path = argv[i + 1]; + if (!msCurrScreen->glamor_info.dri_path) { + msCurrScreen->glamor_info.dri_path = msCurrScreen->dev_path; + } return 2; } UseMsg(); @@ -166,7 +168,7 @@ ddxProcessArgument(int argc, char **argv, int i) return 1; } - glamor_arg = KdGlamorParse(&msCurrScreen->glamor_info, &msCurrScreen->dri_path, argc, argv, i); + glamor_arg = KdGlamorParse(&msCurrScreen->glamor_info, argc, argv, i); if (glamor_arg) { return glamor_arg; } diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index 1ab06f3e012..d414fc62e98 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -11,6 +11,9 @@ #include "os/cmdline.h" /* UseMsg() */ +#include "present.h" +#include "Xext/present/present_priv.h" /* extern uint32_t FakeScreenFps; */ + #ifdef GLAMOR #include "glamor.h" #include "glamor_egl.h" @@ -24,23 +27,49 @@ #include -const KdGlamorInfo kdGlamorDefault = { - .glvnd = NULL, - .dri_fd = -1, - .use_gbm = FALSE, - .direct_dri3 = FALSE, - .force_gl = FALSE, - .force_es = FALSE, - .no_xv = FALSE, - .no_render_accel = FALSE, - .force_render_accel = FALSE, - }; +#ifdef WITH_LIBDRM +#include +#else +#ifdef GLAMOR + +#ifdef KDRIVE_LINUX +#include +#endif + +#ifndef DRM_IOCTL_DROP_MASTER +#define DRM_IOCTL_DROP_MASTER 0x641f +#endif + +static int +drmIoctl(int fd, unsigned long request, void *arg) +{ +#ifdef KDRIVE_LINUX + int ret; + + do { + ret = ioctl(fd, request, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + return ret; +#else + return -ENOSYS; +#endif +} + +static int drmDropMaster(int fd) +{ + return drmIoctl(fd, DRM_IOCTL_DROP_MASTER, NULL); +} +#endif +#endif #ifdef GLAMOR Bool -KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps) +KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd) { int flags = GLAMOR_USE_EGL_SCREEN; + int has_dri3; + int _caps; + int _dri_fd; glamor_egl_conf_t glamor_egl_conf = { .server_private = NULL, /* only for xf86 */ @@ -48,7 +77,7 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps) .glamor_egl_priv = NULL, /* only for xf86 */ .GLAMOR_EGL_PRIV_PROC = NULL, /* only for xf86 */ .glvnd_vendor = info->glvnd, - .fd = info->dri_fd, + .fd = -1, .gbm_forbidden = !info->use_gbm, .direct_dri3_only = info->direct_dri3, .auto_dri = FALSE, /* deprecated */ @@ -61,10 +90,31 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps) .force_es = info->force_es, }; - if (caps) { - *caps = GLAMOR_EGL_CAP_NONE; + if (!caps) { + caps = &_caps; + } + + *caps = GLAMOR_EGL_CAP_NONE; + + if (!dri_fd) { + dri_fd = &_dri_fd; + } + + if (info->dri_path) { + *dri_fd = open(info->dri_path, O_RDWR); + if (*dri_fd < 0) { + LogMessage(X_WARNING, "KGlamor(%d): Could not open %s: %s\n", pScreen->myNum, info->dri_path, strerror(errno)); + } + } else { + *dri_fd = -1; + } + + if ((*dri_fd >= 0) && info->drop_master) { + drmDropMaster(*dri_fd); } + glamor_egl_conf.fd = *dri_fd; + if (!glamor_egl_init_internal(&glamor_egl_conf, caps)) { return FALSE; } @@ -80,7 +130,7 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps) } } - if (info->dri_fd < 0) { + if (*dri_fd < 0) { flags |= GLAMOR_NO_DRI3; } @@ -88,12 +138,34 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps) return FALSE; } +#define GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT (GLAMOR_EGL_CAP_DRI3_IMPORT | GLAMOR_EGL_CAP_DRI3_EXPORT) + has_dri3 = (*caps & GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT) == GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT; + LogMessage(X_INFO, "KGlamor(%d): DRI3 %s initialized\n", pScreen->myNum, has_dri3 ? "" : "not"); + +#if 0 /* Not yet implemented */ + LogMessage(X_INFO, "KGlamor(%d): DRI3 explicit sync %s\n", pScreen->myNum, + (*caps & GLAMOR_EGL_CAP_DRI3_SYNCOBJ) ? + "available" : "unavailable"); +#endif + #ifdef XV if (!info->no_xv) { kd_glamor_xv_init(pScreen); } #endif + if (info->fake_rate && (*dri_fd >= 0)) { + /* + * X clients use present to try to synchronize with the screen + * If no global fake rate was requested and a per-screen rate was requested, use that + */ + if (!FakeScreenFps) { + FakeScreenFps = info->fake_rate; + present_screen_init(pScreen, NULL); + FakeScreenFps = 0; + } + } + return TRUE; } @@ -115,7 +187,7 @@ KdGlamorFini(ScreenPtr pScreen) #endif int -KdGlamorParse(KdGlamorInfo *info, const char **dri_path, int argc, char **argv, int i) +KdGlamorParse(KdGlamorInfo *info, int argc, char **argv, int i) { if (!strcmp(argv[i], "-glamor")) { info->force_render_accel = TRUE; @@ -148,9 +220,7 @@ KdGlamorParse(KdGlamorInfo *info, const char **dri_path, int argc, char **argv, if (!strcmp(argv[i], "-dri")) { if ((i + 1 < argc) && (argv[i + 1][0] != '-')) { - if (dri_path) { - *dri_path = argv[i + 1]; - } + info->dri_path = argv[i + 1]; return 2; } UseMsg(); diff --git a/hw/kdrive/src/kglamor.h b/hw/kdrive/src/kglamor.h index 10abdaa1eee..5bb8994fbee 100644 --- a/hw/kdrive/src/kglamor.h +++ b/hw/kdrive/src/kglamor.h @@ -11,29 +11,28 @@ typedef struct { /* Passed to glamor_egl */ const char* glvnd; /* glvnd vendor library or driver name */ - int dri_fd; /* /dev/dri/[cardxx|renderDxxx] */ + const char* dri_path; /* /dev/dri/[cardxx|renderDxxx] */ Bool use_gbm; /* If glamor should try to use libgbm */ Bool direct_dri3; /* If glamor should only use the direct DRI3 implementation */ Bool force_gl; /* If glamor should only create desktop gl contexts */ Bool force_es; /* If glamor should only create gles contexts */ /* Handled by KdGlamorInit */ + int fake_rate; /* If a fake refresh rate should be used by present */ + Bool drop_master; /* If KdGlamorInit should call drmDropMaster on the dri fd */ Bool no_xv; /* Disable X-Video support */ Bool no_render_accel; /* Disable render acceleration */ Bool force_render_accel; /* Enable render acceleration on top of sw renderers */ } KdGlamorInfo; -/* A sane default config for KdGlamorInit */ -extern const KdGlamorInfo kdGlamorDefault; - #ifdef GLAMOR -Bool KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps); +Bool KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd); void KdGlamorEnable(ScreenPtr pScreen); void KdGlamorDisable(ScreenPtr pScreen); void KdGlamorFini(ScreenPtr pScreen); #endif -int KdGlamorParse(KdGlamorInfo *info, const char **dri, int argc, char **argv, int i); +int KdGlamorParse(KdGlamorInfo *info, int argc, char **argv, int i); void KdGlamorUseMsg(void); /* Put each screen on a different card */ diff --git a/hw/kdrive/src/meson.build b/hw/kdrive/src/meson.build index 686e9128ac6..fbbecba24ba 100644 --- a/hw/kdrive/src/meson.build +++ b/hw/kdrive/src/meson.build @@ -37,7 +37,7 @@ configure_file(input : 'kdrive-config.h.meson.in', kdrive = static_library('kdrive', srcs_kdrive, include_directories: inc, - dependencies: common_dep, + dependencies: [ common_dep, libdrm_dep ], link_with: [ libxserver_miext_shadow, kdrive_glamor, From cb1ef9a8153a22ecb997952e4699fe530ffe4fa4 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 01:11:59 +0300 Subject: [PATCH 05/47] kdrive/glamor: Add `-nogbm` option Forces glamor to not use libgbm Signed-off-by: stefan11111 --- hw/kdrive/Xkdrive.man | 5 ++++- hw/kdrive/src/kglamor.c | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/Xkdrive.man b/hw/kdrive/Xkdrive.man index a7a8242aa4a..f488623106c 100644 --- a/hw/kdrive/Xkdrive.man +++ b/hw/kdrive/Xkdrive.man @@ -57,7 +57,10 @@ enables DRI3 support for the X server. force enables glamor render acceleration (even on top of sw renderers like softpipe/llvmpipe). .TP 8 .B -gbm -allows glamor to use libgbm (it is only used for matching EGLDeviceEXT's to dri fd's). +allows glamor to use libgbm. +.TP 8 +.B -nogbm +forces glamor to not use libgbm. .TP 8 .B -direct-dri3 Forces glamor to use the direct implementation of DRI3. diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index d414fc62e98..346240a8181 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -204,6 +204,11 @@ KdGlamorParse(KdGlamorInfo *info, int argc, char **argv, int i) return 1; } + if (!strcmp(argv[i], "-nogbm")) { + info->use_gbm = FALSE; + return 1; + } + if (!strcmp(argv[i], "-direct-dri3")) { info->direct_dri3 = TRUE; return 1; @@ -258,6 +263,8 @@ KdGlamorUseMsg(void) ("-noglamor Force disable glamor render acceleration\n"); ErrorF ("-gbm Allow glamor to use libgbm\n"); + ErrorF + ("-nogbm Force glamor to not use libgbm\n"); ErrorF ("-direct-dri3 Force glamor to use the direct DRI3 implementation\n"); ErrorF From 6f45606daf78401dae317337d1460df0dcfbc7b9 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 01:24:01 +0300 Subject: [PATCH 06/47] kdrive/glamor: lift glamor option reporting code Signed-off-by: stefan11111 --- hw/kdrive/fbdev/fbinit.c | 21 +-------------------- hw/kdrive/modesetting/msinit.c | 23 ++--------------------- hw/kdrive/src/kglamor.c | 25 +++++++++++++++++++++++++ hw/kdrive/src/kglamor.h | 1 + 4 files changed, 29 insertions(+), 41 deletions(-) diff --git a/hw/kdrive/fbdev/fbinit.c b/hw/kdrive/fbdev/fbinit.c index 97a4d676b48..a7adbaff66c 100644 --- a/hw/kdrive/fbdev/fbinit.c +++ b/hw/kdrive/fbdev/fbinit.c @@ -88,26 +88,7 @@ fbdevLogScreenInfo(const FbScreenConf *config, int screen_num) LogMessage(X_INFO, "Xfbdev(%d): ShadowFB %s\n", screen_num, config->shadow ? "enabled" : "disabled"); - LogMessage(X_INFO, "Xfbdev(%d): glvnd library: %s\n", screen_num, - config->glamor_info.glvnd ? config->glamor_info.glvnd : "not passed"); - - LogMessage(X_INFO, "Xfbdev(%d): dri device: %s\n", screen_num, - config->glamor_info.dri_path ? config->glamor_info.dri_path : "none"); - - LogMessage(X_INFO, "Xfbdev(%d): glamor OpenGL contexts %s\n", screen_num, - !config->glamor_info.force_es ? "allowed" : "forbidden"); - LogMessage(X_INFO, "Xfbdev(%d): glamor GLES contexts %s\n", screen_num, - !config->glamor_info.force_gl ? "allowed" : "forbidden"); - - LogMessage(X_INFO, "Xfbdev(%d): glamor render acceleration %s\n", screen_num, - !config->glamor_info.no_render_accel ? "enabled" : "disabled"); - LogMessage(X_INFO, "Xfbdev(%d): glamor render acceleration %s on software renderers\n", screen_num, - config->glamor_info.force_render_accel ? "allowed" : "forbidden"); - LogMessage(X_INFO, "Xfbdev(%d): glamor is %s libgbm \n", screen_num, - config->glamor_info.use_gbm ? "allowed to use" : "forbidden from using"); - - LogMessage(X_INFO, "Xfbdev(%d): glamor X-Video support %s\n", screen_num, - config->glamor_info.no_xv ? "allowed" : "forbidden"); + KdGlamorLogScreenInfo(&config->glamor_info, screen_num); LogMessage(X_INFO, "\n"); } diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 6a040b55e04..4cdd1f01e92 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -72,31 +72,12 @@ msLogScreenInfo(const MsScreenConf *config, int screen_num) { LogMessage(X_INFO, "Xmodesetting(%d): Screen %d:\n", screen_num, screen_num); - LogMessage(X_INFO, "Xmodesetting(%d): kms device: %s\n", screen_num, + LogMessage(X_INFO, "Xmodesetting(%d): KMS device: %s\n", screen_num, config->dev_path ? config->dev_path : "not passed"); LogMessage(X_INFO, "Xmodesetting(%d): ShadowFB %s\n", screen_num, config->shadow ? "enabled" : "disabled"); - LogMessage(X_INFO, "Xmodesetting(%d): glvnd library: %s\n", screen_num, - config->glamor_info.glvnd ? config->glamor_info.glvnd : "not passed"); - - LogMessage(X_INFO, "Xmodesetting(%d): dri device: %s\n", screen_num, - config->glamor_info.dri_path ? config->glamor_info.dri_path : "none"); - - LogMessage(X_INFO, "Xmodesetting(%d): glamor OpenGL contexts %s\n", screen_num, - !config->glamor_info.force_es ? "allowed" : "forbidden"); - LogMessage(X_INFO, "Xmodesetting(%d): glamor GLES contexts %s\n", screen_num, - !config->glamor_info.force_gl ? "allowed" : "forbidden"); - - LogMessage(X_INFO, "Xmodesetting(%d): glamor render acceleration %s\n", screen_num, - !config->glamor_info.no_render_accel ? "enabled" : "disabled"); - LogMessage(X_INFO, "Xmodesetting(%d): glamor render acceleration %s on software renderers\n", screen_num, - config->glamor_info.force_render_accel ? "allowed" : "forbidden"); - LogMessage(X_INFO, "Xmodesetting(%d): glamor is %s libgbm \n", screen_num, - config->glamor_info.use_gbm ? "allowed to use" : "forbidden from using"); - - LogMessage(X_INFO, "Xmodesetting(%d): glamor X-Video support %s\n", screen_num, - config->glamor_info.no_xv ? "allowed" : "forbidden"); + KdGlamorLogScreenInfo(&config->glamor_info, screen_num); LogMessage(X_INFO, "\n"); } diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index 346240a8181..0d6765a7932 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -250,6 +250,31 @@ KdGlamorParse(KdGlamorInfo *info, int argc, char **argv, int i) return 0; } +void +KdGlamorLogScreenInfo(const KdGlamorInfo *info, int screen_num) +{ + LogMessage(X_INFO, "KGlamor(%d): glvnd library: %s\n", screen_num, + info->glvnd ? info->glvnd : "not passed"); + + LogMessage(X_INFO, "KGlamor(%d): dri device: %s\n", screen_num, + info->dri_path ? info->dri_path : "not passed"); + + LogMessage(X_INFO, "KGlamor(%d): glamor OpenGL contexts %s\n", screen_num, + !info->force_es ? "allowed" : "forbidden"); + LogMessage(X_INFO, "KGlamor(%d): glamor GLES contexts %s\n", screen_num, + !info->force_gl ? "allowed" : "forbidden"); + + LogMessage(X_INFO, "KGlamor(%d): glamor render acceleration %s\n", screen_num, + !info->no_render_accel ? "enabled" : "disabled"); + LogMessage(X_INFO, "KGlamor(%d): glamor render acceleration %s on software renderers\n", screen_num, + info->force_render_accel ? "allowed" : "forbidden"); + LogMessage(X_INFO, "KGlamor(%d): glamor is %s libgbm \n", screen_num, + info->use_gbm ? "allowed to use" : "forbidden from using"); + + LogMessage(X_INFO, "KGlamor(%d): glamor X-Video support %s\n", screen_num, + !info->no_xv ? "enabled" : "disabled"); +} + void KdGlamorUseMsg(void) { diff --git a/hw/kdrive/src/kglamor.h b/hw/kdrive/src/kglamor.h index 5bb8994fbee..88605ae6c55 100644 --- a/hw/kdrive/src/kglamor.h +++ b/hw/kdrive/src/kglamor.h @@ -33,6 +33,7 @@ void KdGlamorFini(ScreenPtr pScreen); #endif int KdGlamorParse(KdGlamorInfo *info, int argc, char **argv, int i); +void KdGlamorLogScreenInfo(const KdGlamorInfo *info, int screen_num); void KdGlamorUseMsg(void); /* Put each screen on a different card */ From 06b6ea6bc6a4d2402a7ca43144f45b7746318916 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 01:34:15 +0300 Subject: [PATCH 07/47] kdrive/glamor: Store `dri_fd` in `KdGlamorInfo` Allows kglamor to manage it without ddx involvement Signed-off-by: stefan11111 --- hw/kdrive/fake/fake.h | 3 --- hw/kdrive/fake/fake_glamor.c | 11 +++-------- hw/kdrive/fbdev/fb_glamor.c | 11 +++-------- hw/kdrive/fbdev/fbdev.h | 3 --- hw/kdrive/modesetting/modesetting.h | 3 --- hw/kdrive/modesetting/ms_glamor.c | 11 +++-------- hw/kdrive/src/kglamor.c | 30 ++++++++++++++--------------- hw/kdrive/src/kglamor.h | 7 +++++-- 8 files changed, 29 insertions(+), 50 deletions(-) diff --git a/hw/kdrive/fake/fake.h b/hw/kdrive/fake/fake.h index 7bee219e0e1..cf58ec8691c 100644 --- a/hw/kdrive/fake/fake.h +++ b/hw/kdrive/fake/fake.h @@ -38,9 +38,6 @@ typedef struct _fakePriv { typedef struct _fakeScrPriv { Rotation randr; Bool shadow; -#ifdef GLAMOR - int dri_fd; -#endif } FakeScrPriv; typedef struct _fakeScreenConf { diff --git a/hw/kdrive/fake/fake_glamor.c b/hw/kdrive/fake/fake_glamor.c index eaba8fd5410..6759843c6d1 100644 --- a/hw/kdrive/fake/fake_glamor.c +++ b/hw/kdrive/fake/fake_glamor.c @@ -13,10 +13,9 @@ fakeInitAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - FakeScrPriv *scrpriv = screen->driver; FakeScreenConf *config = screen->card->closure; - return KdGlamorInit(pScreen, &config->glamor_info, NULL, &scrpriv->dri_fd); + return KdGlamorInit(pScreen, &config->glamor_info, NULL); } void @@ -36,11 +35,7 @@ fakeFiniAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - FakeScrPriv *scrpriv = screen->driver; - - KdGlamorFini(pScreen); + FakeScreenConf *config = screen->card->closure; - if (scrpriv->dri_fd >= 0) { - close(scrpriv->dri_fd); - } + KdGlamorFini(pScreen, &config->glamor_info); } diff --git a/hw/kdrive/fbdev/fb_glamor.c b/hw/kdrive/fbdev/fb_glamor.c index 2a7b971deb4..fa5a03e018c 100644 --- a/hw/kdrive/fbdev/fb_glamor.c +++ b/hw/kdrive/fbdev/fb_glamor.c @@ -13,14 +13,13 @@ fbdevInitAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - FbdevScrPriv *scrpriv = screen->driver; FbScreenConf *config = screen->card->closure; if (screen->rate > 60) { config->glamor_info.fake_rate = screen->rate; } - return KdGlamorInit(pScreen, &config->glamor_info, NULL, &scrpriv->dri_fd); + return KdGlamorInit(pScreen, &config->glamor_info, NULL); } void @@ -40,11 +39,7 @@ fbdevFiniAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - FbdevScrPriv *scrpriv = screen->driver; - - KdGlamorFini(pScreen); + FbScreenConf *config = screen->card->closure; - if (scrpriv->dri_fd >= 0) { - close(scrpriv->dri_fd); - } + KdGlamorFini(pScreen, &config->glamor_info); } diff --git a/hw/kdrive/fbdev/fbdev.h b/hw/kdrive/fbdev/fbdev.h index c044bf5138d..3909dfa0acf 100644 --- a/hw/kdrive/fbdev/fbdev.h +++ b/hw/kdrive/fbdev/fbdev.h @@ -48,9 +48,6 @@ typedef struct _fbdevScrPriv { Bool shadow; int max_width; int max_height; -#ifdef GLAMOR - int dri_fd; -#endif } FbdevScrPriv; typedef struct _fbScreenConf { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index cd7f255e268..7ed943e9965 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -29,9 +29,6 @@ typedef struct _msScrPriv { Rotation randr; Bool blockHandler; Bool shadow; -#ifdef GLAMOR - int dri_fd; -#endif } msScrPriv; typedef struct _msScreenConf { diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index d2cecebdd20..9c8cfda0b2f 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -15,7 +15,6 @@ msInitAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; MsScreenConf *config = screen->card->closure; int caps = GLAMOR_EGL_CAP_NONE; @@ -23,7 +22,7 @@ msInitAccel(ScreenPtr pScreen) config->glamor_info.fake_rate = screen->rate; } - if (!KdGlamorInit(pScreen, &config->glamor_info, &caps, &scrpriv->dri_fd)) { + if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { return FALSE; } @@ -52,11 +51,7 @@ msFiniAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - - KdGlamorFini(pScreen); + MsScreenConf *config = screen->card->closure; - if (scrpriv->dri_fd >= 0) { - close(scrpriv->dri_fd); - } + KdGlamorFini(pScreen, &config->glamor_info); } diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index 0d6765a7932..013ecbcd6e1 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -64,12 +64,11 @@ static int drmDropMaster(int fd) #ifdef GLAMOR Bool -KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd) +KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps) { int flags = GLAMOR_USE_EGL_SCREEN; int has_dri3; int _caps; - int _dri_fd; glamor_egl_conf_t glamor_egl_conf = { .server_private = NULL, /* only for xf86 */ @@ -96,24 +95,20 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd *caps = GLAMOR_EGL_CAP_NONE; - if (!dri_fd) { - dri_fd = &_dri_fd; - } - if (info->dri_path) { - *dri_fd = open(info->dri_path, O_RDWR); - if (*dri_fd < 0) { + info->dri_fd = open(info->dri_path, O_RDWR); + if (info->dri_fd < 0) { LogMessage(X_WARNING, "KGlamor(%d): Could not open %s: %s\n", pScreen->myNum, info->dri_path, strerror(errno)); } } else { - *dri_fd = -1; + info->dri_fd = -1; } - if ((*dri_fd >= 0) && info->drop_master) { - drmDropMaster(*dri_fd); + if ((info->dri_fd >= 0) && info->drop_master) { + drmDropMaster(info->dri_fd); } - glamor_egl_conf.fd = *dri_fd; + glamor_egl_conf.fd = info->dri_fd; if (!glamor_egl_init_internal(&glamor_egl_conf, caps)) { return FALSE; @@ -130,7 +125,7 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd } } - if (*dri_fd < 0) { + if (info->dri_fd < 0) { flags |= GLAMOR_NO_DRI3; } @@ -154,7 +149,7 @@ KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd } #endif - if (info->fake_rate && (*dri_fd >= 0)) { + if (info->fake_rate && (info->dri_fd >= 0)) { /* * X clients use present to try to synchronize with the screen * If no global fake rate was requested and a per-screen rate was requested, use that @@ -180,9 +175,14 @@ KdGlamorDisable(ScreenPtr pScreen) } void -KdGlamorFini(ScreenPtr pScreen) +KdGlamorFini(ScreenPtr pScreen, KdGlamorInfo *info) { glamor_fini(pScreen); + + if (info->dri_fd) { + close(info->dri_fd); + info->dri_fd = -1; + } } #endif diff --git a/hw/kdrive/src/kglamor.h b/hw/kdrive/src/kglamor.h index 88605ae6c55..4656abe334e 100644 --- a/hw/kdrive/src/kglamor.h +++ b/hw/kdrive/src/kglamor.h @@ -23,13 +23,16 @@ typedef struct { Bool no_xv; /* Disable X-Video support */ Bool no_render_accel; /* Disable render acceleration */ Bool force_render_accel; /* Enable render acceleration on top of sw renderers */ + + /* Populated and closed by KdGlamorInit / KdGlamorFini */ + int dri_fd; } KdGlamorInfo; #ifdef GLAMOR -Bool KdGlamorInit(ScreenPtr pScreen, const KdGlamorInfo *info, int *caps, int *dri_fd); +Bool KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps); void KdGlamorEnable(ScreenPtr pScreen); void KdGlamorDisable(ScreenPtr pScreen); -void KdGlamorFini(ScreenPtr pScreen); +void KdGlamorFini(ScreenPtr pScreen, KdGlamorInfo *info); #endif int KdGlamorParse(KdGlamorInfo *info, int argc, char **argv, int i); From fea035ad1ab34355c5f3ffb0592527ca4d1735b2 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 01:55:00 +0300 Subject: [PATCH 08/47] kdrive/glamor: Close `dri_fd` on glamor init error Signed-off-by: stefan11111 --- hw/kdrive/src/kglamor.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index 013ecbcd6e1..afae5c50c43 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -111,7 +111,7 @@ KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps) glamor_egl_conf.fd = info->dri_fd; if (!glamor_egl_init_internal(&glamor_egl_conf, caps)) { - return FALSE; + goto bail; } if (info->no_render_accel) { @@ -130,7 +130,7 @@ KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps) } if (!glamor_init(pScreen, flags)) { - return FALSE; + goto bail; } #define GLAMOR_EGL_CAP_DRI3_IMPORT_EXPORT (GLAMOR_EGL_CAP_DRI3_IMPORT | GLAMOR_EGL_CAP_DRI3_EXPORT) @@ -162,6 +162,14 @@ KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps) } return TRUE; + +bail: + if (info->dri_fd >= 0) { + close(info->dri_fd); + info->dri_fd = -1; + } + + return FALSE; } void From 30b5056392b45829e3b8634db4ca92db8af353b8 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 15:06:12 +0300 Subject: [PATCH 09/47] Xfbdev: `ErrorF(...)` -> `LogMessage(X_ERROR, ...)` Signed-off-by: stefan11111 --- hw/kdrive/fbdev/fbdev.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/kdrive/fbdev/fbdev.c b/hw/kdrive/fbdev/fbdev.c index ca266933e6c..ff993ab1b53 100644 --- a/hw/kdrive/fbdev/fbdev.c +++ b/hw/kdrive/fbdev/fbdev.c @@ -42,8 +42,8 @@ fbdevInitialize(KdCardInfo * card, FbdevPriv * priv) if (config->fb_path) { priv->fd = open(config->fb_path, O_RDWR); if (priv->fd < 0) { - ErrorF("Error opening framebuffer %s: %s\n", - config->fb_path, strerror(errno)); + LogMessage(X_ERROR, "Xfbdev(%d): Error opening framebuffer %s: %s\n", + card->mynum, config->fb_path, strerror(errno)); return FALSE; } LogMessage(X_INFO, "Xfbdev(%d): Using framebuffer device: %s\n", @@ -67,7 +67,7 @@ fbdevInitialize(KdCardInfo * card, FbdevPriv * priv) } } if (priv->fd < 0) { - ErrorF("Error opening framebuffers /dev/fb[0-31]\n"); + LogMessage(X_ERROR, "Xfbdev(%d): Error opening framebuffers /dev/fb[0-31]\n", card->mynum); return FALSE; } LogMessage(X_INFO, "Xfbdev(%d): Using framebuffer device: %s\n", card->mynum, devbuf); From fc9f2751137de47f07888b96bc47aa4d1aaa0d06 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 21:25:32 +0300 Subject: [PATCH 10/47] kdrive/modesetting: Mode the drm resources ptr to the card private This is per-card info, that is shared among screens Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 55 ++++++++++++++++------------- hw/kdrive/modesetting/modesetting.h | 1 + 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 87633997c1b..d8dbd4d401c 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -16,7 +16,6 @@ typedef struct { drmModeConnector *connector; - drmModeRes *resources; drmModeModeInfo *mode; void *map_data; @@ -58,10 +57,6 @@ destroy_user_data(struct gbm_bo *bo, void *_data) drmModeFreeConnector(data->connector); } - if (data->resources) { - drmModeFreeResources(data->resources); - } - free(data); } @@ -309,8 +304,9 @@ modeseting_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn) static struct gbm_bo* -modesetting_open(struct gbm_device *gbm, KdScreenInfo *screen) +modesetting_open(msPriv *priv, KdScreenInfo *screen) { + struct gbm_device *gbm = priv->gbm; int fd = gbm_device_get_fd(gbm); struct gbm_bo *ret = NULL; gbm_user_data_t *data = NULL; @@ -320,14 +316,7 @@ modesetting_open(struct gbm_device *gbm, KdScreenInfo *screen) goto fail; } - drmSetMaster(fd); - - data->resources = drmModeGetResources(fd); - if (!data->resources) { - goto fail; - } - - data->connector = modesetting_find_connector(data->resources, fd, &data->conn_id); + data->connector = modesetting_find_connector(priv->resources, fd, &data->conn_id); if (!data->connector) { goto fail; } @@ -352,7 +341,7 @@ modesetting_open(struct gbm_device *gbm, KdScreenInfo *screen) goto fail; } - data->crtc_id = modeseting_find_crtc(fd, data->resources, data->connector); + data->crtc_id = modeseting_find_crtc(fd, priv->resources, data->connector); if (data->crtc_id < 0) { goto fail; } @@ -369,8 +358,6 @@ modesetting_open(struct gbm_device *gbm, KdScreenInfo *screen) if (data) { if (data->connector) drmModeFreeConnector(data->connector); - if (data->resources) - drmModeFreeResources(data->resources); free(data); } @@ -395,7 +382,7 @@ msSetMode(ScreenPtr pScreen, int rate) screen->height = pScreen->height; screen->rate = rate; - new_bo = modesetting_open(priv->gbm, screen); + new_bo = modesetting_open(priv, screen); if (!new_bo) { screen->width = oldwidth; screen->height = oldheight; @@ -418,7 +405,7 @@ static Bool msInitialize(KdCardInfo * card, msPriv * priv) if (fd < 0) { LogMessage(X_ERROR, "Xmodesetting(%d): Error opening KMS device %s: %s\n", card->mynum, config->dev_path, strerror(errno)); - return FALSE; + goto bail; } LogMessage(X_INFO, "Xmodesetting(%d): Using KMS device: %s\n", card->mynum, config->dev_path); @@ -442,20 +429,37 @@ static Bool msInitialize(KdCardInfo * card, msPriv * priv) } } if (fd < 0) { - ErrorF("Error opening kms devices /dev/dri/card[0-63]\n"); - return FALSE; + LogMessage(X_ERROR, "Xmodesetting(%d): Error opening kms devices /dev/dri/card[0-63]\n", card->mynum); + goto bail; } LogMessage(X_INFO, "Xmodesetting(%d): Using kms device: %s\n", card->mynum, devbuf); } priv->gbm = gbm_create_device(fd); if (!priv->gbm) { - ErrorF("Could not create a gbm device\n"); - close(fd); - return FALSE; + LogMessage(X_ERROR, "Xmodesetting(%d): Could not create a gbm device\n", card->mynum); + goto bail; + } + + drmSetMaster(fd); + + priv->resources = drmModeGetResources(fd); + if (!priv->resources) { + LogMessage(X_ERROR, "Xmodesetting(%d): Could not get drm resources: %s\n", card->mynum, strerror(errno)); + goto bail; } return TRUE; + +bail: + if (priv->gbm) { + gbm_device_destroy(priv->gbm); + priv->gbm = NULL; + } + if (fd >= 0) { + close(fd); + } + return FALSE; } Bool msCardInit(KdCardInfo * card) @@ -480,7 +484,7 @@ static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) msPriv *priv = screen->card->driver; gbm_user_data_t *data = NULL; - scrpriv->front = modesetting_open(priv->gbm, screen); + scrpriv->front = modesetting_open(priv, screen); if (!scrpriv->front) { return FALSE; } @@ -1078,6 +1082,7 @@ void msCardFini(KdCardInfo * card) struct gbm_device *gbm = priv->gbm; int fd = gbm_device_get_fd(gbm); + drmModeFreeResources(priv->resources); gbm_device_destroy(gbm); close(fd); free(priv); diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 7ed943e9965..39d3b5604ef 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -18,6 +18,7 @@ typedef struct _msPriv { struct gbm_device *gbm; + drmModeRes *resources; __u16 red[256]; __u16 green[256]; __u16 blue[256]; From 5548bc318430df889fa0bc161e834787838c1519 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 22:49:35 +0300 Subject: [PATCH 11/47] kdrive/modesetting: Move the connector, mode, and crtc to `scrpriv` They are properties of the screen, not the front bo Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 150 ++++++++++++++++------------ hw/kdrive/modesetting/modesetting.h | 6 ++ 2 files changed, 92 insertions(+), 64 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index d8dbd4d401c..9a1a687e54b 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -15,14 +15,9 @@ #endif typedef struct { - drmModeConnector *connector; - drmModeModeInfo *mode; - void *map_data; void *map_addr; - uint32_t conn_id; - uint32_t crtc_id; uint32_t fb_id; } gbm_user_data_t; @@ -53,10 +48,6 @@ destroy_user_data(struct gbm_bo *bo, void *_data) gbm_bo_unmap(bo, data->map_data); } - if (data->connector) { - drmModeFreeConnector(data->connector); - } - free(data); } @@ -121,11 +112,8 @@ gbm_bo_create_and_map_once(struct gbm_device *gbm, } static struct gbm_bo* -gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, int w, int h) +gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t width, uint32_t height) { - uint32_t width = data->mode ? data->mode->hdisplay : w; - uint32_t height = data->mode ? data->mode->vdisplay : h; - uint32_t format = GBM_FORMAT_XRGB8888; #if 0 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_FRONT_RENDERING; @@ -307,7 +295,6 @@ static struct gbm_bo* modesetting_open(msPriv *priv, KdScreenInfo *screen) { struct gbm_device *gbm = priv->gbm; - int fd = gbm_device_get_fd(gbm); struct gbm_bo *ret = NULL; gbm_user_data_t *data = NULL; @@ -316,20 +303,7 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen) goto fail; } - data->connector = modesetting_find_connector(priv->resources, fd, &data->conn_id); - if (!data->connector) { - goto fail; - } - - data->mode = modesetting_find_mode(data->connector, screen->width, screen->height, screen->rate); - if (!data->mode) { - LogMessage(X_WARNING, "Xmodesetting(%d): Could not find a supported mode\n", - screen->card->mynum); - LogMessage(X_WARNING, "Xmodesetting(%d): This likely means the video card has no connected outputs, or the requested mode is not supported\n", - screen->card->mynum); - } - - ret = gbm_bo_create_and_map(gbm, data, screen->width ? screen->width : 1920, screen->height ? screen->height : 1080); + ret = gbm_bo_create_and_map(gbm, data, screen->width, screen->height); if (!ret) { goto fail; } @@ -341,11 +315,6 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen) goto fail; } - data->crtc_id = modeseting_find_crtc(fd, priv->resources, data->connector); - if (data->crtc_id < 0) { - goto fail; - } - return ret; fail: @@ -356,8 +325,6 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen) } if (data) { - if (data->connector) - drmModeFreeConnector(data->connector); free(data); } @@ -365,34 +332,52 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen) } static Bool -msSetMode(ScreenPtr pScreen, int rate) +msSetMode(ScreenPtr pScreen, int width, int height, int rate) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; msPriv *priv = screen->card->driver; msScrPriv *scrpriv = screen->driver; - struct gbm_bo *new_bo; + struct gbm_bo *old_front; + drmModeModeInfo *old_mode; int oldwidth, oldheight, oldrate; + old_front = scrpriv->front; + old_mode = scrpriv->mode; oldwidth = screen->width; oldheight = screen->height; oldrate = screen->rate; - screen->width = pScreen->width; - screen->height = pScreen->height; + screen->width = width; + screen->height = height; screen->rate = rate; - new_bo = modesetting_open(priv, screen); - if (!new_bo) { - screen->width = oldwidth; - screen->height = oldheight; - screen->rate = oldrate; - return FALSE; + /* Find the mode */ + scrpriv->mode = modesetting_find_mode(scrpriv->connector, screen->width, screen->height, screen->rate); + if (!scrpriv->mode) { + goto bail; } - gbm_bo_destroy(scrpriv->front); - scrpriv->front = new_bo; + /* Create a new front with the new sizes */ + if (oldwidth != screen->width || + oldheight != screen->height) { + scrpriv->front = modesetting_open(priv, screen); + if (!scrpriv->front) { + goto bail; + } + + gbm_bo_destroy(old_front); + } return TRUE; + +bail: + scrpriv->front = old_front; + scrpriv->mode = old_mode; + screen->width = oldwidth; + screen->height = oldheight; + screen->rate = oldrate; + + return FALSE; } static Bool msInitialize(KdCardInfo * card, msPriv * priv) @@ -482,18 +467,40 @@ Bool msCardInit(KdCardInfo * card) static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) { msPriv *priv = screen->card->driver; - gbm_user_data_t *data = NULL; + int fd = gbm_device_get_fd(priv->gbm); + + scrpriv->connector = modesetting_find_connector(priv->resources, fd, &scrpriv->conn_id); + if (!scrpriv->connector) { + goto fail; + } + + scrpriv->crtc_id = modeseting_find_crtc(fd, priv->resources, scrpriv->connector); + if (scrpriv->crtc_id < 0) { + goto fail; + } + + scrpriv->mode = modesetting_find_mode(scrpriv->connector, screen->width, screen->height, screen->rate); + if (!scrpriv->mode) { + LogMessage(X_WARNING, "Xmodesetting(%d): Could not find a supported mode\n", + screen->card->mynum); + LogMessage(X_WARNING, "Xmodesetting(%d): This likely means the video card has no connected outputs, or the requested mode is not supported\n", + screen->card->mynum); + } + + /* modesetting_open allocates the bo based on this */ + if (!screen->width || !screen->height) { + screen->width = scrpriv->mode ? scrpriv->mode->hdisplay : 1920; + screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; + } scrpriv->front = modesetting_open(priv, screen); if (!scrpriv->front) { - return FALSE; + goto fail; } - data = gbm_bo_get_user_data(scrpriv->front); - screen->width = gbm_bo_get_width(scrpriv->front); screen->height = gbm_bo_get_height(scrpriv->front); - screen->rate = data->mode ? data->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ + screen->rate = scrpriv->mode ? scrpriv->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ /* GBM_FORMAT_XRGB8888 */ screen->fb.visuals = (1 << TrueColor); @@ -505,7 +512,22 @@ static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->fb.bitsPerPixel = 32; scrpriv->randr = screen->randr; - return msMapFramebuffer(screen); + if (!msMapFramebuffer(screen)) { + goto fail; + } + + return TRUE; + +fail: + if (scrpriv->front) { + gbm_bo_destroy(scrpriv->front); + } + + if (scrpriv->connector) { + drmModeFreeConnector(scrpriv->connector); + } + + return FALSE; } Bool msScreenInit(KdScreenInfo * screen) @@ -627,7 +649,6 @@ static Bool msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; msScrPriv *scrpriv = screen->driver; - gbm_user_data_t *data = gbm_bo_get_user_data(scrpriv->front); Rotation randr; int n; @@ -645,8 +666,8 @@ static Bool msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) randr = KdSubRotation(scrpriv->randr, screen->randr); - for (int i = 0; i < data->connector->count_modes; i++) { - drmModeModeInfo *mode = &data->connector->modes[i]; + for (int i = 0; i < scrpriv->connector->count_modes; i++) { + drmModeModeInfo *mode = &scrpriv->connector->modes[i]; RRScreenSizePtr pSize; pSize = RRRegisterSize(pScreen, mode->hdisplay, @@ -715,7 +736,7 @@ msRandRSetConfig(ScreenPtr pScreen, msUnmapFramebuffer(screen); - if (!msSetMode(pScreen, rate)) + if (!msSetMode(pScreen, pSize->width, pSize->height, rate)) goto bail4; if (!msMapFramebuffer(screen)) @@ -767,7 +788,6 @@ msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; msScrPriv *scrpriv = screen->driver; - gbm_user_data_t *data = gbm_bo_get_user_data(scrpriv->front); *mmWidth = screen->width_mm; *mmHeight = screen->height_mm; @@ -776,9 +796,9 @@ msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) return TRUE; } - if (((int)data->connector->mmWidth > 0) && ((int)data->connector->mmHeight > 0)) { - *mmWidth = data->connector->mmWidth; - *mmWidth = data->connector->mmHeight; + if (((int)scrpriv->connector->mmWidth > 0) && ((int)scrpriv->connector->mmHeight > 0)) { + *mmWidth = scrpriv->connector->mmWidth; + *mmWidth = scrpriv->connector->mmHeight; return TRUE; } @@ -1016,10 +1036,10 @@ Bool msEnable(ScreenPtr pScreen) drmSetMaster(fd); - if (!data->mode) { - data->mode = modesetting_find_mode(data->connector, screen->width, screen->height, screen->rate); + if (!priv->mode) { + priv->mode = modesetting_find_mode(priv->connector, screen->width, screen->height, screen->rate); } - if (data->mode && drmModeSetCrtc(fd, data->crtc_id, data->fb_id, 0, 0, &data->conn_id, 1, data->mode)) { + if (priv->mode && drmModeSetCrtc(fd, priv->crtc_id, data->fb_id, 0, 0, &priv->conn_id, 1, priv->mode)) { return FALSE; } @@ -1071,6 +1091,8 @@ void msScreenFini(KdScreenInfo * screen) msScrPriv *priv = screen->driver; gbm_bo_destroy(priv->front); + drmModeFreeConnector(priv->connector); + free(priv); screen->driver = NULL; } diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 39d3b5604ef..5867711d890 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -19,6 +19,7 @@ typedef struct _msPriv { struct gbm_device *gbm; drmModeRes *resources; + __u16 red[256]; __u16 green[256]; __u16 blue[256]; @@ -26,6 +27,11 @@ typedef struct _msPriv { typedef struct _msScrPriv { struct gbm_bo *front; + drmModeConnector *connector; + drmModeModeInfo *mode; + uint32_t conn_id; + uint32_t crtc_id; + DamagePtr damage; Rotation randr; Bool blockHandler; From 05f3637d952f1558cc7910864244d701c06f1304 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Mon, 14 Sep 2026 23:22:29 +0300 Subject: [PATCH 12/47] kdrive/modesetting: Add multiple screens on a single card Store only the device path in `card->closure` Store the screen config in `screen->closure` Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 95 ++++++++++++++---- hw/kdrive/modesetting/modesetting.h | 7 +- hw/kdrive/modesetting/ms_glamor.c | 8 +- hw/kdrive/modesetting/msinit.c | 146 +++++++++++++++++++++++++--- 4 files changed, 223 insertions(+), 33 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 9a1a687e54b..8690e72f595 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -382,18 +382,18 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) static Bool msInitialize(KdCardInfo * card, msPriv * priv) { - MsScreenConf *config = card->closure; + const char *dev_path = card->closure; int fd; - if (config->dev_path) { - fd = open(config->dev_path, O_RDWR); + if (dev_path) { + fd = open(dev_path, O_RDWR); if (fd < 0) { - LogMessage(X_ERROR, "Xmodesetting(%d): Error opening KMS device %s: %s\n", - card->mynum, config->dev_path, strerror(errno)); + LogMessage(X_ERROR, "Xmodesetting(card %d): Error opening KMS device %s: %s\n", + card->mynum, dev_path, strerror(errno)); goto bail; } - LogMessage(X_INFO, "Xmodesetting(%d): Using KMS device: %s\n", - card->mynum, config->dev_path); + LogMessage(X_INFO, "Xmodesetting(card %d): Using KMS device: %s\n", + card->mynum, dev_path); } else { char devbuf[] = "/dev/dri/cardxx"; fd = -1; @@ -414,15 +414,15 @@ static Bool msInitialize(KdCardInfo * card, msPriv * priv) } } if (fd < 0) { - LogMessage(X_ERROR, "Xmodesetting(%d): Error opening kms devices /dev/dri/card[0-63]\n", card->mynum); + LogMessage(X_ERROR, "Xmodesetting(card %d): Error opening kms devices /dev/dri/card[0-63]\n", card->mynum); goto bail; } - LogMessage(X_INFO, "Xmodesetting(%d): Using kms device: %s\n", card->mynum, devbuf); + LogMessage(X_INFO, "Xmodesetting(card %d): Using kms device: %s\n", card->mynum, devbuf); } priv->gbm = gbm_create_device(fd); if (!priv->gbm) { - LogMessage(X_ERROR, "Xmodesetting(%d): Could not create a gbm device\n", card->mynum); + LogMessage(X_ERROR, "Xmodesetting(card %d): Could not create a gbm device\n", card->mynum); goto bail; } @@ -430,7 +430,7 @@ static Bool msInitialize(KdCardInfo * card, msPriv * priv) priv->resources = drmModeGetResources(fd); if (!priv->resources) { - LogMessage(X_ERROR, "Xmodesetting(%d): Could not get drm resources: %s\n", card->mynum, strerror(errno)); + LogMessage(X_ERROR, "Xmodesetting(card %d): Could not get drm resources: %s\n", card->mynum, strerror(errno)); goto bail; } @@ -447,7 +447,68 @@ static Bool msInitialize(KdCardInfo * card, msPriv * priv) return FALSE; } -Bool msCardInit(KdCardInfo * card) +/* XXX This really belongs in os/, like the version from glamor_egl */ +static Bool +msFdMatch(int fd1, int fd2) +{ + struct stat stat1, stat2; + + if (fd1 == fd2) { + return TRUE; + } + + if (fd1 < 0 || fd2 < 0) { + return FALSE; + } + + if (fstat(fd1, &stat1) < 0 || + fstat(fd2, &stat2) < 0) { + return FALSE; + } + + /** + * From https://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/stat.h.html + * + * The st_ino and st_dev fields taken together uniquely identify the file within the system. + */ + return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); +} + +static KdCardInfo* +msFindCardForFd(int fd) +{ + for (KdCardInfo *card = kdCardInfo; card; card = card->next) { + const char *card_path = card->closure; + int cardFd = card_path ? open(card_path, O_RDWR) : -1; + Bool ret = msFdMatch(cardFd, fd); + + if (cardFd >= 0) { + close(cardFd); + } + if (ret) { + return card; + } + } + + return NULL; +} + +KdCardInfo* +msFindMatchingCard(const char *card_path) +{ + KdCardInfo *card; + int fd = card_path ? open(card_path, O_RDWR) : -1; + + card = msFindCardForFd(fd); + + if (fd >= 0) { + close(fd); + } + return card; +} + +Bool +msCardInit(KdCardInfo * card) { msPriv *priv; @@ -481,10 +542,10 @@ static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) scrpriv->mode = modesetting_find_mode(scrpriv->connector, screen->width, screen->height, screen->rate); if (!scrpriv->mode) { - LogMessage(X_WARNING, "Xmodesetting(%d): Could not find a supported mode\n", - screen->card->mynum); - LogMessage(X_WARNING, "Xmodesetting(%d): This likely means the video card has no connected outputs, or the requested mode is not supported\n", - screen->card->mynum); + LogMessage(X_WARNING, "Xmodesetting(card %d, screen %d): Could not find a supported mode\n", + screen->card->mynum, screen->mynum); + LogMessage(X_WARNING, "Xmodesetting(card %d, screen %d): This likely means that this output is not connected, or the requested mode is not supported\n", + screen->card->mynum, screen->mynum); } /* modesetting_open allocates the bo based on this */ @@ -568,7 +629,7 @@ static Bool msMapFramebuffer(KdScreenInfo * screen) { msScrPriv *scrpriv = screen->driver; KdPointerMatrix m; - MsScreenConf *config = screen->card->closure; + MsScreenConf *config = screen->closure; unsigned long stride = gbm_bo_get_stride(scrpriv->front); diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 5867711d890..67cf5fd6e6c 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -19,10 +19,11 @@ typedef struct _msPriv { struct gbm_device *gbm; drmModeRes *resources; - +#if 0 __u16 red[256]; __u16 green[256]; __u16 blue[256]; +#endif } msPriv; typedef struct _msScrPriv { @@ -39,14 +40,14 @@ typedef struct _msScrPriv { } msScrPriv; typedef struct _msScreenConf { - const char *dev_path; Bool shadow; KdGlamorInfo glamor_info; - const char *dri_path; } MsScreenConf; extern KdCardFuncs msFuncs; +KdCardInfo* msFindMatchingCard(const char *card_path); + Bool msCardInit(KdCardInfo * card); Bool msScreenInit(KdScreenInfo * screen); diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 9c8cfda0b2f..1882f4a006f 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -15,13 +15,17 @@ msInitAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - MsScreenConf *config = screen->card->closure; + MsScreenConf *config = screen->closure; int caps = GLAMOR_EGL_CAP_NONE; if (screen->rate > 60) { config->glamor_info.fake_rate = screen->rate; } + if (!config->glamor_info.dri_path) { + config->glamor_info.dri_path = screen->card->closure; + } + if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { return FALSE; } @@ -51,7 +55,7 @@ msFiniAccel(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - MsScreenConf *config = screen->card->closure; + MsScreenConf *config = screen->closure; KdGlamorFini(pScreen, &config->glamor_info); } diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 4cdd1f01e92..1d9fc2322cb 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -20,15 +20,19 @@ #include +static int ac = 0; +static char **av = NULL; + static MsScreenConf *msCurrScreen = NULL; static const MsScreenConf msDefaultConfig = { - .dev_path = NULL, .shadow = TRUE, .glamor_info = {.use_gbm = TRUE,}, }; -static void msLogScreenInfo(const MsScreenConf *config, int screen_num); +static const char* FindDevPath(int argc, char **argv, int i); + +static void msLogScreenInfo(const MsScreenConf *config, const char* dev_path, int screen_num); static void msLogInit(void) @@ -36,6 +40,7 @@ msLogInit(void) KdCardInfo *curr_card = kdCardInfo; char *log_file = NULL; const char *display_name = display ? display : ""; + int idx = 0; if (asprintf(&log_file, DEFAULT_LOGDIR "/Xmodesetting.%s.log", display_name) < 0) { LogInit(DEFAULT_LOGDIR "/Xkdrive.log", ".old"); } else { @@ -50,30 +55,120 @@ msLogInit(void) if (curr_card) { while(curr_card) { - msLogScreenInfo(curr_card->closure, curr_card->mynum); + for (KdScreenInfo *screen = curr_card->screenList; screen; screen = screen->next) { + msLogScreenInfo(screen->closure, curr_card->closure, idx++); + } curr_card = curr_card->next; } } else { - MsScreenConf msDummyConfig = msDefaultConfig; - msLogScreenInfo(&msDummyConfig, 0); + msLogScreenInfo(msCurrScreen ? msCurrScreen : &msDefaultConfig, FindDevPath(ac, av, 0), 0); } } void InitCard(char *name) { - msCurrScreen = XNFalloc(sizeof(*msCurrScreen)); - *msCurrScreen = msDefaultConfig; - KdCardInfoAdd(&msFuncs, msCurrScreen); + KdCardInfoAdd(&msFuncs, name); +} + +/* Find the dev_path argument for this screen */ +static const char* +FindDevPath(int argc, char **argv, int i) +{ + const char *dev_path = NULL; + + /* If this is the last screen and we find a -dev argument, return it */ + for (int j = i + 1; j < argc; j++) { + if (!strcmp(argv[j], "-dev")) { + if ((j + 1 < argc) && (argv[j + 1][0] != '-')) { + dev_path = argv[j + 1]; + } + } + + /* This was not the last screen */ + if (!strcmp(argv[j], "-screen")) { + dev_path = NULL; + break; + } + } + + if (dev_path) { + return dev_path; + } + + /* Now go backwards to find the -dev argument */ + for (int j = i - 1; j >= 0; j--) { + if (!strcmp(argv[j], "-dev")) { + if ((j + 1 < argc) && (argv[j + 1][0] != '-')) { + return argv[j + 1]; + } + } + + /* This screen had no -dev argument */ + if (!strcmp(argv[j], "-screen")) { + return NULL; + } + } + + /* This screen had no -dev argument */ + return NULL; +} + +static int +InitScreen(int argc, char **argv, int i) +{ + KdCardInfo *card; + KdScreenInfo *screen; + const char *screen_arg; + const char *dev_path; + + /* We need at least one screen config */ + if (!msCurrScreen) { + msCurrScreen = XNFalloc(sizeof(*msCurrScreen)); + *msCurrScreen = msDefaultConfig; + } + + /* Not a -screen argument */ + if (strcmp(argv[i], "-screen")) { + return 0; + } + + screen_arg = ((i + 1) < argc && argv[i + 1][0] != '-') ? argv[i + 1] : NULL; + dev_path = FindDevPath(argc, argv, i); + + card = msFindMatchingCard(dev_path); + if (!card) { + InitCard((char*)dev_path); + card = KdCardInfoLast(); + } + + if (!card) { + FatalError("Xmodesetting: No matching card found for device: %s!\n", dev_path); + } + + screen = KdScreenInfoAdd(card, msCurrScreen); + KdParseScreen(screen, screen_arg); + + /* Check if there are any more screens */ + for (int j = i + 1; j < argc; j++) { + /* If yes, allocate one more screen config */ + if (!strcmp(argv[j], "-screen")) { + msCurrScreen = XNFalloc(sizeof(*msCurrScreen)); + *msCurrScreen = msDefaultConfig; + break; + } + } + + return screen_arg ? 2 : 1; } static void -msLogScreenInfo(const MsScreenConf *config, int screen_num) +msLogScreenInfo(const MsScreenConf *config, const char *dev_path, int screen_num) { LogMessage(X_INFO, "Xmodesetting(%d): Screen %d:\n", screen_num, screen_num); LogMessage(X_INFO, "Xmodesetting(%d): KMS device: %s\n", screen_num, - config->dev_path ? config->dev_path : "not passed"); + dev_path ? dev_path : "not passed"); LogMessage(X_INFO, "Xmodesetting(%d): ShadowFB %s\n", screen_num, config->shadow ? "enabled" : "disabled"); @@ -93,6 +188,26 @@ ddxInputThreadInit(void) void InitOutput(int argc, char **argv) { + KdCardInfo *card; + KdScreenInfo *screen; + + if (!kdCardInfo) { + InitCard((char*)FindDevPath(argc, argv, 0)); + } + + if (!(card = KdCardInfoLast())) + FatalError("No matching cards found!\n"); + + /* Add at least one screen */ + if (!card->screenList) { + if (!msCurrScreen) { + msCurrScreen = XNFalloc(sizeof(*msCurrScreen)); + *msCurrScreen = msDefaultConfig; + } + screen = KdScreenInfoAdd(card, msCurrScreen); + KdParseScreen(screen, NULL); + } + KdInitOutput(argc, argv); } @@ -129,15 +244,24 @@ int ddxProcessArgument(int argc, char **argv, int i) { int glamor_arg; + int screen_arg; - KdEnsureCard(argc, argv, i, !msCurrScreen); + ac = argc; + av = argv; + + screen_arg = InitScreen(argc, argv, i); + if (screen_arg) { + return screen_arg; + } if (!strcmp(argv[i], "-dev")) { if ((i + 1 < argc) && (argv[i + 1][0] != '-')) { +#if 0 /* Handled by InitScreen */ msCurrScreen->dev_path = argv[i + 1]; if (!msCurrScreen->glamor_info.dri_path) { msCurrScreen->glamor_info.dri_path = msCurrScreen->dev_path; } +#endif return 2; } UseMsg(); From 9f9b126df93759008c1a4e6dc16dad8828045e88 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Tue, 15 Sep 2026 18:24:26 +0300 Subject: [PATCH 13/47] kdrive/modesetting: Handle multiple outputs connected on the same card If multiple physical outputs are connected to screens on the same physical card, we probe the first output and crtc as unusal, and add them to a list. For subsequent screens on the same card, we look for different outputs and crtcs Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 117 +++++++++++++++++++++++----- hw/kdrive/modesetting/modesetting.h | 6 ++ 2 files changed, 105 insertions(+), 18 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 8690e72f595..cf77fad6e1d 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -199,31 +199,46 @@ modesetting_find_mode(drmModeConnector *conn, uint32_t req_w, uint32_t req_h, ui } static int -modesetting_grade_connector(drmModeConnector *conn) +modesetting_grade_connector(msPriv *priv, drmModeConnector *conn, uint32_t conn_id) { - if (!conn->modes || !conn->count_modes) { - return 1; + int score = 1; + Bool in_use = FALSE; + + if (conn->modes && conn->count_modes) { + score += 5; } switch(conn->connection) { case DRM_MODE_CONNECTED: - return 5; + score++; case DRM_MODE_UNKNOWNCONNECTION: - return 4; + score++; case DRM_MODE_DISCONNECTED: - return 3; + score++; } - /* unreachable */ - return 2; + for(int i = 0; i < priv->num_used_connectors; i++) { + if (priv->used_connectors[i] == conn_id) { + in_use = TRUE; + break; + } + } + + if (!in_use) { + score += 10; + } + + return score; } static drmModeConnector* -modesetting_find_connector(drmModeRes *res, int fd, uint32_t *conn_id) +modesetting_find_connector(msPriv *priv, int fd, uint32_t *conn_id) { drmModeConnector *best_connector = NULL; int best_score = 0; + drmModeRes *res = priv->resources; + for (int i = 0; i < res->count_connectors; i++) { drmModeConnector *conn; int id; @@ -234,7 +249,7 @@ modesetting_find_connector(drmModeRes *res, int fd, uint32_t *conn_id) continue; } - score = modesetting_grade_connector(conn); + score = modesetting_grade_connector(priv, conn, id); if (score <= best_score) { drmModeFreeConnector(conn); continue; @@ -252,12 +267,26 @@ modesetting_find_connector(drmModeRes *res, int fd, uint32_t *conn_id) return best_connector; } -/* From man drm-kms */ +static Bool +modesetting_crtc_is_used(msPriv *priv, int crtc) +{ + for (int i = 0; i < priv->num_used_crtcs; i++) { + if (priv->used_crtcs[i] == crtc) { + return TRUE; + } + } + + return FALSE; +} + +/* Slightly modified rom man drm-kms */ static int -modeseting_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn) +modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn) { + drmModeRes *res = priv->resources; drmModeEncoder *enc; unsigned int i, j; + int crtc = -ENOENT; /* iterate all encoders of this connector */ for (i = 0; i < conn->count_encoders; ++i) { @@ -279,15 +308,22 @@ modeseting_find_crtc(int fd, drmModeRes *res, drmModeConnector *conn) * step. Otherwise, simply scan your list of configured * connectors and CRTCs whether this CRTC is already * used. If it is, then simply continue the search here. */ - drmModeFreeEncoder(enc); - return res->crtcs[j]; + if (!modesetting_crtc_is_used(priv, res->crtcs[j])) { + drmModeFreeEncoder(enc); + return res->crtcs[j]; + } + + /* Allow reusing crtcs for testing */ + if (crtc < 0) { + crtc = res->crtcs[j]; + } } drmModeFreeEncoder(enc); } /* cannot find a suitable CRTC */ - return -ENOENT; + return crtc; } @@ -525,17 +561,57 @@ msCardInit(KdCardInfo * card) return TRUE; } -static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) +static void +modesetting_claim_connector_crtc(msPriv *priv, uint32_t conn, int crtc) +{ + Bool need_new_conn = TRUE; + Bool need_new_crtc = TRUE; + + for (int i = 0; i < priv->num_used_connectors; i++) { + if (priv->used_connectors[i] == conn) { + need_new_conn = FALSE; + break; + } + } + + for (int i = 0; i < priv->num_used_crtcs; i++) { + if (priv->used_crtcs[i] == crtc) { + need_new_crtc = FALSE; + break; + } + } + + if (need_new_conn) { + void *tmp = realloc(priv->used_connectors, (priv->num_used_connectors + 1) * sizeof(*priv->used_connectors)); + if (tmp) { + priv->used_connectors = tmp; + priv->used_connectors[priv->num_used_connectors] = conn; + priv->num_used_connectors++; + } + } + + if (need_new_crtc) { + void *tmp = realloc(priv->used_crtcs, (priv->num_used_crtcs + 1) * sizeof(*priv->used_crtcs)); + if (tmp) { + priv->used_crtcs = tmp; + priv->used_crtcs[priv->num_used_crtcs] = crtc; + priv->num_used_crtcs++; + } + } +} + +static Bool +msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) { msPriv *priv = screen->card->driver; int fd = gbm_device_get_fd(priv->gbm); - scrpriv->connector = modesetting_find_connector(priv->resources, fd, &scrpriv->conn_id); + scrpriv->connector = modesetting_find_connector(priv, fd, &scrpriv->conn_id); if (!scrpriv->connector) { goto fail; } - scrpriv->crtc_id = modeseting_find_crtc(fd, priv->resources, scrpriv->connector); + scrpriv->crtc_id = modeseting_find_crtc(priv, fd, scrpriv->connector); if (scrpriv->crtc_id < 0) { goto fail; } @@ -577,6 +653,9 @@ static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) goto fail; } + /* Mark the connector and crtc used */ + modesetting_claim_connector_crtc(priv, scrpriv->conn_id, scrpriv->crtc_id); + return TRUE; fail: @@ -1165,6 +1244,8 @@ void msCardFini(KdCardInfo * card) struct gbm_device *gbm = priv->gbm; int fd = gbm_device_get_fd(gbm); + free(priv->used_crtcs); + free(priv->used_connectors); drmModeFreeResources(priv->resources); gbm_device_destroy(gbm); close(fd); diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 67cf5fd6e6c..050bc8343ad 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -19,6 +19,12 @@ typedef struct _msPriv { struct gbm_device *gbm; drmModeRes *resources; + + int *used_crtcs; + int num_used_crtcs; + + int num_used_connectors; + uint32_t *used_connectors; #if 0 __u16 red[256]; __u16 green[256]; From fe45c1be7bc0e93ac49c28a6f12f60bcb7ae14cd Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Tue, 15 Sep 2026 23:17:49 +0300 Subject: [PATCH 14/47] kdrive: Don't try to access screen privates for a screen that wasn't initialized Signed-off-by: stefan11111 --- hw/kdrive/src/kdrive.c | 4 +++- hw/kdrive/src/kdrive.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index 43ae6d860ac..d51228e3185 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -169,7 +169,8 @@ void KdSuspend(int ddxAbort) for (card = kdCardInfo; card; card = card->next) { for (screen = card->screenList; screen; screen = screen->next) if (screen->mynum == card->selected && screen->pScreen) - KdDisableScreen(screen->pScreen); + if (screen->initialized) + KdDisableScreen(screen->pScreen); if (card->driver && card->cfuncs->restore) (*card->cfuncs->restore) (card); } @@ -994,6 +995,7 @@ bool KdScreenInit(ScreenPtr pScreen, int argc, char **argv, void *closure) } #endif + screen->initialized = TRUE; return TRUE; } diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h index 880919ff61a..4e88f458570 100644 --- a/hw/kdrive/src/kdrive.h +++ b/hw/kdrive/src/kdrive.h @@ -105,6 +105,7 @@ typedef struct _KdScreenInfo { int subpixel_order; Bool dumb; Bool softCursor; + Bool initialized; /* If KdScreenInit succeeded */ int mynum; xPoint origin; KdFrameBuffer fb; From a45d5673fc674eb58eeea9a5952e0cbd54b6b31b Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Tue, 15 Sep 2026 23:27:22 +0300 Subject: [PATCH 15/47] kdrive: Don't disable input devices if already disabled Reverts and fixes https://github.com/X11Libre/xserver/commit/14912f8a095b2df497d4c3a085ca4d75186d695d Signed-off-by: stefan11111 --- hw/kdrive/os/linux/linux.c | 2 +- hw/kdrive/src/kdrive.c | 14 ++++++-------- hw/kdrive/src/kdrive.h | 4 ++-- hw/kdrive/src/kinput.c | 4 ++++ 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/hw/kdrive/os/linux/linux.c b/hw/kdrive/os/linux/linux.c index 770f670f9d8..924b363aa57 100644 --- a/hw/kdrive/os/linux/linux.c +++ b/hw/kdrive/os/linux/linux.c @@ -177,7 +177,7 @@ LinuxApmNotify(int fd, int mask, void *blockData) LinuxApmRunning = TRUE; } else if (!running && LinuxApmRunning) { - KdSuspend(FALSE); + KdSuspend(); LinuxApmRunning = FALSE; ioctl(fd, cmd, 0); } diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index d51228e3185..0083521dd4f 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -160,7 +160,7 @@ KdDoSwitchCmd(const char *reason) } } -void KdSuspend(int ddxAbort) +void KdSuspend(void) { KdCardInfo *card; KdScreenInfo *screen; @@ -174,16 +174,14 @@ void KdSuspend(int ddxAbort) if (card->driver && card->cfuncs->restore) (*card->cfuncs->restore) (card); } - if (!ddxAbort) { - KdDisableInput(); - } + KdDisableInput(); KdDoSwitchCmd("suspend"); } } -void KdDisableScreens(int ddxAbort) +void KdDisableScreens(void) { - KdSuspend(ddxAbort); + KdSuspend(); if (kdEnabled && (kdOsFuncs->Disable)) kdOsFuncs->Disable(); kdEnabled = FALSE; @@ -247,7 +245,7 @@ void KdProcessSwitch(void) { if (kdEnabled) - KdDisableScreens(FALSE); + KdDisableScreens(); else KdEnableScreens(); } @@ -255,7 +253,7 @@ KdProcessSwitch(void) static void AbortDDX(enum ExitCode error) { - KdDisableScreens(TRUE); + KdDisableScreens(); if (kdOsFuncs) { if (kdEnabled && kdOsFuncs->Disable) (*kdOsFuncs->Disable) (); diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h index 4e88f458570..14fba0ccad6 100644 --- a/hw/kdrive/src/kdrive.h +++ b/hw/kdrive/src/kdrive.h @@ -380,14 +380,14 @@ void KdSetColormap(ScreenPtr pScreen); /* kdrive.c */ extern miPointerScreenFuncRec kdPointerScreenFuncs; -void KdSuspend(int ddxAbort); +void KdSuspend(void); void KdInitScreen(KdScreenInfo * screen, int argc, char **argv); void KdDisableScreen(ScreenPtr pScreen); -void KdDisableScreens(int ddxAbort); +void KdDisableScreens(void); Bool KdEnableScreen(ScreenPtr pScreen); diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c index 76ca085ae51..ba5bb70bed2 100644 --- a/hw/kdrive/src/kinput.c +++ b/hw/kdrive/src/kinput.c @@ -220,6 +220,10 @@ KdDisableInput(void) KdPointerInfo *pi; int found = 0, i = 0; + if (!kdInputEnabled) { + return; + } + /** * When we're doing something that causes a vt switch, * if that action is a key press, the X server doesn't see From a8055e1c8c32bd0246ba5676639124b490e4ae01 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Tue, 15 Sep 2026 23:44:45 +0300 Subject: [PATCH 16/47] kdrive/modesetting: Use the scanout video card for rendering even when probed and not explcit Signed-off-by: stefan11111 --- hw/kdrive/modesetting/ms_glamor.c | 8 +++++++- hw/kdrive/modesetting/msinit.c | 7 +------ hw/kdrive/src/kglamor.c | 4 +++- hw/kdrive/src/kglamor.h | 1 + 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 1882f4a006f..bc71aa63515 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -16,6 +16,7 @@ msInitAccel(ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; MsScreenConf *config = screen->closure; + msPriv *priv = screen->card->driver; int caps = GLAMOR_EGL_CAP_NONE; if (screen->rate > 60) { @@ -23,7 +24,12 @@ msInitAccel(ScreenPtr pScreen) } if (!config->glamor_info.dri_path) { - config->glamor_info.dri_path = screen->card->closure; + config->glamor_info.dri_fd = dup(gbm_device_get_fd(priv->gbm)); + if (config->glamor_info.dri_fd >= 0) { + config->glamor_info.want_dri_fd = TRUE; + } else { + config->glamor_info.dri_path = screen->card->closure; + } } if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 1d9fc2322cb..a312cd0eca9 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -256,12 +256,7 @@ ddxProcessArgument(int argc, char **argv, int i) if (!strcmp(argv[i], "-dev")) { if ((i + 1 < argc) && (argv[i + 1][0] != '-')) { -#if 0 /* Handled by InitScreen */ - msCurrScreen->dev_path = argv[i + 1]; - if (!msCurrScreen->glamor_info.dri_path) { - msCurrScreen->glamor_info.dri_path = msCurrScreen->dev_path; - } -#endif + /* Handled by InitScreen */ return 2; } UseMsg(); diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index afae5c50c43..6ad2f659928 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -95,7 +95,9 @@ KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps) *caps = GLAMOR_EGL_CAP_NONE; - if (info->dri_path) { + if (info->want_dri_fd) { + /* do nothing */ + } else if (info->dri_path) { info->dri_fd = open(info->dri_path, O_RDWR); if (info->dri_fd < 0) { LogMessage(X_WARNING, "KGlamor(%d): Could not open %s: %s\n", pScreen->myNum, info->dri_path, strerror(errno)); diff --git a/hw/kdrive/src/kglamor.h b/hw/kdrive/src/kglamor.h index 4656abe334e..745469d4de1 100644 --- a/hw/kdrive/src/kglamor.h +++ b/hw/kdrive/src/kglamor.h @@ -18,6 +18,7 @@ typedef struct { Bool force_es; /* If glamor should only create gles contexts */ /* Handled by KdGlamorInit */ + Bool want_dri_fd; /* If dri_fd is already populated */ int fake_rate; /* If a fake refresh rate should be used by present */ Bool drop_master; /* If KdGlamorInit should call drmDropMaster on the dri fd */ Bool no_xv; /* Disable X-Video support */ From 6bac28f8c7ec2a63f3ddecbc83ca7d537dc13fe4 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 16 Sep 2026 00:12:09 +0300 Subject: [PATCH 17/47] kdrive/os/stub: Add a distinctive XInput name Signed-off-by: stefan11111 --- hw/kdrive/os/stub/kbd.c | 11 +++++++++++ hw/kdrive/os/stub/mouse.c | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/hw/kdrive/os/stub/kbd.c b/hw/kdrive/os/stub/kbd.c index b586a575d82..034e1636c09 100644 --- a/hw/kdrive/os/stub/kbd.c +++ b/hw/kdrive/os/stub/kbd.c @@ -9,6 +9,17 @@ static int StubKeyboardInit(KdKeyboardInfo * ki) { + char *tmp = NULL; + + if (!ki) + return !Success; + + tmp = strdup("Stub keyboard"); + if (tmp) { + free(ki->name); + ki->name = tmp; + } + ki->minScanCode = 8; ki->maxScanCode = 255; return Success; diff --git a/hw/kdrive/os/stub/mouse.c b/hw/kdrive/os/stub/mouse.c index 354052299aa..b7f634ab562 100644 --- a/hw/kdrive/os/stub/mouse.c +++ b/hw/kdrive/os/stub/mouse.c @@ -9,6 +9,17 @@ static Status StubMouseInit(KdPointerInfo * pi) { + char *tmp; + + if (!pi) + return BadImplementation; + + tmp = strdup("Stub Mouse"); + if (tmp) { + free(pi->name); + pi->name = tmp; + } + return Success; } From da9f4524067d961a328d5b71a6faba4d5e2d1c83 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 16 Sep 2026 01:23:53 +0300 Subject: [PATCH 18/47] kdrive/modesetting: Move gbm functions to another file, support more formats Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.c | 277 ++++++++++------------------ hw/kdrive/modesetting/modesetting.h | 17 ++ hw/kdrive/modesetting/ms_gbm.c | 263 ++++++++++++++++++++++++++ 4 files changed, 376 insertions(+), 182 deletions(-) create mode 100644 hw/kdrive/modesetting/ms_gbm.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index e6c2e35da50..c98c43ec504 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -1,6 +1,7 @@ srcs = [ 'modesetting.c', 'msinit.c', + 'ms_gbm.c', '../../stubs/ddxBeforeReset.c', ] diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index cf77fad6e1d..d459dece971 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -14,144 +14,8 @@ #include "kxv.h" #endif -typedef struct { - void *map_data; - void *map_addr; - - uint32_t fb_id; -} gbm_user_data_t; - static Bool msMapFramebuffer(KdScreenInfo * screen); -static inline void* -gbm_bo_get_map(struct gbm_bo *bo) -{ - gbm_user_data_t *data = gbm_bo_get_user_data(bo); - return data ? data->map_addr : NULL; -} - -static void -destroy_user_data(struct gbm_bo *bo, void *_data) -{ - struct gbm_device *gbm = gbm_bo_get_device(bo); - int fd = gbm_device_get_fd(gbm); - gbm_user_data_t* data = _data; - if (!data) { - return; - } - - if (data->fb_id) { - drmModeRmFB(fd, data->fb_id); - } - - if (data->map_data) { - gbm_bo_unmap(bo, data->map_data); - } - - free(data); -} - -static inline int -gbm_bo_map_all(struct gbm_bo *bo, gbm_user_data_t *data) -{ - uint32_t stride = 0; - - if (!bo || !data) { - return FALSE; - } - - if (data->map_addr) { - return TRUE; - } - - uint32_t width = gbm_bo_get_width(bo); - uint32_t height = gbm_bo_get_height(bo); - - /* must be NULL before the map call */ - data->map_data = NULL; - - /* While reading from gpu memory is often very slow, we do allow it */ - data->map_addr = gbm_bo_map(bo, 0, 0, width, height, - GBM_BO_TRANSFER_READ_WRITE, - &stride, &data->map_data); - - return !!data->map_addr; -} - -static inline int -gbm_bo_map_or_free(struct gbm_bo *bo, gbm_user_data_t *data) -{ - if (gbm_bo_map_all(bo, data)) { - return TRUE; - } - - if (bo) { - gbm_bo_destroy(bo); - } - return FALSE; -} - -static inline struct gbm_bo* -gbm_bo_create_and_map_once(struct gbm_device *gbm, - gbm_user_data_t *data, - uint32_t width, uint32_t height, - uint32_t format, uint32_t flags) -{ - struct gbm_bo *ret = NULL; - - if (!data) { - return NULL; - } - - ret = gbm_bo_create(gbm, width, height, format, flags); - if (ret && gbm_bo_map_or_free(ret, data)) { - return ret; - } - - return NULL; -} - -static struct gbm_bo* -gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t width, uint32_t height) -{ - uint32_t format = GBM_FORMAT_XRGB8888; -#if 0 - uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_FRONT_RENDERING; - uint32_t flags2 = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; -#endif - uint32_t flags_dumb = GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE; - - struct gbm_bo *bo = NULL; - -#if 0 /* non-dumb buffers require unmap + map to flush writes, which is far slower than ShadowFB */ - bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags); - if (!bo) { - bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags2); - } -#endif - if (!bo) { - bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags_dumb); - } - - return bo; -} - -static int -gbm_bo_create_fb(struct gbm_bo *bo) -{ - struct gbm_device *gbm = gbm_bo_get_device(bo); - int fd = gbm_device_get_fd(gbm); - - uint32_t width = gbm_bo_get_width(bo); - uint32_t height = gbm_bo_get_height(bo); - uint32_t pitch = gbm_bo_get_stride(bo); - uint32_t handle = gbm_bo_get_handle(bo).u32; - uint32_t fb_id = 0; - - int ret = drmModeAddFB(fd, width, height, 24, 32, pitch, handle, &fb_id); - return ret ? 0 : fb_id; -} - static int modesetting_grade_mode(drmModeModeInfo *mode, uint32_t req_w, uint32_t req_h, uint32_t req_rate) { @@ -330,41 +194,25 @@ modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn) static struct gbm_bo* modesetting_open(msPriv *priv, KdScreenInfo *screen) { - struct gbm_device *gbm = priv->gbm; - struct gbm_bo *ret = NULL; - gbm_user_data_t *data = NULL; - - data = calloc(1, sizeof(*data)); - if (!data) { - goto fail; - } - - ret = gbm_bo_create_and_map(gbm, data, screen->width, screen->height); - if (!ret) { - goto fail; - } + msScrPriv *scrpriv = screen->driver; - gbm_bo_set_user_data(ret, data, destroy_user_data); + struct gbm_bo *ret = NULL; + uint32_t format; - data->fb_id = gbm_bo_create_fb(ret); - if (!data->fb_id) { - goto fail; + if (scrpriv->front) { + Bool want_map = !!gbm_bo_get_map(scrpriv->front); + format = gbm_bo_get_format(scrpriv->front); + return gbm_create_front_bo(priv->gbm, want_map, screen->width, screen->height, format); } - return ret; - -fail: + format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, FALSE /* rb_swap */); + ret = gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format); if (ret) { - gbm_bo_destroy(ret); - /* destroy_user_data takes care of the rest */ - return NULL; - } - - if (data) { - free(data); + return ret; } - return NULL; + format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, TRUE /* rb_swap */); + return gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format); } static Bool @@ -605,6 +453,8 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) { msPriv *priv = screen->card->driver; int fd = gbm_device_get_fd(priv->gbm); + uint32_t format; + Bool rb_swap = FALSE; scrpriv->connector = modesetting_find_connector(priv, fd, &scrpriv->conn_id); if (!scrpriv->connector) { @@ -639,14 +489,75 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = gbm_bo_get_height(scrpriv->front); screen->rate = scrpriv->mode ? scrpriv->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ - /* GBM_FORMAT_XRGB8888 */ - screen->fb.visuals = (1 << TrueColor); - screen->fb.redMask = 0xff << 16; - screen->fb.greenMask = 0xff << 8; - screen->fb.blueMask = 0xff; + format = gbm_bo_get_format(scrpriv->front); + + switch (format) { + case GBM_FORMAT_C8: + case GBM_FORMAT_R8: + screen->fb.depth = 8; + screen->fb.bitsPerPixel = 8; + screen->fb.visuals = (1 << GrayScale); + screen->fb.redMask = 0xff; + screen->fb.greenMask = 0x00; + screen->fb.blueMask = 0x00; + break; + case GBM_FORMAT_XBGR1555: + rb_swap = TRUE; + case GBM_FORMAT_XRGB1555: + screen->fb.depth = 15; + screen->fb.bitsPerPixel = 16; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0x1f << 10; + screen->fb.greenMask = 0x1f << 5; + screen->fb.blueMask = 0x1f; + break; + case GBM_FORMAT_BGR565: + rb_swap = TRUE; + case GBM_FORMAT_RGB565: + screen->fb.depth = 16; + screen->fb.bitsPerPixel = 16; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0x1f << 11; + screen->fb.greenMask = 0x3f << 5; + screen->fb.blueMask = 0x1f; + break; + case GBM_FORMAT_BGR888: + rb_swap = TRUE; + case GBM_FORMAT_RGB888: + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 24; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0xff << 16; + screen->fb.greenMask = 0xff << 8; + screen->fb.blueMask = 0xff; + break; + case GBM_FORMAT_XBGR8888: + rb_swap = TRUE; + case GBM_FORMAT_XRGB8888: + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 32; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0xff << 16; + screen->fb.greenMask = 0xff << 8; + screen->fb.blueMask = 0xff; + break; + case GBM_FORMAT_XBGR2101010: + rb_swap = TRUE; + case GBM_FORMAT_XRGB2101010: + screen->fb.depth = 30; + screen->fb.bitsPerPixel = 32; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0x3ff << 20; + screen->fb.greenMask = 0x3ff <<10; + screen->fb.blueMask = 0x3ff; + break; + } - screen->fb.depth = 24; - screen->fb.bitsPerPixel = 32; + if (rb_swap) { + int tmp = screen->fb.blueMask; + screen->fb.blueMask = screen->fb.redMask; + screen->fb.redMask = tmp; + } scrpriv->randr = screen->randr; if (!msMapFramebuffer(screen)) { @@ -777,7 +688,9 @@ static Bool msSetShadow(ScreenPtr pScreen) window = msWindowLinear; update = 0; - if (scrpriv->randr) + if (screen->fb.bitsPerPixel == 24) + update = shadowUpdate32to24; + else if (scrpriv->randr) update = shadowUpdateRotatePacked; else update = shadowUpdatePacked; @@ -1044,14 +957,14 @@ msBlockHandler(void *blockData, void *timeout) RegionPtr dirty; drmModeClip full_clip; struct gbm_device *gbm; - gbm_user_data_t *data; + uint32_t fb_id; int fd; uint32_t width; uint32_t height; unsigned num_cliprects; gbm = gbm_bo_get_device(priv->front); - data = gbm_bo_get_user_data(priv->front); + fb_id = gbm_bo_get_fb(priv->front); fd = gbm_device_get_fd(gbm); width = gbm_bo_get_width(priv->front); @@ -1081,12 +994,12 @@ msBlockHandler(void *blockData, void *timeout) } /* TODO query connector property to see if this is needed */ - ret = drmModeDirtyFB(fd, data->fb_id, clip, num_cliprects); + ret = drmModeDirtyFB(fd, fb_id, clip, num_cliprects); /* if we're swamping it with work, try one at a time */ if (ret) { for (int i = 0; i < num_cliprects; i++) { - ret = drmModeDirtyFB(fd, data->fb_id, &clip[i], 1); + ret = drmModeDirtyFB(fd, fb_id, &clip[i], 1); if (ret) { break; } @@ -1104,7 +1017,7 @@ msBlockHandler(void *blockData, void *timeout) return; bail: - drmModeDirtyFB(fd, data->fb_id, &full_clip, 1); + drmModeDirtyFB(fd, fb_id, &full_clip, 1); if (priv->damage) { DamageEmpty(priv->damage); } @@ -1122,11 +1035,11 @@ Bool msCreateResources(ScreenPtr pScreen) msScrPriv *priv = screen->driver; PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); struct gbm_device *gbm; - gbm_user_data_t *data; + uint32_t fb_id; int fd; gbm = gbm_bo_get_device(priv->front); - data = gbm_bo_get_user_data(priv->front); + fb_id = gbm_bo_get_fb(priv->front); fd = gbm_device_get_fd(gbm); if (!msSetShadow(pScreen)) { @@ -1134,7 +1047,7 @@ Bool msCreateResources(ScreenPtr pScreen) } /* Damage tracking not supported/needed */ - if (drmModeDirtyFB(fd, data->fb_id, NULL, 0) && + if (drmModeDirtyFB(fd, fb_id, NULL, 0) && ((errno == EINVAL) || (errno == ENOSYS))) { return TRUE; } @@ -1171,7 +1084,7 @@ Bool msEnable(ScreenPtr pScreen) msScrPriv *priv = screen->driver; struct gbm_device *gbm = gbm_bo_get_device(priv->front); - gbm_user_data_t *data = gbm_bo_get_user_data(priv->front); + uint32_t fb_id = gbm_bo_get_fb(priv->front); int fd = gbm_device_get_fd(gbm); drmSetMaster(fd); @@ -1179,7 +1092,7 @@ Bool msEnable(ScreenPtr pScreen) if (!priv->mode) { priv->mode = modesetting_find_mode(priv->connector, screen->width, screen->height, screen->rate); } - if (priv->mode && drmModeSetCrtc(fd, priv->crtc_id, data->fb_id, 0, 0, &priv->conn_id, 1, priv->mode)) { + if (priv->mode && drmModeSetCrtc(fd, priv->crtc_id, fb_id, 0, 0, &priv->conn_id, 1, priv->mode)) { return FALSE; } diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 050bc8343ad..ecdbcd12649 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -90,4 +90,21 @@ void msFiniAccel(ScreenPtr screen); void msCloseScreen(ScreenPtr pScreen); +/* ms_gbm.c */ + +void* +gbm_bo_get_map(struct gbm_bo *bo); + +uint32_t +gbm_bo_get_fb(struct gbm_bo *bo); + +uint32_t +gbm_front_format_for_depth(int depth, int bpp, Bool rb_swap); + +int +gbm_format_get_depth(uint32_t format); + +struct gbm_bo* +gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format); + #endif /* _MODESETTING_H_ */ diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c new file mode 100644 index 00000000000..ec14a8d6e83 --- /dev/null +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -0,0 +1,263 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +/* TODO: Stuff that should be in msutil */ + +typedef struct { + void *map_data; + void *map_addr; + + uint32_t fb_id; +} gbm_user_data_t; + +void* +gbm_bo_get_map(struct gbm_bo *bo) +{ + gbm_user_data_t *data = gbm_bo_get_user_data(bo); + return data ? data->map_addr : NULL; +} + +uint32_t +gbm_bo_get_fb(struct gbm_bo *bo) +{ + gbm_user_data_t *data = gbm_bo_get_user_data(bo); + return data ? data->fb_id : 0; +} + +static void +destroy_user_data(struct gbm_bo *bo, void *_data) +{ + struct gbm_device *gbm = gbm_bo_get_device(bo); + int fd = gbm_device_get_fd(gbm); + gbm_user_data_t* data = _data; + if (!data) { + return; + } + + if (data->fb_id) { + drmModeRmFB(fd, data->fb_id); + } + + if (data->map_data) { + gbm_bo_unmap(bo, data->map_data); + } + + free(data); +} + +static inline int +gbm_bo_map_all(struct gbm_bo *bo, gbm_user_data_t *data) +{ + uint32_t stride = 0; + + if (!bo || !data) { + return FALSE; + } + + if (data->map_addr) { + return TRUE; + } + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + + /* must be NULL before the map call */ + data->map_data = NULL; + + /* While reading from gpu memory is often very slow, we do allow it */ + data->map_addr = gbm_bo_map(bo, 0, 0, width, height, + GBM_BO_TRANSFER_READ_WRITE, + &stride, &data->map_data); + + return !!data->map_addr; +} + +static inline int +gbm_bo_map_or_free(struct gbm_bo *bo, gbm_user_data_t *data) +{ + if (gbm_bo_map_all(bo, data)) { + return TRUE; + } + + if (bo) { + gbm_bo_destroy(bo); + } + return FALSE; +} + +static inline struct gbm_bo* +gbm_bo_create_and_map_once(struct gbm_device *gbm, + gbm_user_data_t *data, + uint32_t width, uint32_t height, + uint32_t format, uint32_t flags) +{ + struct gbm_bo *ret = NULL; + + if (!data) { + return NULL; + } + + ret = gbm_bo_create(gbm, width, height, format, flags); + if (ret && gbm_bo_map_or_free(ret, data)) { + return ret; + } + + return NULL; +} + +static struct gbm_bo* +gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t width, uint32_t height, uint32_t format) +{ +#if 0 + uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_FRONT_RENDERING; + uint32_t flags2 = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; +#endif + uint32_t flags_dumb = GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE; + + struct gbm_bo *bo = NULL; + +#if 0 /* non-dumb buffers require unmap + map to flush writes, which is far slower than ShadowFB */ + bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags); + if (!bo) { + bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags2); + } +#endif + if (!bo) { + bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags_dumb); + } + + return bo; +} + +static int +gbm_bo_create_fb(struct gbm_bo *bo) +{ + struct gbm_device *gbm = gbm_bo_get_device(bo); + int fd = gbm_device_get_fd(gbm); + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t pitch = gbm_bo_get_stride(bo); + uint32_t handle = gbm_bo_get_handle(bo).u32; + uint32_t fb_id = 0; + + uint32_t format = gbm_bo_get_format(bo); + int depth = gbm_format_get_depth(format); + int bpp = gbm_bo_get_bpp(bo); + + int ret = drmModeAddFB(fd, width, height, depth, bpp, pitch, handle, &fb_id); + return ret ? 0 : fb_id; +} + +static uint32_t +gbm_front_format_for_depth_swap(int depth, int bpp) +{ + switch (depth) { + case 8: + return GBM_FORMAT_C8; + case 15: + return GBM_FORMAT_XBGR1555; + case 16: + return GBM_FORMAT_BGR565; + case 30: + return GBM_FORMAT_XBGR2101010; + case 24: + default: + return (bpp == 24) ? GBM_FORMAT_BGR888 : GBM_FORMAT_XBGR8888; + } + +} + +uint32_t +gbm_front_format_for_depth(int depth, int bpp, Bool rb_swap) +{ + if (rb_swap) { + return gbm_front_format_for_depth_swap(depth, bpp); + } + + switch (depth) { + case 8: + return GBM_FORMAT_R8; + case 15: + return GBM_FORMAT_XRGB1555; + case 16: + return GBM_FORMAT_RGB565; + case 30: + return GBM_FORMAT_XRGB2101010; + case 24: + default: + return (bpp == 24) ? GBM_FORMAT_RGB888 : GBM_FORMAT_XRGB8888; + } +} + +int +gbm_format_get_depth(uint32_t format) +{ + switch (format) { + case GBM_FORMAT_R8: + case GBM_FORMAT_C8: + return 8; + case GBM_FORMAT_XRGB1555: + case GBM_FORMAT_XBGR1555: + return 15; + case GBM_FORMAT_RGB565: + case GBM_FORMAT_BGR565: + return 16; + case GBM_FORMAT_RGB888: + case GBM_FORMAT_BGR888: + case GBM_FORMAT_XRGB8888: + case GBM_FORMAT_XBGR8888: + default: + return 24; + case GBM_FORMAT_XRGB2101010: + case GBM_FORMAT_XBGR2101010: + return 30; + } +} + +struct gbm_bo* +gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format) +{ + struct gbm_bo *ret = NULL; + gbm_user_data_t *data = NULL; + + (void)do_map; /* Ignored for now */ + + data = calloc(1, sizeof(*data)); + if (!data) { + goto fail; + } + + ret = gbm_bo_create_and_map(gbm, data, width, height, format); + if (!ret) { + goto fail; + } + + gbm_bo_set_user_data(ret, data, destroy_user_data); + + data->fb_id = gbm_bo_create_fb(ret); + if (!data->fb_id) { + goto fail; + } + + return ret; + +fail: + if (ret) { + gbm_bo_destroy(ret); + /* destroy_user_data takes care of the rest */ + return NULL; + } + + if (data) { + free(data); + } + + return NULL; +} From eac9e8141318897f9a4a3bef3170acccfa053276 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 16 Sep 2026 21:51:22 +0300 Subject: [PATCH 19/47] kdrive: Implement `-videoTest` option The option was parsed, but not implemented Signed-off-by: stefan11111 --- hw/kdrive/src/kdrive.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index 0083521dd4f..6772e2857e0 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -80,7 +80,7 @@ KdDepths kdDepths[] = { DevPrivateKeyRec kdScreenPrivateKeyRec; Bool kdVideoTest; -unsigned long kdVideoTestTime; +unsigned long kdVideoTestTime = 5000; /* miliseconds */ Bool kdEmulateMiddleButton; Bool kdRawPointerCoordinates; Bool kdDisableZaphod; @@ -107,6 +107,13 @@ static Bool kdCaughtSignal = FALSE; */ const KdOsFuncs *kdOsFuncs = NULL; +static CARD32 +KdVideoTestFunc(OsTimerPtr timer, CARD32 time, void *arg) +{ + dispatchException |= DE_TERMINATE; + return 0; +} + static void KdDPMS(ScreenPtr pScreen, int mode) { @@ -971,6 +978,9 @@ bool KdScreenInit(ScreenPtr pScreen, int argc, char **argv, void *closure) kdEnabled = TRUE; if (screen->mynum == card->selected) { + if (kdVideoTest) { + TimerSet(NULL, 0, kdVideoTestTime, KdVideoTestFunc, NULL); + } if (card->cfuncs->preserve) (*card->cfuncs->preserve) (card); if (card->cfuncs->enable) From 71de753516bab8c12551427f8deea455a83d2fe9 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 16 Sep 2026 23:02:09 +0300 Subject: [PATCH 20/47] kdrive/modesetting: Try to use `drmModeAddFB2{,WithModifiers}` Fall back to `drmModeAddFB` if that fails Signed-off-by: stefan11111 --- hw/kdrive/modesetting/ms_gbm.c | 45 +++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index ec14a8d6e83..adc5c370a8b 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -143,15 +143,54 @@ gbm_bo_create_fb(struct gbm_bo *bo) uint32_t width = gbm_bo_get_width(bo); uint32_t height = gbm_bo_get_height(bo); - uint32_t pitch = gbm_bo_get_stride(bo); - uint32_t handle = gbm_bo_get_handle(bo).u32; uint32_t fb_id = 0; + Bool need_check = FALSE; uint32_t format = gbm_bo_get_format(bo); int depth = gbm_format_get_depth(format); int bpp = gbm_bo_get_bpp(bo); + int num_planes = gbm_bo_get_plane_count(bo); + int ret; + + uint32_t handles[4] = {0}; + uint32_t pitches[4] = {0}; + uint32_t offsets[4] = {0}; + uint64_t modifiers[4] = {0}; + uint64_t modifier = gbm_bo_get_modifier(bo); + + for (int i = 0; i < num_planes; i++) { + handles[i] = gbm_bo_get_handle_for_plane(bo, i).u32; + pitches[i] = gbm_bo_get_stride_for_plane(bo, i); + offsets[i] = gbm_bo_get_offset(bo, i); + modifiers[i] = modifier; + } + + ret = drmModeAddFB2WithModifiers(fd, width, height, format, handles, pitches, offsets, + modifiers, &fb_id, DRM_MODE_FB_MODIFIERS); + if (ret) { + need_check = TRUE; + ret = drmModeAddFB2(fd, width, height, format, handles, pitches, offsets, &fb_id, 0); + } + if (ret && num_planes == 1) { + ret = drmModeAddFB(fd, width, height, depth, bpp, pitches[0], handles[0], &fb_id); + } + + if (!ret && need_check) { + /* Check that we didn't lose format + modifier information */ + drmModeFB2Ptr fb_ptr; + + fb_ptr = drmModeGetFB2(fd, fb_id); + if (fb_ptr) { + if (fb_ptr->pixel_format != format || + fb_ptr->modifier != modifier) { + drmModeFreeFB2(fb_ptr); + drmModeRmFB(fd, fb_id); + return 0; + } + drmModeFreeFB2(fb_ptr); + } + } - int ret = drmModeAddFB(fd, width, height, depth, bpp, pitch, handle, &fb_id); return ret ? 0 : fb_id; } From 044092d3f0e19a272802e59b79ab2482f5b1876d Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Wed, 16 Sep 2026 15:11:10 +0300 Subject: [PATCH 21/47] kdrive/modesetting: Tile the front buffer Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 115 +++++++++++++++++++--------- hw/kdrive/modesetting/modesetting.h | 19 +++++ hw/kdrive/modesetting/ms_gbm.c | 36 ++++++++- hw/kdrive/modesetting/ms_glamor.c | 100 ++++++++++++++++++++++-- 4 files changed, 222 insertions(+), 48 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index d459dece971..1d9173a40f1 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -14,8 +14,6 @@ #include "kxv.h" #endif -static Bool msMapFramebuffer(KdScreenInfo * screen); - static int modesetting_grade_mode(drmModeModeInfo *mode, uint32_t req_w, uint32_t req_h, uint32_t req_rate) { @@ -191,28 +189,57 @@ modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn) } -static struct gbm_bo* -modesetting_open(msPriv *priv, KdScreenInfo *screen) +struct gbm_bo* +modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) { - msScrPriv *scrpriv = screen->driver; - struct gbm_bo *ret = NULL; - uint32_t format; + uint32_t format, format_swap; - if (scrpriv->front) { - Bool want_map = !!gbm_bo_get_map(scrpriv->front); - format = gbm_bo_get_format(scrpriv->front); - return gbm_create_front_bo(priv->gbm, want_map, screen->width, screen->height, format); - } + while (!ret) { + format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, FALSE /* rb_swap */); + format_swap = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, TRUE /* rb_swap */); - format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, FALSE /* rb_swap */); - ret = gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format); - if (ret) { - return ret; +#ifdef GLAMOR + if (!need_map) { + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, FALSE /* do map */, screen->width, screen->height, format); + } + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, FALSE /* do map */, screen->width, screen->height, format_swap); + } + } +#endif + + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format); + } + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format_swap); + } + + if (!ret) { + int old_depth = screen->fb.depth; + if (screen->fb.depth > 30) { + screen->fb.depth = 30; + screen->fb.bitsPerPixel = 24; + } else if (screen->fb.depth > 24) { + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 24; + } else if (screen->fb.depth > 16) { + screen->fb.depth = 16; + screen->fb.bitsPerPixel = 16; + } else if (screen->fb.depth > 8) { + screen->fb.depth = 8; + screen->fb.bitsPerPixel = 8; + } else { + break; + } + LogMessage(X_ERROR, "Xmodesetting(card: %d, screen: %d): Cannot use a depth %d front, trying again with depth %d\n", + screen->card->mynum, screen->mynum, old_depth, screen->fb.depth); + } } - format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, TRUE /* rb_swap */); - return gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format); + return ret; } static Bool @@ -224,42 +251,37 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) msScrPriv *scrpriv = screen->driver; struct gbm_bo *old_front; drmModeModeInfo *old_mode; - int oldwidth, oldheight, oldrate; old_front = scrpriv->front; old_mode = scrpriv->mode; - oldwidth = screen->width; - oldheight = screen->height; - oldrate = screen->rate; - - screen->width = width; - screen->height = height; - screen->rate = rate; /* Find the mode */ - scrpriv->mode = modesetting_find_mode(scrpriv->connector, screen->width, screen->height, screen->rate); + scrpriv->mode = modesetting_find_mode(scrpriv->connector, width, height, rate); if (!scrpriv->mode) { goto bail; } /* Create a new front with the new sizes */ - if (oldwidth != screen->width || - oldheight != screen->height) { - scrpriv->front = modesetting_open(priv, screen); + if (width != screen->width || + height != screen->height) { + uint32_t format = gbm_bo_get_format(scrpriv->front); + Bool do_map = !!gbm_bo_get_map(scrpriv->front); + scrpriv->front = gbm_create_front_bo(priv->gbm, do_map, width, height, format); if (!scrpriv->front) { goto bail; } gbm_bo_destroy(old_front); } + + screen->width = width; + screen->height = height; + screen->rate = rate; return TRUE; bail: scrpriv->front = old_front; scrpriv->mode = old_mode; - screen->width = oldwidth; - screen->height = oldheight; - screen->rate = oldrate; return FALSE; } @@ -458,11 +480,15 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) scrpriv->connector = modesetting_find_connector(priv, fd, &scrpriv->conn_id); if (!scrpriv->connector) { + LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not find a usable connector\n", + screen->card->mynum, screen->mynum); goto fail; } scrpriv->crtc_id = modeseting_find_crtc(priv, fd, scrpriv->connector); if (scrpriv->crtc_id < 0) { + LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not find a suitable crtc\n", + screen->card->mynum, screen->mynum); goto fail; } @@ -480,8 +506,10 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; } - scrpriv->front = modesetting_open(priv, screen); + scrpriv->front = modesetting_open(priv, screen, screen->dumb /* need_map */); if (!scrpriv->front) { + LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not create a front buffer\n", + screen->card->mynum, screen->mynum); goto fail; } @@ -615,7 +643,8 @@ static void *msWindowLinear(ScreenPtr pScreen, return mem + row * (*size) + offset; } -static Bool msMapFramebuffer(KdScreenInfo * screen) +Bool +msMapFramebuffer(KdScreenInfo * screen) { msScrPriv *scrpriv = screen->driver; KdPointerMatrix m; @@ -623,7 +652,9 @@ static Bool msMapFramebuffer(KdScreenInfo * screen) unsigned long stride = gbm_bo_get_stride(scrpriv->front); - if (config->shadow >= 0) { + if (!gbm_bo_get_map(scrpriv->front)) { + scrpriv->shadow = FALSE; + } else if (config->shadow >= 0) { scrpriv->shadow = config->shadow; } else if (scrpriv->randr != RR_Rotate_0) { scrpriv->shadow = TRUE; @@ -671,13 +702,15 @@ static void msSetScreenSizes(ScreenPtr pScreen) } } -static Bool msUnmapFramebuffer(KdScreenInfo * screen) +Bool +msUnmapFramebuffer(KdScreenInfo * screen) { KdShadowFbFree(screen); return TRUE; } -static Bool msSetShadow(ScreenPtr pScreen) +Bool +msSetShadow(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -1042,6 +1075,12 @@ Bool msCreateResources(ScreenPtr pScreen) fb_id = gbm_bo_get_fb(priv->front); fd = gbm_device_get_fd(gbm); +#ifdef GLAMOR + if (!msGlamorCreateRes(pScreen)) { + return FALSE; + } +#endif + if (!msSetShadow(pScreen)) { return FALSE; } diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index ecdbcd12649..d027c10d4b9 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -43,6 +43,9 @@ typedef struct _msScrPriv { Rotation randr; Bool blockHandler; Bool shadow; + + Bool error; + Bool setPixmapBits; } msScrPriv; typedef struct _msScreenConf { @@ -79,6 +82,10 @@ void msScreenFini(KdScreenInfo * screen); void msCardFini(KdCardInfo * card); #ifdef GLAMOR +/* ms_glamor.c */ + +Bool msGlamorCreateRes(ScreenPtr pScreen); + Bool msInitAccel(ScreenPtr screen); void msEnableAccel(ScreenPtr screen); @@ -90,6 +97,15 @@ void msFiniAccel(ScreenPtr screen); void msCloseScreen(ScreenPtr pScreen); +Bool msMapFramebuffer(KdScreenInfo * screen); + +Bool msUnmapFramebuffer(KdScreenInfo * screen); + +Bool msSetShadow(ScreenPtr pScreen); + +struct gbm_bo* +modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map); + /* ms_gbm.c */ void* @@ -98,6 +114,9 @@ gbm_bo_get_map(struct gbm_bo *bo); uint32_t gbm_bo_get_fb(struct gbm_bo *bo); +Bool +gbm_bo_get_used_modifiers(struct gbm_bo *bo); + uint32_t gbm_front_format_for_depth(int depth, int bpp, Bool rb_swap); diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index adc5c370a8b..e1c447a58ff 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -13,6 +13,8 @@ typedef struct { void *map_data; void *map_addr; + Bool used_modifiers; + uint32_t fb_id; } gbm_user_data_t; @@ -30,6 +32,13 @@ gbm_bo_get_fb(struct gbm_bo *bo) return data ? data->fb_id : 0; } +Bool +gbm_bo_get_used_modifiers(struct gbm_bo *bo) +{ + gbm_user_data_t *data = gbm_bo_get_user_data(bo); + return data ? data->used_modifiers : FALSE; +} + static void destroy_user_data(struct gbm_bo *bo, void *_data) { @@ -135,6 +144,28 @@ gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t wi return bo; } +static struct gbm_bo* +gbm_bo_create_tiled(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format) +{ + struct gbm_bo *bo = NULL; + + /* Used by mesa */ + uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_FRONT_RENDERING; + + /* Used by nvidia */ + uint32_t flags2 = GBM_BO_USE_SCANOUT; + + if (!bo) { + bo = gbm_bo_create(gbm, width, height, format, flags); + } + + if (!bo) { + bo = gbm_bo_create(gbm, width, height, format, flags2); + } + + return bo; +} + static int gbm_bo_create_fb(struct gbm_bo *bo) { @@ -266,14 +297,13 @@ gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_ struct gbm_bo *ret = NULL; gbm_user_data_t *data = NULL; - (void)do_map; /* Ignored for now */ - data = calloc(1, sizeof(*data)); if (!data) { goto fail; } - ret = gbm_bo_create_and_map(gbm, data, width, height, format); + ret = do_map ? gbm_bo_create_and_map(gbm, data, width, height, format) : + gbm_bo_create_tiled(gbm, width, height, format); if (!ret) { goto fail; } diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index bc71aa63515..a7b97240c9d 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -10,6 +10,98 @@ #include "glamor.h" +static Bool +msGlamorMapFront(ScreenPtr pScreen); + +Bool +msGlamorCreateRes(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + PixmapPtr rootPixmap; + Bool ret = TRUE; + + rootPixmap = (*pScreen->GetScreenPixmap)(pScreen); + + if (!gbm_bo_get_map(scrpriv->front)) { + Bool used_modifiers = gbm_bo_get_used_modifiers(scrpriv->front); + ret = !screen->dumb && glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, scrpriv->front, + used_modifiers); + if (ret) { + LogMessage(X_INFO, "Xmodesetting(%d): Using a tiled front buffer\n", pScreen->myNum); + } else { + if (!msGlamorMapFront(pScreen)) { + return FALSE; + } + ret = (*pScreen->ModifyPixmapHeader) (rootPixmap, + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + if (ret) { + LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); + } + } + } else { + LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); + } + + if (ret) { + LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d\n", + pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel); + } + + return ret; +} + +static Bool +msGlamorMapFront(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + msScrPriv oldscr; + + struct gbm_bo *old_front = scrpriv->front; + + LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use tiled gbm front, trying to use a mapped front bo\n", pScreen->myNum); + + oldscr = *scrpriv; + + msUnmapFramebuffer(screen); + + /* Depth >24 requires tiled bo */ + if (screen->fb.depth > 24) { + goto bail; + } + + scrpriv->front = modesetting_open(priv, screen, TRUE /* need_map */); + if (!scrpriv->front) { + goto bail; + } + + if (!msMapFramebuffer(screen)) { + goto bail; + } + + gbm_bo_destroy(old_front); + scrpriv->setPixmapBits = TRUE; + + return TRUE; + +bail: + msUnmapFramebuffer(screen); + *scrpriv = oldscr; + msMapFramebuffer(screen); + scrpriv->error = TRUE; + return FALSE; +} + Bool msInitAccel(ScreenPtr pScreen) { @@ -17,7 +109,6 @@ msInitAccel(ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; MsScreenConf *config = screen->closure; msPriv *priv = screen->card->driver; - int caps = GLAMOR_EGL_CAP_NONE; if (screen->rate > 60) { config->glamor_info.fake_rate = screen->rate; @@ -32,15 +123,10 @@ msInitAccel(ScreenPtr pScreen) } } - if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { + if (!KdGlamorInit(pScreen, &config->glamor_info, NULL)) { return FALSE; } -#if 0 - if (caps & GLAMOR_EGL_CAP_TEXTURE_GBM_BO) { - } -#endif - return TRUE; } From eecefe50029fbcf4843c282d32436b68976e3883 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 17 Sep 2026 01:05:53 +0300 Subject: [PATCH 22/47] kdrive/modesetting: Tighten front buffer allocation checks/fallbacks Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 78 +++++++++++++++++++++++++++-- hw/kdrive/modesetting/ms_glamor.c | 5 -- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 1d9173a40f1..a42b7d28ec1 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -14,6 +14,9 @@ #include "kxv.h" #endif +static Bool +msFdMatch(int fd1, int fd2); + static int modesetting_grade_mode(drmModeModeInfo *mode, uint32_t req_w, uint32_t req_h, uint32_t req_rate) { @@ -192,9 +195,74 @@ modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn) struct gbm_bo* modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) { +#ifdef GLAMOR + MsScreenConf *config = screen->closure; +#endif struct gbm_bo *ret = NULL; uint32_t format, format_swap; + /* + * XXX This all simplifies with modifier support + * + * Just query the renderable modifiers on the render card, + * and allocate a gbm bo on the scanout card using those modifiers. + * + * If that fails, fall back to dumb buffers. + */ + +#ifdef GLAMOR + if (screen->dumb) { + need_map = TRUE; + } else if (config->glamor_info.dri_path) { + /* + * Until modifier support, we want to be conservative here. + * + * If the render card is different fron the scanout card, assume the modifier sets are disjoint. + * If the cards are the same, and it is from nvidia, and the gbm backend is mesa or dumb, + * assume that buffers are not renderable. + */ + int dri_fd = open(config->glamor_info.dri_path, O_RDWR); + if (!msFdMatch(gbm_device_get_fd(priv->gbm), dri_fd)) { + need_map = TRUE; + } + + if (dri_fd >= 0) { + close(dri_fd); + } + } else { + drmVersionPtr version; + Bool is_nvidia = TRUE; + Bool backend_is_mesa = FALSE; + Bool linear_only = FALSE; + const char *backend_name; + + version = drmGetVersion(gbm_device_get_fd(priv->gbm)); + if (version) { + is_nvidia = !version->name || !strcmp(version->name, "nvidia-drm"); + drmFreeVersion(version); + } + backend_name = gbm_device_get_backend_name(priv->gbm); + if (!backend_name) { + linear_only = TRUE; + } else if (!strcmp(backend_name, "dumb")) { + linear_only = TRUE; + } else if (!strcmp(backend_name, "drm")) { + backend_is_mesa = TRUE; + } + + /** + * Nvidia's egl libraries do not allow creating GL_TEXTURE_2D textures from linear buffers. + * + * See: https://gitlab.freedesktop.org/xorg/xserver/-/work_items/1444 + */ + if (is_nvidia) { + if (linear_only || backend_is_mesa) { + need_map = TRUE; + } + } + } +#endif + while (!ret) { format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, FALSE /* rb_swap */); format_swap = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, TRUE /* rb_swap */); @@ -219,10 +287,14 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) if (!ret) { int old_depth = screen->fb.depth; + int old_bpp = screen->fb.bitsPerPixel; if (screen->fb.depth > 30) { screen->fb.depth = 30; screen->fb.bitsPerPixel = 24; } else if (screen->fb.depth > 24) { + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 32; + } else if (screen->fb.depth == 24 && screen->fb.bitsPerPixel == 32) { screen->fb.depth = 24; screen->fb.bitsPerPixel = 24; } else if (screen->fb.depth > 16) { @@ -234,8 +306,8 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) } else { break; } - LogMessage(X_ERROR, "Xmodesetting(card: %d, screen: %d): Cannot use a depth %d front, trying again with depth %d\n", - screen->card->mynum, screen->mynum, old_depth, screen->fb.depth); + LogMessage(X_ERROR, "Xmodesetting(card: %d, screen: %d): Cannot use a depth %d/%d front, trying again with depth %d/%d\n", + screen->card->mynum, screen->mynum, old_depth, old_bpp, screen->fb.depth, screen->fb.bitsPerPixel); } } @@ -506,7 +578,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; } - scrpriv->front = modesetting_open(priv, screen, screen->dumb /* need_map */); + scrpriv->front = modesetting_open(priv, screen, FALSE /* need_map */); if (!scrpriv->front) { LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not create a front buffer\n", screen->card->mynum, screen->mynum); diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index a7b97240c9d..7738f16bdc7 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -75,11 +75,6 @@ msGlamorMapFront(ScreenPtr pScreen) msUnmapFramebuffer(screen); - /* Depth >24 requires tiled bo */ - if (screen->fb.depth > 24) { - goto bail; - } - scrpriv->front = modesetting_open(priv, screen, TRUE /* need_map */); if (!scrpriv->front) { goto bail; From ccfa8737f56d9074cb3798077162e2d3e94a59c8 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 17 Sep 2026 01:23:34 +0300 Subject: [PATCH 23/47] kdrive/modesetting: Implement DPMS support Also some cosmetic changes Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 69 ++++++++++++++++++----------- hw/kdrive/modesetting/msinit.c | 5 ++- 2 files changed, 46 insertions(+), 28 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index a42b7d28ec1..7bbcd9fe256 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -358,7 +358,8 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) return FALSE; } -static Bool msInitialize(KdCardInfo * card, msPriv * priv) +static Bool +msInitialize(KdCardInfo * card, msPriv * priv) { const char *dev_path = card->closure; int fd; @@ -681,7 +682,8 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) return FALSE; } -Bool msScreenInit(KdScreenInfo * screen) +Bool +msScreenInit(KdScreenInfo * screen) { msScrPriv *scrpriv; @@ -698,9 +700,10 @@ Bool msScreenInit(KdScreenInfo * screen) return TRUE; } -static void *msWindowLinear(ScreenPtr pScreen, - CARD32 row, - CARD32 offset, int mode, CARD32 * size, void *closure) +static void* +msWindowLinear(ScreenPtr pScreen, + CARD32 row, + CARD32 offset, int mode, CARD32 * size, void *closure) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -755,7 +758,8 @@ msMapFramebuffer(KdScreenInfo * screen) return TRUE; } -static void msSetScreenSizes(ScreenPtr pScreen) +static void +msSetScreenSizes(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -802,7 +806,8 @@ msSetShadow(ScreenPtr pScreen) return KdShadowSet(pScreen, scrpriv->randr, update, window); } -static Bool msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) +static Bool +msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -963,7 +968,8 @@ msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) return FALSE; } -static Bool msRandRInit(ScreenPtr pScreen) +static Bool +msRandRInit(ScreenPtr pScreen) { rrScrPrivPtr pScrPriv; int mmWidth, mmHeight; @@ -993,13 +999,15 @@ static Bool msRandRInit(ScreenPtr pScreen) return TRUE; } -Bool msInitScreen(ScreenPtr pScreen) +Bool +msInitScreen(ScreenPtr pScreen) { pScreen->CreateColormap = fbInitializeColormap; return TRUE; } -Bool msFinishInitScreen(ScreenPtr pScreen) +Bool +msFinishInitScreen(ScreenPtr pScreen) { if (!shadowSetup(pScreen)) { return FALSE; @@ -1133,7 +1141,8 @@ msWakeupHandler(void *blockData, int result) { } -Bool msCreateResources(ScreenPtr pScreen) +Bool +msCreateResources(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -1184,11 +1193,13 @@ Bool msCreateResources(ScreenPtr pScreen) return TRUE; } -void msPreserve(KdCardInfo * card) +void +msPreserve(KdCardInfo * card) { } -Bool msEnable(ScreenPtr pScreen) +Bool +msEnable(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -1214,23 +1225,26 @@ Bool msEnable(ScreenPtr pScreen) return TRUE; } -#if 0 -Bool msDPMS(ScreenPtr pScreen, int mode) +Bool +msDPMS(ScreenPtr pScreen, int mode) { KdScreenPriv(pScreen); - msPriv *priv = pScreenPriv->card->driver; - static int oldmode = -1; + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; - if (mode == oldmode) - return TRUE; + struct gbm_device *gbm = gbm_bo_get_device(priv->front); + uint32_t fb_id = gbm_bo_get_fb(priv->front); + int fd = gbm_device_get_fd(gbm); - /* TODO: implement dpms */ + if (mode == KD_DPMS_NORMAL) { + return !priv->mode || !drmModeSetCrtc(fd, priv->crtc_id, fb_id, 0, 0, &priv->conn_id, 1, priv->mode); + } - return FALSE; + return !drmModeSetCrtc(fd, priv->crtc_id, 0, 0, 0, NULL, 0, NULL); } -#endif -void msDisable(ScreenPtr pScreen) +void +msDisable(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -1246,11 +1260,13 @@ void msDisable(ScreenPtr pScreen) drmDropMaster(fd); } -void msRestore(KdCardInfo * card) +void +msRestore(KdCardInfo * card) { } -void msScreenFini(KdScreenInfo * screen) +void +msScreenFini(KdScreenInfo * screen) { msScrPriv *priv = screen->driver; @@ -1261,7 +1277,8 @@ void msScreenFini(KdScreenInfo * screen) screen->driver = NULL; } -void msCardFini(KdCardInfo * card) +void +msCardFini(KdCardInfo * card) { msPriv *priv = card->driver; diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index a312cd0eca9..56078abc0e5 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -276,7 +276,8 @@ ddxProcessArgument(int argc, char **argv, int i) return KdProcessArgument(argc, argv, i); } -void ddxInit(void) +void +ddxInit(void) { msLogInit(); #ifdef KDRIVE_LINUX @@ -294,7 +295,7 @@ KdCardFuncs msFuncs = { .createRes = msCreateResources, .preserve = msPreserve, .enable = msEnable, - .dpms = NULL, /* TODO: implement */ + .dpms = msDPMS, .disable = msDisable, .restore = msRestore, .scrfini = msScreenFini, From 86158149eb743f1a6aaab46237f6173d418936b6 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 18 Sep 2026 01:06:35 +0300 Subject: [PATCH 24/47] kdrive/modesetting: Implement gamma support through RandR Move the gamma-related stuff to a different file Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.c | 63 +++++---- hw/kdrive/modesetting/modesetting.h | 21 ++- hw/kdrive/modesetting/ms_gamma.c | 190 ++++++++++++++++++++++++++++ hw/kdrive/modesetting/msinit.c | 2 - 5 files changed, 244 insertions(+), 33 deletions(-) create mode 100644 hw/kdrive/modesetting/ms_gamma.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index c98c43ec504..d17790c3542 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -1,6 +1,7 @@ srcs = [ 'modesetting.c', 'msinit.c', + 'ms_gamma.c', 'ms_gbm.c', '../../stubs/ddxBeforeReset.c', ] diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 7bbcd9fe256..4664deed1ad 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -565,6 +565,8 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) goto fail; } + scrpriv->crtc = drmModeGetCrtc(fd, scrpriv->crtc_id); + scrpriv->mode = modesetting_find_mode(scrpriv->connector, screen->width, screen->height, screen->rate); if (!scrpriv->mode) { LogMessage(X_WARNING, "Xmodesetting(card %d, screen %d): Could not find a supported mode\n", @@ -945,6 +947,7 @@ msRandRSetConfig(ScreenPtr pScreen, return FALSE; } +#ifdef RANDR static Bool msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) { @@ -968,11 +971,31 @@ msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) return FALSE; } +static Bool +msRandRSetPhysicalScreenSizes(ScreenPtr pScreen) +{ + int mmWidth, mmHeight; + + if (msGetPhysicalScreenSizes(pScreen, &mmWidth, &mmHeight)) { + RROutputPtr pOutput; + pOutput = RRFirstOutput(pScreen); + + if (!pOutput) { + return FALSE; + } + + RROutputSetPhysicalSize(pOutput, + mmWidth, + mmHeight); + } + + return TRUE; +} + static Bool msRandRInit(ScreenPtr pScreen) { rrScrPrivPtr pScrPriv; - int mmWidth, mmHeight; if (!RRScreenInit(pScreen)) { return FALSE; @@ -982,22 +1005,19 @@ msRandRInit(ScreenPtr pScreen) pScrPriv->rrGetInfo = msRandRGetInfo; pScrPriv->rrSetConfig = msRandRSetConfig; - if (msGetPhysicalScreenSizes(pScreen, &mmWidth, &mmHeight)) { - RROutputPtr pOutput; + /* Create the output */ + RRGetInfo(pScreen, TRUE); - /* Create the output */ - RRGetInfo(pScreen, TRUE); + msRandRSetPhysicalScreenSizes(pScreen); - pOutput = RRFirstOutput(pScreen); - if (pOutput) { - RROutputSetPhysicalSize(pOutput, - mmWidth, - mmHeight); - } +#if RANDR_12_INTERFACE + if (msRandRGammaInit(pScreen)) { + pScrPriv->rrCrtcSetGamma = msRandRCrtcSetGamma; } - +#endif return TRUE; } +#endif /* RANDR */ Bool msInitScreen(ScreenPtr pScreen) @@ -1012,11 +1032,11 @@ msFinishInitScreen(ScreenPtr pScreen) if (!shadowSetup(pScreen)) { return FALSE; } - +#ifdef RANDR if (!msRandRInit(pScreen)) { return FALSE; } - +#endif return TRUE; } @@ -1271,6 +1291,9 @@ msScreenFini(KdScreenInfo * screen) msScrPriv *priv = screen->driver; gbm_bo_destroy(priv->front); + if (priv->crtc) { + drmModeFreeCrtc(priv->crtc); + } drmModeFreeConnector(priv->connector); free(priv); @@ -1294,18 +1317,6 @@ msCardFini(KdCardInfo * card) card->driver = NULL; } -#if 0 -void -msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs) -{ -} - -void -msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) -{ -} -#endif - void msCloseScreen(ScreenPtr pScreen) { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index d027c10d4b9..2ea21e23317 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -14,7 +14,9 @@ #include "kglamor.h" +#ifdef RANDR #include "randrstr.h" +#endif typedef struct _msPriv { struct gbm_device *gbm; @@ -25,17 +27,13 @@ typedef struct _msPriv { int num_used_connectors; uint32_t *used_connectors; -#if 0 - __u16 red[256]; - __u16 green[256]; - __u16 blue[256]; -#endif } msPriv; typedef struct _msScrPriv { struct gbm_bo *front; drmModeConnector *connector; drmModeModeInfo *mode; + drmModeCrtcPtr crtc; uint32_t conn_id; uint32_t crtc_id; @@ -81,6 +79,19 @@ void msScreenFini(KdScreenInfo * screen); void msCardFini(KdCardInfo * card); +/* ms_gamma.c */ + +void msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs); + +void msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs); + +#ifdef RANDR +#if RANDR_12_INTERFACE +Bool msRandRCrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc); +#endif +Bool msRandRGammaInit(ScreenPtr pScreen); +#endif + #ifdef GLAMOR /* ms_glamor.c */ diff --git a/hw/kdrive/modesetting/ms_gamma.c b/hw/kdrive/modesetting/ms_gamma.c new file mode 100644 index 00000000000..ee474cd075a --- /dev/null +++ b/hw/kdrive/modesetting/ms_gamma.c @@ -0,0 +1,190 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +static Bool +msGetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + + struct gbm_device *gbm; + int fd; + int sz = size; + + gbm = gbm_bo_get_device(priv->front); + fd = gbm_device_get_fd(gbm); + + if (priv->crtc && priv->crtc->gamma_size < size) { + sz = priv->crtc->gamma_size; + } + + memset(r, 0, size * sizeof(*r)); + memset(g, 0, size * sizeof(*g)); + memset(b, 0, size * sizeof(*b)); + + if (!drmModeCrtcGetGamma(fd, priv->crtc_id, sz, r, g, b)) { + return TRUE; + } + + memset(r, 0, size * sizeof(*r)); + memset(g, 0, size * sizeof(*g)); + memset(b, 0, size * sizeof(*b)); + return FALSE; +} + +static Bool +msSetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + + struct gbm_device *gbm; + int fd; + int sz = size; + + gbm = gbm_bo_get_device(priv->front); + fd = gbm_device_get_fd(gbm); + + if (priv->crtc && priv->crtc->gamma_size < size) { + sz = priv->crtc->gamma_size; + } + + return !drmModeCrtcSetGamma(fd, priv->crtc_id, sz, r, g, b); +} + +void +msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs) +{ + uint16_t r[256] = {0}, g[256] = {0}, b[256] = {0}; + int max = 0; + + for (int i = 0; i < n; i++) { + if (pdefs[i].pixel > max) + max = pdefs[i].pixel; + if (max >= sizeof(r) / sizeof(*r)) { + max = sizeof(r) / sizeof(*r); + break; + } + } + + msGetGamma(pScreen, max, r, g, b); + + for (int i = 0; i < n; i++) { + int p = pdefs[i].pixel; + if (p > max) { + p = max; + } + if (p < 0) { + p = 0; + } + pdefs[i].red = r[p]; + pdefs[i].green = g[p]; + pdefs[i].blue = b[p]; + } +} + +void +msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) +{ + uint16_t r[256] = {0}, g[256] = {0}, b[256] = {0}; + int max = 0; + + for (int i = 0; i < n; i++) { + int p = pdefs[i].pixel; + if (p > sizeof(r) / sizeof(*r)) { + p = sizeof(r) / sizeof(*r); + } + if (p < 0) { + p = 0; + } + if (p > max) { + max = p; + } + r[p] = pdefs[i].red; + g[p] = pdefs[i].green; + b[p] = pdefs[i].blue; + } + + msSetGamma(pScreen, max, r, g, b); +} + +#ifdef RANDR +#if RANDR_12_INTERFACE +Bool +msRandRCrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc) +{ + return msSetGamma(pScreen, crtc->gammaSize, crtc->gammaRed, crtc->gammaGreen, crtc->gammaBlue); +} +#endif +Bool +msRandRGammaInit(ScreenPtr pScreen) +{ +#if RANDR_12_INTERFACE + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + RROutputPtr pOutput; + RRCrtcPtr crtc; + + uint16_t *gamma; + int gamma_size; + + pOutput = RRFirstOutput(pScreen); + if (!pOutput) { + return FALSE; + } + + if (!pOutput->numCrtcs || !pOutput->crtcs) { + return FALSE; + } + + crtc = pOutput->crtc ? pOutput->crtc : pOutput->crtcs[0]; + if (!crtc) { + return FALSE; + } + + if (priv->crtc && priv->crtc->gamma_size) { + gamma_size = priv->crtc->gamma_size; + } else { + switch (screen->fb.depth) { + case 8: + gamma_size = 1 << 8; + case 15: + gamma_size = 1 << 5; + case 16: + gamma_size = 1 << 6; + case 24: + gamma_size = 1 << 8; + case 30: + default: + gamma_size = 1 << 10; + } + } + + gamma = calloc(3 * gamma_size, sizeof(*gamma)); + if (!gamma) { + return FALSE; + } + + if (!RRCrtcGammaSetSize(crtc, gamma_size)) { + return FALSE; + } + + msGetGamma(pScreen, gamma_size, gamma, gamma + gamma_size, gamma + 2 * gamma_size); + RRCrtcGammaSet(crtc, gamma, gamma + gamma_size, gamma + 2 * gamma_size); + + free(gamma); + return TRUE; +#else /* RANDR_12_INTERFACE */ + return FALSE; +#endif +} +#endif /* RANDR */ diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 56078abc0e5..34c1087588e 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -310,10 +310,8 @@ KdCardFuncs msFuncs = { .finiAccel = msFiniAccel, #endif -#if 0 .getColors = msGetColors, .putColors = msPutColors, -#endif .closeScreen = msCloseScreen, }; From 95e2e1d418442bf7e180cd71472298ac7ac0cc0b Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 18 Sep 2026 11:22:57 +0300 Subject: [PATCH 25/47] kdrive/modesetting: Add `-swap` option Mostly intended for testing. Signed-off-by: stefan11111 --- hw/kdrive/modesetting/Xmodesetting.man | 4 +++- hw/kdrive/modesetting/modesetting.c | 9 ++++++++- hw/kdrive/modesetting/modesetting.h | 1 + hw/kdrive/modesetting/msinit.c | 10 +++++++++- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/hw/kdrive/modesetting/Xmodesetting.man b/hw/kdrive/modesetting/Xmodesetting.man index ca3641b384b..72754901da6 100644 --- a/hw/kdrive/modesetting/Xmodesetting.man +++ b/hw/kdrive/modesetting/Xmodesetting.man @@ -23,7 +23,9 @@ If no -dri option was passed, this device will also be used for rendering .B -noshadow disables the ShadowFB layer on supported hw, may slightly increase performance. May also lead to flickering. - +.TP 8 +.B -swap +Sets the prefered format color ordering to BGR instead of RGB. .SH CONFIGURATION . Like all kdrive X servers, diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 4664deed1ad..fc863a7c3ab 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -267,6 +267,12 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, FALSE /* rb_swap */); format_swap = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, TRUE /* rb_swap */); + if (config->format_swap) { + uint32_t tmp = format; + format = format_swap; + format_swap = tmp; + } + #ifdef GLAMOR if (!need_map) { if (!ret) { @@ -656,7 +662,8 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) break; } - if (rb_swap) { + /* XXX Only cpu-mapped buffers need swap here */ + if (rb_swap && gbm_bo_get_map(scrpriv->front)) { int tmp = screen->fb.blueMask; screen->fb.blueMask = screen->fb.redMask; screen->fb.redMask = tmp; diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 2ea21e23317..205f2e26a97 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -48,6 +48,7 @@ typedef struct _msScrPriv { typedef struct _msScreenConf { Bool shadow; + Bool format_swap; KdGlamorInfo glamor_info; } MsScreenConf; diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 34c1087588e..13e8e7a3252 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -171,7 +171,8 @@ msLogScreenInfo(const MsScreenConf *config, const char *dev_path, int screen_num dev_path ? dev_path : "not passed"); LogMessage(X_INFO, "Xmodesetting(%d): ShadowFB %s\n", screen_num, config->shadow ? "enabled" : "disabled"); - + LogMessage(X_INFO, "Xmodesetting(%d): Preferred format color ordering %s\n", screen_num, + config->format_swap ? "BGR" : "RGB"); KdGlamorLogScreenInfo(&config->glamor_info, screen_num); LogMessage(X_INFO, "\n"); } @@ -237,6 +238,8 @@ ddxUseMsg(void) ("-dev KMS device to use. Defaults to /dev/dri/card0\n"); ErrorF ("-noshadow Disable the ShadowFB layer if possible\n"); + ErrorF + ("-swap Prefer BGR format color ordering instead of RGB\n"); ErrorF("\n"); } @@ -268,6 +271,11 @@ ddxProcessArgument(int argc, char **argv, int i) return 1; } + if (!strcmp(argv[i], "-swap")) { + msCurrScreen->format_swap = TRUE; + return 1; + } + glamor_arg = KdGlamorParse(&msCurrScreen->glamor_info, argc, argv, i); if (glamor_arg) { return glamor_arg; From c2bd1580c372dae197b75feed886a292340e4bf2 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 18 Sep 2026 16:39:01 +0300 Subject: [PATCH 26/47] kdrive/modesetting: Log the front buffer format and modifier Progress report Tested Xmodesetting on intel and nvidia, both with regular and swapped formats, both with and without `-nogbm`, both with and without glamor. Depths 30, 24, and 16 work both on intel and nvidia. Depth 15 also works on nvidia, but the nvidia gbm backend refuses to allocate a depth 15 bo. Using the dumb gbm backend, an depth 15 bo can be allocated, and it works. Nvidia doesn't support depth 30 with RGB ordering, and depth 16 with BGR ordering. Xmodesetting properly detects this and swaps the R-B channels. Signed-off-by: stefan11111 --- hw/kdrive/modesetting/ms_glamor.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 7738f16bdc7..1cf9e67c9c8 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -51,8 +51,12 @@ msGlamorCreateRes(ScreenPtr pScreen) } if (ret) { - LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d\n", - pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel); + struct gbm_format_name_desc desc = {0}; + uint32_t format = gbm_bo_get_format(scrpriv->front); + uint64_t modifier = gbm_bo_get_modifier(scrpriv->front); + const char *format_name = gbm_format_get_name(format, &desc); + LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d, format: %s, modifier: 0x%lx\n", + pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel, format_name, modifier); } return ret; From 26729714860cb98674d0a80c3b67d78537868971 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 19 Sep 2026 14:05:56 +0300 Subject: [PATCH 27/47] kdrive/modesetting: Factor out bo swapping code fron RandR Fixes a bug where on the fallback bo map path, one would have to chang VT away and back to the X server for the image to appear on screen. May be useful for implementing page flipping in the future Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 180 +++++++++++++++++----------- hw/kdrive/modesetting/modesetting.h | 2 + hw/kdrive/modesetting/ms_glamor.c | 69 ++++------- 3 files changed, 134 insertions(+), 117 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index fc863a7c3ab..9347b1bbd83 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -14,6 +14,10 @@ #include "kxv.h" #endif + +static void +msSetScreenSizes(ScreenPtr pScreen); + static Bool msFdMatch(int fd1, int fd2); @@ -320,6 +324,78 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) return ret; } +Bool +msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + struct gbm_bo *old_front; + Bool wasEnabled = pScreenPriv->enabled; + msScrPriv oldscr; + + if (wasEnabled) { + KdDisableScreen(pScreen); + } + + oldscr = *scrpriv; + + old_front = scrpriv->front; + + msUnmapFramebuffer(screen); + + scrpriv->front = bo; + + if (!msMapFramebuffer(screen)) { + goto bail; + } + + KdShadowUnset(screen->pScreen); + + if (!msSetShadow(screen->pScreen)) { + goto bail; + } + + msSetScreenSizes(screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) ((*pScreen->GetScreenPixmap)(pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder(pScreen, scrpriv->randr); + + /* Scan out the new bo on the screen's crtc */ + if (wasEnabled) { + KdEnableScreen(pScreen); + } + + if (!flip) { + gbm_bo_destroy(old_front); + } + return TRUE; + +bail: + msUnmapFramebuffer(screen); + old_front = scrpriv->front; + *scrpriv = oldscr; + msMapFramebuffer(screen); + msSetScreenSizes(screen->pScreen); + + if (wasEnabled) { + KdEnableScreen(pScreen); + } + return FALSE; +} + static Bool msSetMode(ScreenPtr pScreen, int width, int height, int rate) { @@ -327,38 +403,49 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) KdScreenInfo *screen = pScreenPriv->screen; msPriv *priv = screen->card->driver; msScrPriv *scrpriv = screen->driver; - struct gbm_bo *old_front; + struct gbm_bo *new_front = NULL; drmModeModeInfo *old_mode; + int old_width, old_height, old_rate; - old_front = scrpriv->front; old_mode = scrpriv->mode; + old_width = screen->width; + old_height = screen->height; + old_rate = screen->rate; + /* Find the mode */ scrpriv->mode = modesetting_find_mode(scrpriv->connector, width, height, rate); if (!scrpriv->mode) { goto bail; } + screen->width = width; + screen->height = height; + screen->rate = rate; + /* Create a new front with the new sizes */ if (width != screen->width || height != screen->height) { uint32_t format = gbm_bo_get_format(scrpriv->front); Bool do_map = !!gbm_bo_get_map(scrpriv->front); - scrpriv->front = gbm_create_front_bo(priv->gbm, do_map, width, height, format); - if (!scrpriv->front) { + new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format); + if (!new_front || + !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { goto bail; } - - gbm_bo_destroy(old_front); } - screen->width = width; - screen->height = height; - screen->rate = rate; return TRUE; bail: - scrpriv->front = old_front; + if (new_front) { + gbm_bo_destroy(new_front); + } + + screen->width = old_width; + screen->height = old_height; + screen->rate = old_rate; + scrpriv->mode = old_mode; return FALSE; @@ -865,33 +952,20 @@ msRandRSetConfig(ScreenPtr pScreen, KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; msScrPriv *scrpriv = screen->driver; - Bool wasEnabled = pScreenPriv->enabled; - msScrPriv oldscr; - int oldwidth; - int oldheight; + int oldmmwidth; int oldmmheight; - int newwidth, newheight, newmmwidth, newmmheight; + int newmmwidth; + int newmmheight; if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { - newwidth = pSize->width; - newheight = pSize->height; newmmwidth = pSize->mmWidth; newmmheight = pSize->mmHeight; } else { - newwidth = pSize->height; - newheight = pSize->width; newmmwidth = pSize->mmHeight; newmmheight = pSize->mmWidth; } - if (wasEnabled) - KdDisableScreen(pScreen); - - oldscr = *scrpriv; - - oldwidth = screen->width; - oldheight = screen->height; oldmmwidth = pScreen->mmWidth; oldmmheight = pScreen->mmHeight; @@ -901,56 +975,18 @@ msRandRSetConfig(ScreenPtr pScreen, scrpriv->randr = KdAddRotation(screen->randr, randr); - pScreen->width = newwidth; - pScreen->height = newheight; pScreen->mmWidth = newmmwidth; pScreen->mmHeight = newmmheight; - msUnmapFramebuffer(screen); - - if (!msSetMode(pScreen, pSize->width, pSize->height, rate)) - goto bail4; - - if (!msMapFramebuffer(screen)) - goto bail4; - - KdShadowUnset(screen->pScreen); - - if (!msSetShadow(screen->pScreen)) - goto bail4; - - msSetScreenSizes(screen->pScreen); - - /* - * Set frame buffer mapping - */ - (*pScreen->ModifyPixmapHeader) ((*pScreen->GetScreenPixmap)(pScreen), - pScreen->width, - pScreen->height, - screen->fb.depth, - screen->fb.bitsPerPixel, - screen->fb.byteStride, - screen->fb.frameBuffer); - - /* set the subpixel order */ - - KdSetSubpixelOrder(pScreen, scrpriv->randr); - if (wasEnabled) - KdEnableScreen(pScreen); + if (!msSetMode(pScreen, pSize->width, pSize->height, rate)) { + goto bail; + } return TRUE; -bail4: - msUnmapFramebuffer(screen); - *scrpriv = oldscr; - msMapFramebuffer(screen); - pScreen->width = oldwidth; - pScreen->height = oldheight; +bail: pScreen->mmWidth = oldmmwidth; pScreen->mmHeight = oldmmheight; - - if (wasEnabled) - KdEnableScreen(pScreen); return FALSE; } @@ -1183,15 +1219,15 @@ msCreateResources(ScreenPtr pScreen) fb_id = gbm_bo_get_fb(priv->front); fd = gbm_device_get_fd(gbm); -#ifdef GLAMOR - if (!msGlamorCreateRes(pScreen)) { + if (!msSetShadow(pScreen)) { return FALSE; } -#endif - if (!msSetShadow(pScreen)) { +#ifdef GLAMOR + if (!msGlamorCreateRes(pScreen)) { return FALSE; } +#endif /* Damage tracking not supported/needed */ if (drmModeDirtyFB(fd, fb_id, NULL, 0) && diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 205f2e26a97..1ca1d28aa5e 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -80,6 +80,8 @@ void msScreenFini(KdScreenInfo * screen); void msCardFini(KdCardInfo * card); +Bool msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip); + /* ms_gamma.c */ void msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs); diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 1cf9e67c9c8..0707f60388c 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -20,46 +20,39 @@ msGlamorCreateRes(ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; msScrPriv *scrpriv = screen->driver; PixmapPtr rootPixmap; - Bool ret = TRUE; + + struct gbm_format_name_desc desc = {0}; + uint32_t format; + uint64_t modifier; + const char *format_name; rootPixmap = (*pScreen->GetScreenPixmap)(pScreen); if (!gbm_bo_get_map(scrpriv->front)) { Bool used_modifiers = gbm_bo_get_used_modifiers(scrpriv->front); - ret = !screen->dumb && glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, scrpriv->front, - used_modifiers); - if (ret) { + if (!screen->dumb && + glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, scrpriv->front, used_modifiers)) { LogMessage(X_INFO, "Xmodesetting(%d): Using a tiled front buffer\n", pScreen->myNum); } else { if (!msGlamorMapFront(pScreen)) { + LogMessage(X_ERROR, "Xmodesetting(%d): Could not map the front buffer\n", + pScreen->myNum); return FALSE; } - ret = (*pScreen->ModifyPixmapHeader) (rootPixmap, - pScreen->width, - pScreen->height, - screen->fb.depth, - screen->fb.bitsPerPixel, - screen->fb.byteStride, - screen->fb.frameBuffer); - - if (ret) { - LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); - } + + LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); } } else { LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); } - if (ret) { - struct gbm_format_name_desc desc = {0}; - uint32_t format = gbm_bo_get_format(scrpriv->front); - uint64_t modifier = gbm_bo_get_modifier(scrpriv->front); - const char *format_name = gbm_format_get_name(format, &desc); - LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d, format: %s, modifier: 0x%lx\n", - pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel, format_name, modifier); - } + format = gbm_bo_get_format(scrpriv->front); + modifier = gbm_bo_get_modifier(scrpriv->front); + format_name = gbm_format_get_name(format, &desc); + LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d, format: %s, modifier: 0x%lx\n", + pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel, format_name, modifier); - return ret; + return TRUE; } static Bool @@ -68,36 +61,22 @@ msGlamorMapFront(ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; msPriv *priv = screen->card->driver; - msScrPriv *scrpriv = screen->driver; - msScrPriv oldscr; - - struct gbm_bo *old_front = scrpriv->front; + struct gbm_bo *new_front = NULL; LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use tiled gbm front, trying to use a mapped front bo\n", pScreen->myNum); - oldscr = *scrpriv; - - msUnmapFramebuffer(screen); - - scrpriv->front = modesetting_open(priv, screen, TRUE /* need_map */); - if (!scrpriv->front) { + new_front = modesetting_open(priv, screen, TRUE /* need_map */); + if (!new_front || + !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { goto bail; } - if (!msMapFramebuffer(screen)) { - goto bail; - } - - gbm_bo_destroy(old_front); - scrpriv->setPixmapBits = TRUE; - return TRUE; bail: - msUnmapFramebuffer(screen); - *scrpriv = oldscr; - msMapFramebuffer(screen); - scrpriv->error = TRUE; + if (new_front) { + gbm_bo_destroy(new_front); + } return FALSE; } From 9d195155f6df61f79515fb44aa72baf4e7018d11 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 19 Sep 2026 17:59:49 +0300 Subject: [PATCH 28/47] kdrive/modesetting: swab r-b channels for BGR depth 30 visuals on gles `glamor_setup_formats` chooses `PIXMAN_x2b10g10r10` format for depth 30 pixmaps on gles. If the front buffer is XBGR2101010 on gles, swap the r-b channels, like we would with a cpu-mapped buffer. As I understand it, we should also swap XRGB2101010 r-b channels on gles, but for some reason not swapping them works. This needs further investigating. Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 9347b1bbd83..7e0933f612f 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -639,6 +639,9 @@ modesetting_claim_connector_crtc(msPriv *priv, uint32_t conn, int crtc) static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) { +#ifdef GLAMOR + MsScreenConf *config = screen->closure; +#endif msPriv *priv = screen->card->driver; int fd = gbm_device_get_fd(priv->gbm); uint32_t format; @@ -749,8 +752,15 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) break; } - /* XXX Only cpu-mapped buffers need swap here */ - if (rb_swap && gbm_bo_get_map(scrpriv->front)) { + /* XXX Tiled buffers don't need r-b swap, unless it's depth 30 on gles */ + if (!gbm_bo_get_map(scrpriv->front)) { + if (screen->fb.depth != 30 || + !config->glamor_info.force_es) { + rb_swap = FALSE; + } + } + + if (rb_swap) { int tmp = screen->fb.blueMask; screen->fb.blueMask = screen->fb.redMask; screen->fb.redMask = tmp; From a9b97d1a8fb18de11842503e2810a8353022bf47 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sun, 20 Sep 2026 13:44:41 +0300 Subject: [PATCH 29/47] kdrive/modesetting: Fix non-shadow bpp Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 7e0933f612f..42b72cb55e4 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -831,8 +831,6 @@ msMapFramebuffer(KdScreenInfo * screen) KdPointerMatrix m; MsScreenConf *config = screen->closure; - unsigned long stride = gbm_bo_get_stride(scrpriv->front); - if (!gbm_bo_get_map(scrpriv->front)) { scrpriv->shadow = FALSE; } else if (config->shadow >= 0) { @@ -856,8 +854,10 @@ msMapFramebuffer(KdScreenInfo * screen) return FALSE; } } else { + unsigned long stride = gbm_bo_get_stride(scrpriv->front); + int cpp = (gbm_bo_get_bpp(scrpriv->front) + 7) / 8; screen->fb.byteStride = stride; - screen->fb.pixelStride = stride / 4; + screen->fb.pixelStride = stride / cpp; screen->fb.frameBuffer = gbm_bo_get_map(scrpriv->front); } From 9f6a25a256664ad64c1f8b83da91b217a4ebee41 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sun, 20 Sep 2026 14:07:33 +0300 Subject: [PATCH 30/47] kdrive: Don't limit refresh rate by default Signed-off-by: stefan11111 --- hw/kdrive/fake/fakeinit.c | 2 +- hw/kdrive/fbdev/fb_glamor.c | 4 ---- hw/kdrive/fbdev/fbinit.c | 2 +- hw/kdrive/modesetting/ms_glamor.c | 4 ---- hw/kdrive/modesetting/msinit.c | 2 +- hw/kdrive/src/kglamor.c | 3 ++- 6 files changed, 5 insertions(+), 12 deletions(-) diff --git a/hw/kdrive/fake/fakeinit.c b/hw/kdrive/fake/fakeinit.c index dad34178217..647be9734d9 100644 --- a/hw/kdrive/fake/fakeinit.c +++ b/hw/kdrive/fake/fakeinit.c @@ -32,7 +32,7 @@ static FakeScreenConf *fakeCurrScreen = NULL; static const FakeScreenConf fakeDefaultConfig = { .shadow = -1, - .glamor_info = {.fake_rate = 600, .drop_master = TRUE,}, + .glamor_info = {.fake_rate = -1, .drop_master = TRUE,}, }; void diff --git a/hw/kdrive/fbdev/fb_glamor.c b/hw/kdrive/fbdev/fb_glamor.c index fa5a03e018c..84ea58e37c9 100644 --- a/hw/kdrive/fbdev/fb_glamor.c +++ b/hw/kdrive/fbdev/fb_glamor.c @@ -15,10 +15,6 @@ fbdevInitAccel(ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; FbScreenConf *config = screen->card->closure; - if (screen->rate > 60) { - config->glamor_info.fake_rate = screen->rate; - } - return KdGlamorInit(pScreen, &config->glamor_info, NULL); } diff --git a/hw/kdrive/fbdev/fbinit.c b/hw/kdrive/fbdev/fbinit.c index a7adbaff66c..ba693f5704a 100644 --- a/hw/kdrive/fbdev/fbinit.c +++ b/hw/kdrive/fbdev/fbinit.c @@ -36,7 +36,7 @@ static FbScreenConf *fbCurrScreen = NULL; static const FbScreenConf fbDefaultConfig = { .fb_path = NULL, .shadow = TRUE, - .glamor_info = {.drop_master = TRUE,}, + .glamor_info = {.fake_rate = -1, .drop_master = TRUE,}, }; static void fbdevLogScreenInfo(const FbScreenConf *config, int screen_num); diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 0707f60388c..95c2c0dcd1f 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -88,10 +88,6 @@ msInitAccel(ScreenPtr pScreen) MsScreenConf *config = screen->closure; msPriv *priv = screen->card->driver; - if (screen->rate > 60) { - config->glamor_info.fake_rate = screen->rate; - } - if (!config->glamor_info.dri_path) { config->glamor_info.dri_fd = dup(gbm_device_get_fd(priv->gbm)); if (config->glamor_info.dri_fd >= 0) { diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 13e8e7a3252..b1858e922aa 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -27,7 +27,7 @@ static MsScreenConf *msCurrScreen = NULL; static const MsScreenConf msDefaultConfig = { .shadow = TRUE, - .glamor_info = {.use_gbm = TRUE,}, + .glamor_info = {.fake_rate = -1, .use_gbm = TRUE,}, }; static const char* FindDevPath(int argc, char **argv, int i); diff --git a/hw/kdrive/src/kglamor.c b/hw/kdrive/src/kglamor.c index 6ad2f659928..8c0681764af 100644 --- a/hw/kdrive/src/kglamor.c +++ b/hw/kdrive/src/kglamor.c @@ -157,7 +157,8 @@ KdGlamorInit(ScreenPtr pScreen, KdGlamorInfo *info, int *caps) * If no global fake rate was requested and a per-screen rate was requested, use that */ if (!FakeScreenFps) { - FakeScreenFps = info->fake_rate; + /* 1000000 is the highest fake rate present supports */ + FakeScreenFps = info->fake_rate > 0 ? info->fake_rate : 1000000; present_screen_init(pScreen, NULL); FakeScreenFps = 0; } From 8bd10d33e4eb91a75022e2a13f934a00d01eabfe Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 19:49:08 +0300 Subject: [PATCH 31/47] kdrive/modesetting: Split modesetting queries into a different file Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.c | 175 -------------------------- hw/kdrive/modesetting/modesetting.h | 11 ++ hw/kdrive/modesetting/ms_query.c | 186 ++++++++++++++++++++++++++++ 4 files changed, 198 insertions(+), 175 deletions(-) create mode 100644 hw/kdrive/modesetting/ms_query.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index d17790c3542..e4e90445356 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -3,6 +3,7 @@ srcs = [ 'msinit.c', 'ms_gamma.c', 'ms_gbm.c', + 'ms_query.c', '../../stubs/ddxBeforeReset.c', ] diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 42b72cb55e4..b1cdfa5c8b7 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -21,181 +21,6 @@ msSetScreenSizes(ScreenPtr pScreen); static Bool msFdMatch(int fd1, int fd2); -static int -modesetting_grade_mode(drmModeModeInfo *mode, uint32_t req_w, uint32_t req_h, uint32_t req_rate) -{ - int score = 1; - - if (req_w && (req_w == mode->hdisplay)) { - score += 10; - } - - if (req_h && (req_h == mode->vdisplay)) { - score += 10; - } - - if (req_rate && (req_rate == mode->vrefresh)) { - score += 5; - } - - if (mode->type & DRM_MODE_TYPE_PREFERRED) { - score++; - } - - return score; -} - -static drmModeModeInfo* -modesetting_find_mode(drmModeConnector *conn, uint32_t req_w, uint32_t req_h, uint32_t req_rate) -{ - drmModeModeInfo *best_mode = NULL; - int best_score = 0; - - for (int i = 0; i < conn->count_modes; i++) { - drmModeModeInfo *mode = &conn->modes[i]; - int score; - - score = modesetting_grade_mode(mode, req_w, req_h, req_rate); - if (score <= best_score) { - continue; - } - - best_mode = mode; - best_score = score; - } - - return best_mode; -} - -static int -modesetting_grade_connector(msPriv *priv, drmModeConnector *conn, uint32_t conn_id) -{ - int score = 1; - Bool in_use = FALSE; - - if (conn->modes && conn->count_modes) { - score += 5; - } - - switch(conn->connection) { - case DRM_MODE_CONNECTED: - score++; - case DRM_MODE_UNKNOWNCONNECTION: - score++; - case DRM_MODE_DISCONNECTED: - score++; - } - - for(int i = 0; i < priv->num_used_connectors; i++) { - if (priv->used_connectors[i] == conn_id) { - in_use = TRUE; - break; - } - } - - if (!in_use) { - score += 10; - } - - return score; -} - -static drmModeConnector* -modesetting_find_connector(msPriv *priv, int fd, uint32_t *conn_id) -{ - drmModeConnector *best_connector = NULL; - int best_score = 0; - - drmModeRes *res = priv->resources; - - for (int i = 0; i < res->count_connectors; i++) { - drmModeConnector *conn; - int id; - int score; - id = res->connectors[i]; - conn = drmModeGetConnector(fd, id); - if (!conn) { - continue; - } - - score = modesetting_grade_connector(priv, conn, id); - if (score <= best_score) { - drmModeFreeConnector(conn); - continue; - } - - if (best_connector) { - drmModeFreeConnector(best_connector); - } - - best_connector = conn; - *conn_id = id; - best_score = score; - } - - return best_connector; -} - -static Bool -modesetting_crtc_is_used(msPriv *priv, int crtc) -{ - for (int i = 0; i < priv->num_used_crtcs; i++) { - if (priv->used_crtcs[i] == crtc) { - return TRUE; - } - } - - return FALSE; -} - -/* Slightly modified rom man drm-kms */ -static int -modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn) -{ - drmModeRes *res = priv->resources; - drmModeEncoder *enc; - unsigned int i, j; - int crtc = -ENOENT; - - /* iterate all encoders of this connector */ - for (i = 0; i < conn->count_encoders; ++i) { - enc = drmModeGetEncoder(fd, conn->encoders[i]); - if (!enc) { - /* cannot retrieve encoder, ignoring... */ - continue; - } - - /* iterate all global CRTCs */ - for (j = 0; j < res->count_crtcs; ++j) { - /* check whether this CRTC works with the encoder */ - if (!(enc->possible_crtcs & (1 << j))) - continue; - - /* Here you need to check that no other connector - * currently uses the CRTC with id "crtc". If you intend - * to drive one connector only, then you can skip this - * step. Otherwise, simply scan your list of configured - * connectors and CRTCs whether this CRTC is already - * used. If it is, then simply continue the search here. */ - if (!modesetting_crtc_is_used(priv, res->crtcs[j])) { - drmModeFreeEncoder(enc); - return res->crtcs[j]; - } - - /* Allow reusing crtcs for testing */ - if (crtc < 0) { - crtc = res->crtcs[j]; - } - } - - drmModeFreeEncoder(enc); - } - - /* cannot find a suitable CRTC */ - return crtc; -} - - struct gbm_bo* modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 1ca1d28aa5e..ab595179053 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -140,4 +140,15 @@ gbm_format_get_depth(uint32_t format); struct gbm_bo* gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format); +/* ms_query.c */ + +drmModeModeInfo* +modesetting_find_mode(drmModeConnector *conn, uint32_t req_w, uint32_t req_h, uint32_t req_rate); + +drmModeConnector* +modesetting_find_connector(msPriv *priv, int fd, uint32_t *conn_id); + +int +modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn); + #endif /* _MODESETTING_H_ */ diff --git a/hw/kdrive/modesetting/ms_query.c b/hw/kdrive/modesetting/ms_query.c new file mode 100644 index 00000000000..d6bc509201c --- /dev/null +++ b/hw/kdrive/modesetting/ms_query.c @@ -0,0 +1,186 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +#include /* ENOENT */ + +/* Various modesetting query functions */ + +static int +modesetting_grade_mode(drmModeModeInfo *mode, uint32_t req_w, uint32_t req_h, uint32_t req_rate) +{ + int score = 1; + + if (req_w && (req_w == mode->hdisplay)) { + score += 10; + } + + if (req_h && (req_h == mode->vdisplay)) { + score += 10; + } + + if (req_rate && (req_rate == mode->vrefresh)) { + score += 5; + } + + if (mode->type & DRM_MODE_TYPE_PREFERRED) { + score++; + } + + return score; +} + +drmModeModeInfo* +modesetting_find_mode(drmModeConnector *conn, uint32_t req_w, uint32_t req_h, uint32_t req_rate) +{ + drmModeModeInfo *best_mode = NULL; + int best_score = 0; + + for (int i = 0; i < conn->count_modes; i++) { + drmModeModeInfo *mode = &conn->modes[i]; + int score; + + score = modesetting_grade_mode(mode, req_w, req_h, req_rate); + if (score <= best_score) { + continue; + } + + best_mode = mode; + best_score = score; + } + + return best_mode; +} + +static int +modesetting_grade_connector(msPriv *priv, drmModeConnector *conn, uint32_t conn_id) +{ + int score = 1; + Bool in_use = FALSE; + + if (conn->modes && conn->count_modes) { + score += 5; + } + + switch(conn->connection) { + case DRM_MODE_CONNECTED: + score++; + case DRM_MODE_UNKNOWNCONNECTION: + score++; + case DRM_MODE_DISCONNECTED: + score++; + } + + for(int i = 0; i < priv->num_used_connectors; i++) { + if (priv->used_connectors[i] == conn_id) { + in_use = TRUE; + break; + } + } + + if (!in_use) { + score += 10; + } + + return score; +} + +drmModeConnector* +modesetting_find_connector(msPriv *priv, int fd, uint32_t *conn_id) +{ + drmModeConnector *best_connector = NULL; + int best_score = 0; + + drmModeRes *res = priv->resources; + + for (int i = 0; i < res->count_connectors; i++) { + drmModeConnector *conn; + int id; + int score; + id = res->connectors[i]; + conn = drmModeGetConnector(fd, id); + if (!conn) { + continue; + } + + score = modesetting_grade_connector(priv, conn, id); + if (score <= best_score) { + drmModeFreeConnector(conn); + continue; + } + + if (best_connector) { + drmModeFreeConnector(best_connector); + } + + best_connector = conn; + *conn_id = id; + best_score = score; + } + + return best_connector; +} + +static Bool +modesetting_crtc_is_used(msPriv *priv, int crtc) +{ + for (int i = 0; i < priv->num_used_crtcs; i++) { + if (priv->used_crtcs[i] == crtc) { + return TRUE; + } + } + + return FALSE; +} + +/* Slightly modified rom man drm-kms */ +int +modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn) +{ + drmModeRes *res = priv->resources; + drmModeEncoder *enc; + unsigned int i, j; + int crtc = -ENOENT; + + /* iterate all encoders of this connector */ + for (i = 0; i < conn->count_encoders; ++i) { + enc = drmModeGetEncoder(fd, conn->encoders[i]); + if (!enc) { + /* cannot retrieve encoder, ignoring... */ + continue; + } + + /* iterate all global CRTCs */ + for (j = 0; j < res->count_crtcs; ++j) { + /* check whether this CRTC works with the encoder */ + if (!(enc->possible_crtcs & (1 << j))) + continue; + + /* Here you need to check that no other connector + * currently uses the CRTC with id "crtc". If you intend + * to drive one connector only, then you can skip this + * step. Otherwise, simply scan your list of configured + * connectors and CRTCs whether this CRTC is already + * used. If it is, then simply continue the search here. */ + if (!modesetting_crtc_is_used(priv, res->crtcs[j])) { + drmModeFreeEncoder(enc); + return res->crtcs[j]; + } + + /* Allow reusing crtcs for testing */ + if (crtc < 0) { + crtc = res->crtcs[j]; + } + } + + drmModeFreeEncoder(enc); + } + + /* cannot find a suitable CRTC */ + return crtc; +} From 72d1ae94a708c49537d45b2323d2e13f764af359 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 20:04:47 +0300 Subject: [PATCH 32/47] kdrive/modesetting: Split some functions to `ms_util.c` Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.c | 159 --------------------------- hw/kdrive/modesetting/modesetting.h | 11 +- hw/kdrive/modesetting/ms_util.c | 160 ++++++++++++++++++++++++++++ 4 files changed, 168 insertions(+), 163 deletions(-) create mode 100644 hw/kdrive/modesetting/ms_util.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index e4e90445356..e35d89c2384 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -4,6 +4,7 @@ srcs = [ 'ms_gamma.c', 'ms_gbm.c', 'ms_query.c', + 'ms_util.c', '../../stubs/ddxBeforeReset.c', ] diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index b1cdfa5c8b7..0b73ad29408 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -14,13 +14,6 @@ #include "kxv.h" #endif - -static void -msSetScreenSizes(ScreenPtr pScreen); - -static Bool -msFdMatch(int fd1, int fd2); - struct gbm_bo* modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) { @@ -149,78 +142,6 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) return ret; } -Bool -msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - struct gbm_bo *old_front; - Bool wasEnabled = pScreenPriv->enabled; - msScrPriv oldscr; - - if (wasEnabled) { - KdDisableScreen(pScreen); - } - - oldscr = *scrpriv; - - old_front = scrpriv->front; - - msUnmapFramebuffer(screen); - - scrpriv->front = bo; - - if (!msMapFramebuffer(screen)) { - goto bail; - } - - KdShadowUnset(screen->pScreen); - - if (!msSetShadow(screen->pScreen)) { - goto bail; - } - - msSetScreenSizes(screen->pScreen); - - /* - * Set frame buffer mapping - */ - (*pScreen->ModifyPixmapHeader) ((*pScreen->GetScreenPixmap)(pScreen), - pScreen->width, - pScreen->height, - screen->fb.depth, - screen->fb.bitsPerPixel, - screen->fb.byteStride, - screen->fb.frameBuffer); - - /* set the subpixel order */ - - KdSetSubpixelOrder(pScreen, scrpriv->randr); - - /* Scan out the new bo on the screen's crtc */ - if (wasEnabled) { - KdEnableScreen(pScreen); - } - - if (!flip) { - gbm_bo_destroy(old_front); - } - return TRUE; - -bail: - msUnmapFramebuffer(screen); - old_front = scrpriv->front; - *scrpriv = oldscr; - msMapFramebuffer(screen); - msSetScreenSizes(screen->pScreen); - - if (wasEnabled) { - KdEnableScreen(pScreen); - } - return FALSE; -} - static Bool msSetMode(ScreenPtr pScreen, int width, int height, int rate) { @@ -344,66 +265,6 @@ msInitialize(KdCardInfo * card, msPriv * priv) return FALSE; } -/* XXX This really belongs in os/, like the version from glamor_egl */ -static Bool -msFdMatch(int fd1, int fd2) -{ - struct stat stat1, stat2; - - if (fd1 == fd2) { - return TRUE; - } - - if (fd1 < 0 || fd2 < 0) { - return FALSE; - } - - if (fstat(fd1, &stat1) < 0 || - fstat(fd2, &stat2) < 0) { - return FALSE; - } - - /** - * From https://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/stat.h.html - * - * The st_ino and st_dev fields taken together uniquely identify the file within the system. - */ - return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); -} - -static KdCardInfo* -msFindCardForFd(int fd) -{ - for (KdCardInfo *card = kdCardInfo; card; card = card->next) { - const char *card_path = card->closure; - int cardFd = card_path ? open(card_path, O_RDWR) : -1; - Bool ret = msFdMatch(cardFd, fd); - - if (cardFd >= 0) { - close(cardFd); - } - if (ret) { - return card; - } - } - - return NULL; -} - -KdCardInfo* -msFindMatchingCard(const char *card_path) -{ - KdCardInfo *card; - int fd = card_path ? open(card_path, O_RDWR) : -1; - - card = msFindCardForFd(fd); - - if (fd >= 0) { - close(fd); - } - return card; -} - Bool msCardInit(KdCardInfo * card) { @@ -689,26 +550,6 @@ msMapFramebuffer(KdScreenInfo * screen) return TRUE; } -static void -msSetScreenSizes(ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - - if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) { - pScreen->width = gbm_bo_get_width(scrpriv->front); - pScreen->height = gbm_bo_get_height(scrpriv->front); - pScreen->mmWidth = screen->width_mm; - pScreen->mmHeight = screen->height_mm; - } else { - pScreen->width = gbm_bo_get_height(scrpriv->front); - pScreen->height = gbm_bo_get_width(scrpriv->front); - pScreen->mmWidth = screen->height_mm; - pScreen->mmHeight = screen->width_mm; - } -} - Bool msUnmapFramebuffer(KdScreenInfo * screen) { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index ab595179053..a082d7b4302 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -54,8 +54,6 @@ typedef struct _msScreenConf { extern KdCardFuncs msFuncs; -KdCardInfo* msFindMatchingCard(const char *card_path); - Bool msCardInit(KdCardInfo * card); Bool msScreenInit(KdScreenInfo * screen); @@ -80,8 +78,6 @@ void msScreenFini(KdScreenInfo * screen); void msCardFini(KdCardInfo * card); -Bool msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip); - /* ms_gamma.c */ void msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs); @@ -151,4 +147,11 @@ modesetting_find_connector(msPriv *priv, int fd, uint32_t *conn_id); int modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn); +/* ms_util.c */ + +Bool msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip); + +Bool msFdMatch(int fd1, int fd2); + +KdCardInfo* msFindMatchingCard(const char *card_path); #endif /* _MODESETTING_H_ */ diff --git a/hw/kdrive/modesetting/ms_util.c b/hw/kdrive/modesetting/ms_util.c new file mode 100644 index 00000000000..03180b141e6 --- /dev/null +++ b/hw/kdrive/modesetting/ms_util.c @@ -0,0 +1,160 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +/* XXX This really belongs in os/, like the version from glamor_egl */ +Bool +msFdMatch(int fd1, int fd2) +{ + struct stat stat1, stat2; + + if (fd1 == fd2) { + return TRUE; + } + + if (fd1 < 0 || fd2 < 0) { + return FALSE; + } + + if (fstat(fd1, &stat1) < 0 || + fstat(fd2, &stat2) < 0) { + return FALSE; + } + + /** + * From https://pubs.opengroup.org/onlinepubs/009696699/basedefs/sys/stat.h.html + * + * The st_ino and st_dev fields taken together uniquely identify the file within the system. + */ + return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino); +} + +static KdCardInfo* +msFindCardForFd(int fd) +{ + for (KdCardInfo *card = kdCardInfo; card; card = card->next) { + const char *card_path = card->closure; + int cardFd = card_path ? open(card_path, O_RDWR) : -1; + Bool ret = msFdMatch(cardFd, fd); + + if (cardFd >= 0) { + close(cardFd); + } + if (ret) { + return card; + } + } + + return NULL; +} + +KdCardInfo* +msFindMatchingCard(const char *card_path) +{ + KdCardInfo *card; + int fd = card_path ? open(card_path, O_RDWR) : -1; + + card = msFindCardForFd(fd); + + if (fd >= 0) { + close(fd); + } + return card; +} + +static void +msSetScreenSizes(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + + if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) { + pScreen->width = gbm_bo_get_width(scrpriv->front); + pScreen->height = gbm_bo_get_height(scrpriv->front); + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } else { + pScreen->width = gbm_bo_get_height(scrpriv->front); + pScreen->height = gbm_bo_get_width(scrpriv->front); + pScreen->mmWidth = screen->height_mm; + pScreen->mmHeight = screen->width_mm; + } +} + +Bool +msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + struct gbm_bo *old_front; + Bool wasEnabled = pScreenPriv->enabled; + msScrPriv oldscr; + + if (wasEnabled) { + KdDisableScreen(pScreen); + } + + oldscr = *scrpriv; + + old_front = scrpriv->front; + + msUnmapFramebuffer(screen); + + scrpriv->front = bo; + + if (!msMapFramebuffer(screen)) { + goto bail; + } + + KdShadowUnset(screen->pScreen); + + if (!msSetShadow(screen->pScreen)) { + goto bail; + } + + msSetScreenSizes(screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) ((*pScreen->GetScreenPixmap)(pScreen), + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); + + /* set the subpixel order */ + + KdSetSubpixelOrder(pScreen, scrpriv->randr); + + /* Scan out the new bo on the screen's crtc */ + if (wasEnabled) { + KdEnableScreen(pScreen); + } + + if (!flip) { + gbm_bo_destroy(old_front); + } + return TRUE; + +bail: + msUnmapFramebuffer(screen); + old_front = scrpriv->front; + *scrpriv = oldscr; + msMapFramebuffer(screen); + msSetScreenSizes(screen->pScreen); + + if (wasEnabled) { + KdEnableScreen(pScreen); + } + return FALSE; +} From a3e0a0539ec9ec4bbbb7ebca5b3d74932930a70c Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 20:29:52 +0300 Subject: [PATCH 33/47] kdrive/modesetting: Split RandR functions to their own file Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.c | 215 -------------------- hw/kdrive/modesetting/modesetting.h | 21 +- hw/kdrive/modesetting/ms_gamma.c | 77 +------- hw/kdrive/modesetting/ms_randr.c | 292 ++++++++++++++++++++++++++++ 5 files changed, 308 insertions(+), 298 deletions(-) create mode 100644 hw/kdrive/modesetting/ms_randr.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index e35d89c2384..a171ef6c55d 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -4,6 +4,7 @@ srcs = [ 'ms_gamma.c', 'ms_gbm.c', 'ms_query.c', + 'ms_randr.c', 'ms_util.c', '../../stubs/ddxBeforeReset.c', ] diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 0b73ad29408..ce783768ddc 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -142,61 +142,6 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) return ret; } -static Bool -msSetMode(ScreenPtr pScreen, int width, int height, int rate) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msPriv *priv = screen->card->driver; - msScrPriv *scrpriv = screen->driver; - struct gbm_bo *new_front = NULL; - drmModeModeInfo *old_mode; - int old_width, old_height, old_rate; - - old_mode = scrpriv->mode; - - old_width = screen->width; - old_height = screen->height; - old_rate = screen->rate; - - /* Find the mode */ - scrpriv->mode = modesetting_find_mode(scrpriv->connector, width, height, rate); - if (!scrpriv->mode) { - goto bail; - } - - screen->width = width; - screen->height = height; - screen->rate = rate; - - /* Create a new front with the new sizes */ - if (width != screen->width || - height != screen->height) { - uint32_t format = gbm_bo_get_format(scrpriv->front); - Bool do_map = !!gbm_bo_get_map(scrpriv->front); - new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format); - if (!new_front || - !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { - goto bail; - } - } - - return TRUE; - -bail: - if (new_front) { - gbm_bo_destroy(new_front); - } - - screen->width = old_width; - screen->height = old_height; - screen->rate = old_rate; - - scrpriv->mode = old_mode; - - return FALSE; -} - static Bool msInitialize(KdCardInfo * card, msPriv * priv) { @@ -578,166 +523,6 @@ msSetShadow(ScreenPtr pScreen) return KdShadowSet(pScreen, scrpriv->randr, update, window); } -static Bool -msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - Rotation randr; - int n; - - *rotations = RR_Rotate_All | RR_Reflect_All; - - for (n = 0; n < pScreen->numDepths; n++) { - if (pScreen->allowedDepths[n].numVids) { - break; - } - } - - if (n == pScreen->numDepths) { - return FALSE; - } - - randr = KdSubRotation(scrpriv->randr, screen->randr); - - for (int i = 0; i < scrpriv->connector->count_modes; i++) { - drmModeModeInfo *mode = &scrpriv->connector->modes[i]; - RRScreenSizePtr pSize; - pSize = RRRegisterSize(pScreen, - mode->hdisplay, - mode->vdisplay, - screen->width_mm, screen->height_mm); - - RRRegisterRate(pScreen, pSize, mode->vrefresh); - - if (mode->hdisplay == screen->width && - mode->vdisplay == screen->height && - mode->vrefresh == screen->rate) { - RRSetCurrentConfig(pScreen, randr, mode->vrefresh, pSize); - } - } - - return TRUE; -} - -static Bool -msRandRSetConfig(ScreenPtr pScreen, - Rotation randr, int rate, RRScreenSizePtr pSize) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - - int oldmmwidth; - int oldmmheight; - int newmmwidth; - int newmmheight; - - if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { - newmmwidth = pSize->mmWidth; - newmmheight = pSize->mmHeight; - } else { - newmmwidth = pSize->mmHeight; - newmmheight = pSize->mmWidth; - } - - oldmmwidth = pScreen->mmWidth; - oldmmheight = pScreen->mmHeight; - - /* - * Set new configuration - */ - - scrpriv->randr = KdAddRotation(screen->randr, randr); - - pScreen->mmWidth = newmmwidth; - pScreen->mmHeight = newmmheight; - - if (!msSetMode(pScreen, pSize->width, pSize->height, rate)) { - goto bail; - } - - return TRUE; - -bail: - pScreen->mmWidth = oldmmwidth; - pScreen->mmHeight = oldmmheight; - return FALSE; -} - -#ifdef RANDR -static Bool -msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - - *mmWidth = screen->width_mm; - *mmHeight = screen->height_mm; - - if (screen->requested_mm) { - return TRUE; - } - - if (((int)scrpriv->connector->mmWidth > 0) && ((int)scrpriv->connector->mmHeight > 0)) { - *mmWidth = scrpriv->connector->mmWidth; - *mmWidth = scrpriv->connector->mmHeight; - return TRUE; - } - - return FALSE; -} - -static Bool -msRandRSetPhysicalScreenSizes(ScreenPtr pScreen) -{ - int mmWidth, mmHeight; - - if (msGetPhysicalScreenSizes(pScreen, &mmWidth, &mmHeight)) { - RROutputPtr pOutput; - pOutput = RRFirstOutput(pScreen); - - if (!pOutput) { - return FALSE; - } - - RROutputSetPhysicalSize(pOutput, - mmWidth, - mmHeight); - } - - return TRUE; -} - -static Bool -msRandRInit(ScreenPtr pScreen) -{ - rrScrPrivPtr pScrPriv; - - if (!RRScreenInit(pScreen)) { - return FALSE; - } - - pScrPriv = rrGetScrPriv(pScreen); - pScrPriv->rrGetInfo = msRandRGetInfo; - pScrPriv->rrSetConfig = msRandRSetConfig; - - /* Create the output */ - RRGetInfo(pScreen, TRUE); - - msRandRSetPhysicalScreenSizes(pScreen); - -#if RANDR_12_INTERFACE - if (msRandRGammaInit(pScreen)) { - pScrPriv->rrCrtcSetGamma = msRandRCrtcSetGamma; - } -#endif - return TRUE; -} -#endif /* RANDR */ - Bool msInitScreen(ScreenPtr pScreen) { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index a082d7b4302..0c6841abfa7 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -80,17 +80,16 @@ void msCardFini(KdCardInfo * card); /* ms_gamma.c */ +Bool +msGetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b); + +Bool +msSetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b); + void msGetColors(ScreenPtr pScreen, int n, xColorItem * pdefs); void msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs); -#ifdef RANDR -#if RANDR_12_INTERFACE -Bool msRandRCrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc); -#endif -Bool msRandRGammaInit(ScreenPtr pScreen); -#endif - #ifdef GLAMOR /* ms_glamor.c */ @@ -103,7 +102,7 @@ void msEnableAccel(ScreenPtr screen); void msDisableAccel(ScreenPtr screen); void msFiniAccel(ScreenPtr screen); -#endif +#endif /* GLAMOR */ void msCloseScreen(ScreenPtr pScreen); @@ -147,6 +146,12 @@ modesetting_find_connector(msPriv *priv, int fd, uint32_t *conn_id); int modeseting_find_crtc(msPriv *priv, int fd, drmModeConnector *conn); +#ifdef RANDR +/* ms_randr.c */ + +Bool msRandRInit(ScreenPtr pScreen); +#endif /* RANDR */ + /* ms_util.c */ Bool msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip); diff --git a/hw/kdrive/modesetting/ms_gamma.c b/hw/kdrive/modesetting/ms_gamma.c index ee474cd075a..3e47e96b6ab 100644 --- a/hw/kdrive/modesetting/ms_gamma.c +++ b/hw/kdrive/modesetting/ms_gamma.c @@ -7,7 +7,7 @@ #include "modesetting.h" -static Bool +Bool msGetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b) { KdScreenPriv(pScreen); @@ -39,7 +39,7 @@ msGetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b) return FALSE; } -static Bool +Bool msSetGamma(ScreenPtr pScreen, int size, uint16_t *r, uint16_t *g, uint16_t *b) { KdScreenPriv(pScreen); @@ -115,76 +115,3 @@ msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs) msSetGamma(pScreen, max, r, g, b); } - -#ifdef RANDR -#if RANDR_12_INTERFACE -Bool -msRandRCrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc) -{ - return msSetGamma(pScreen, crtc->gammaSize, crtc->gammaRed, crtc->gammaGreen, crtc->gammaBlue); -} -#endif -Bool -msRandRGammaInit(ScreenPtr pScreen) -{ -#if RANDR_12_INTERFACE - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *priv = screen->driver; - RROutputPtr pOutput; - RRCrtcPtr crtc; - - uint16_t *gamma; - int gamma_size; - - pOutput = RRFirstOutput(pScreen); - if (!pOutput) { - return FALSE; - } - - if (!pOutput->numCrtcs || !pOutput->crtcs) { - return FALSE; - } - - crtc = pOutput->crtc ? pOutput->crtc : pOutput->crtcs[0]; - if (!crtc) { - return FALSE; - } - - if (priv->crtc && priv->crtc->gamma_size) { - gamma_size = priv->crtc->gamma_size; - } else { - switch (screen->fb.depth) { - case 8: - gamma_size = 1 << 8; - case 15: - gamma_size = 1 << 5; - case 16: - gamma_size = 1 << 6; - case 24: - gamma_size = 1 << 8; - case 30: - default: - gamma_size = 1 << 10; - } - } - - gamma = calloc(3 * gamma_size, sizeof(*gamma)); - if (!gamma) { - return FALSE; - } - - if (!RRCrtcGammaSetSize(crtc, gamma_size)) { - return FALSE; - } - - msGetGamma(pScreen, gamma_size, gamma, gamma + gamma_size, gamma + 2 * gamma_size); - RRCrtcGammaSet(crtc, gamma, gamma + gamma_size, gamma + 2 * gamma_size); - - free(gamma); - return TRUE; -#else /* RANDR_12_INTERFACE */ - return FALSE; -#endif -} -#endif /* RANDR */ diff --git a/hw/kdrive/modesetting/ms_randr.c b/hw/kdrive/modesetting/ms_randr.c new file mode 100644 index 00000000000..be7133f2162 --- /dev/null +++ b/hw/kdrive/modesetting/ms_randr.c @@ -0,0 +1,292 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +#ifdef RANDR + +static Bool +msSetMode(ScreenPtr pScreen, int width, int height, int rate) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + struct gbm_bo *new_front = NULL; + drmModeModeInfo *old_mode; + int old_width, old_height, old_rate; + + old_mode = scrpriv->mode; + + old_width = screen->width; + old_height = screen->height; + old_rate = screen->rate; + + /* Find the mode */ + scrpriv->mode = modesetting_find_mode(scrpriv->connector, width, height, rate); + if (!scrpriv->mode) { + goto bail; + } + + screen->width = width; + screen->height = height; + screen->rate = rate; + + /* Create a new front with the new sizes */ + if (width != screen->width || + height != screen->height) { + uint32_t format = gbm_bo_get_format(scrpriv->front); + Bool do_map = !!gbm_bo_get_map(scrpriv->front); + new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format); + if (!new_front || + !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { + goto bail; + } + } + + return TRUE; + +bail: + if (new_front) { + gbm_bo_destroy(new_front); + } + + screen->width = old_width; + screen->height = old_height; + screen->rate = old_rate; + + scrpriv->mode = old_mode; + + return FALSE; +} + +static Bool +msRandRGetInfo(ScreenPtr pScreen, Rotation * rotations) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + Rotation randr; + int n; + + *rotations = RR_Rotate_All | RR_Reflect_All; + + for (n = 0; n < pScreen->numDepths; n++) { + if (pScreen->allowedDepths[n].numVids) { + break; + } + } + + if (n == pScreen->numDepths) { + return FALSE; + } + + randr = KdSubRotation(scrpriv->randr, screen->randr); + + for (int i = 0; i < scrpriv->connector->count_modes; i++) { + drmModeModeInfo *mode = &scrpriv->connector->modes[i]; + RRScreenSizePtr pSize; + pSize = RRRegisterSize(pScreen, + mode->hdisplay, + mode->vdisplay, + screen->width_mm, screen->height_mm); + + RRRegisterRate(pScreen, pSize, mode->vrefresh); + + if (mode->hdisplay == screen->width && + mode->vdisplay == screen->height && + mode->vrefresh == screen->rate) { + RRSetCurrentConfig(pScreen, randr, mode->vrefresh, pSize); + } + } + + return TRUE; +} + +static Bool +msRandRSetConfig(ScreenPtr pScreen, + Rotation randr, int rate, RRScreenSizePtr pSize) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + + int oldmmwidth; + int oldmmheight; + int newmmwidth; + int newmmheight; + + if (screen->randr & (RR_Rotate_0 | RR_Rotate_180)) { + newmmwidth = pSize->mmWidth; + newmmheight = pSize->mmHeight; + } else { + newmmwidth = pSize->mmHeight; + newmmheight = pSize->mmWidth; + } + + oldmmwidth = pScreen->mmWidth; + oldmmheight = pScreen->mmHeight; + + /* + * Set new configuration + */ + + scrpriv->randr = KdAddRotation(screen->randr, randr); + + pScreen->mmWidth = newmmwidth; + pScreen->mmHeight = newmmheight; + + if (!msSetMode(pScreen, pSize->width, pSize->height, rate)) { + goto bail; + } + + return TRUE; + +bail: + pScreen->mmWidth = oldmmwidth; + pScreen->mmHeight = oldmmheight; + return FALSE; +} + +static Bool +msGetPhysicalScreenSizes(ScreenPtr pScreen, int *mmWidth, int *mmHeight) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + + *mmWidth = screen->width_mm; + *mmHeight = screen->height_mm; + + if (screen->requested_mm) { + return TRUE; + } + + if (((int)scrpriv->connector->mmWidth > 0) && ((int)scrpriv->connector->mmHeight > 0)) { + *mmWidth = scrpriv->connector->mmWidth; + *mmWidth = scrpriv->connector->mmHeight; + return TRUE; + } + + return FALSE; +} + +static Bool +msRandRSetPhysicalScreenSizes(ScreenPtr pScreen) +{ + int mmWidth, mmHeight; + + if (msGetPhysicalScreenSizes(pScreen, &mmWidth, &mmHeight)) { + RROutputPtr pOutput; + pOutput = RRFirstOutput(pScreen); + + if (!pOutput) { + return FALSE; + } + + RROutputSetPhysicalSize(pOutput, + mmWidth, + mmHeight); + } + + return TRUE; +} + +#if RANDR_12_INTERFACE +static Bool +msRandRCrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr crtc) +{ + return msSetGamma(pScreen, crtc->gammaSize, crtc->gammaRed, crtc->gammaGreen, crtc->gammaBlue); +} + +static Bool +msRandRGammaInit(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + RROutputPtr pOutput; + RRCrtcPtr crtc; + + uint16_t *gamma; + int gamma_size; + + pOutput = RRFirstOutput(pScreen); + if (!pOutput) { + return FALSE; + } + + if (!pOutput->numCrtcs || !pOutput->crtcs) { + return FALSE; + } + + crtc = pOutput->crtc ? pOutput->crtc : pOutput->crtcs[0]; + if (!crtc) { + return FALSE; + } + + if (priv->crtc && priv->crtc->gamma_size) { + gamma_size = priv->crtc->gamma_size; + } else { + switch (screen->fb.depth) { + case 8: + gamma_size = 1 << 8; + case 15: + gamma_size = 1 << 5; + case 16: + gamma_size = 1 << 6; + case 24: + gamma_size = 1 << 8; + case 30: + default: + gamma_size = 1 << 10; + } + } + + gamma = calloc(3 * gamma_size, sizeof(*gamma)); + if (!gamma) { + return FALSE; + } + + if (!RRCrtcGammaSetSize(crtc, gamma_size)) { + return FALSE; + } + + msGetGamma(pScreen, gamma_size, gamma, gamma + gamma_size, gamma + 2 * gamma_size); + RRCrtcGammaSet(crtc, gamma, gamma + gamma_size, gamma + 2 * gamma_size); + + free(gamma); + return TRUE; +} +#endif /* RANDR_12_INTERFACE */ + +Bool +msRandRInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit(pScreen)) { + return FALSE; + } + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = msRandRGetInfo; + pScrPriv->rrSetConfig = msRandRSetConfig; + + /* Create the output */ + RRGetInfo(pScreen, TRUE); + + msRandRSetPhysicalScreenSizes(pScreen); + +#if RANDR_12_INTERFACE + if (msRandRGammaInit(pScreen)) { + pScrPriv->rrCrtcSetGamma = msRandRCrtcSetGamma; + } +#endif + return TRUE; +} +#endif /* RANDR */ From 4c5dce1a68925257a61b5628af31271dbf7c11b3 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 20:43:05 +0300 Subject: [PATCH 34/47] kdrive/modesetting: Split damage-tracking functions to their own file Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.c | 175 +------------------------ hw/kdrive/modesetting/modesetting.h | 26 ++-- hw/kdrive/modesetting/ms_damage.c | 194 ++++++++++++++++++++++++++++ hw/kdrive/modesetting/msinit.c | 2 +- 5 files changed, 213 insertions(+), 185 deletions(-) create mode 100644 hw/kdrive/modesetting/ms_damage.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index a171ef6c55d..d6acf11960b 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -1,6 +1,7 @@ srcs = [ 'modesetting.c', 'msinit.c', + 'ms_damage.c', 'ms_gamma.c', 'ms_gbm.c', 'ms_query.c', diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index ce783768ddc..92f17032f6e 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -544,142 +544,9 @@ msFinishInitScreen(ScreenPtr pScreen) return TRUE; } -static void -msFixupDamageRegion(msScrPriv *scrpriv, int w, int h, drmModeClip *clip, BoxPtr rect) -{ - Rotation randr = scrpriv->randr & (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); - - switch (randr) { - case RR_Rotate_0: - clip->x1 = rect->x1; - clip->x2 = rect->x2; - clip->y1 = rect->y1; - clip->y2 = rect->y2; - break; - case RR_Rotate_90: - clip->x1 = rect->y1; - clip->y1 = w - rect->x2; - clip->x2 = rect->y2; - clip->y2 = w - rect->x1; - break; - case RR_Rotate_180: - clip->x1 = w - rect->x2; - clip->y1 = h - rect->y2; - clip->x2 = w - rect->x1; - clip->y2 = h - rect->y1; - break; - case RR_Rotate_270: - clip->x1 = h - rect->y2; - clip->y1 = rect->x1; - clip->x2 = h - rect->y1; - clip->y2 = rect->x2; - break; - default: - clip->x1 = 0; - clip->y1 = 0; - clip->x2 = w; - clip->y2 = h; - break; - } -} - -/* Heavily inspired from the Xorg modesetting driver */ -static void -msBlockHandler(void *blockData, void *timeout) -{ - ScreenPtr pScreen = blockData; - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *priv = screen->driver; - RegionPtr dirty; - drmModeClip full_clip; - struct gbm_device *gbm; - uint32_t fb_id; - int fd; - uint32_t width; - uint32_t height; - unsigned num_cliprects; - - gbm = gbm_bo_get_device(priv->front); - fb_id = gbm_bo_get_fb(priv->front); - fd = gbm_device_get_fd(gbm); - - width = gbm_bo_get_width(priv->front); - height = gbm_bo_get_height(priv->front); - - full_clip = (drmModeClip){.x1 = 0, .y1 = 0, .x2 = width, .y2 = height,}; - - if (!priv->damage) { - goto bail; - } - - dirty = DamageRegion(priv->damage); - - num_cliprects = REGION_NUM_RECTS(dirty); - - if (num_cliprects) { - drmModeClip *clip = calloc(num_cliprects, sizeof(drmModeClip)); - BoxPtr rect = REGION_RECTS(dirty); - int ret; - - if (!clip) { - goto bail; - } - - for (int i = 0; i < num_cliprects; i++) { - msFixupDamageRegion(priv, width, height, &clip[i], &rect[i]); - } - - /* TODO query connector property to see if this is needed */ - ret = drmModeDirtyFB(fd, fb_id, clip, num_cliprects); - - /* if we're swamping it with work, try one at a time */ - if (ret) { - for (int i = 0; i < num_cliprects; i++) { - ret = drmModeDirtyFB(fd, fb_id, &clip[i], 1); - if (ret) { - break; - } - } - } - - free(clip); - - if (ret) { - goto bail; - } - } - - DamageEmpty(priv->damage); - return; - -bail: - drmModeDirtyFB(fd, fb_id, &full_clip, 1); - if (priv->damage) { - DamageEmpty(priv->damage); - } -} - -static void -msWakeupHandler(void *blockData, int result) -{ -} - Bool msCreateResources(ScreenPtr pScreen) { - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *priv = screen->driver; - PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); - struct gbm_device *gbm; - uint32_t fb_id; - int fd; - - gbm = gbm_bo_get_device(priv->front); - fb_id = gbm_bo_get_fb(priv->front); - fd = gbm_device_get_fd(gbm); - if (!msSetShadow(pScreen)) { return FALSE; } @@ -690,30 +557,10 @@ msCreateResources(ScreenPtr pScreen) } #endif - /* Damage tracking not supported/needed */ - if (drmModeDirtyFB(fd, fb_id, NULL, 0) && - ((errno == EINVAL) || (errno == ENOSYS))) { - return TRUE; - } - - priv->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, - pScreen, rootPixmap); - - if (priv->damage) { - DamageRegister(&rootPixmap->drawable, priv->damage); - } - - if (!RegisterBlockAndWakeupHandlers(msBlockHandler, msWakeupHandler, pScreen)) { - if (priv->damage) { - DamageUnregister(priv->damage); - DamageDestroy(priv->damage); - priv->damage = NULL; - } + if (!msDamageCreateRes(pScreen)) { return FALSE; } - priv->blockHandler = TRUE; - return TRUE; } @@ -819,22 +666,4 @@ msCardFini(KdCardInfo * card) close(fd); free(priv); card->driver = NULL; -} - -void -msCloseScreen(ScreenPtr pScreen) -{ - KdScreenPriv(pScreen); - KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *priv = screen->driver; - - if (!priv->blockHandler) { - return; - } - - RemoveBlockAndWakeupHandlers(msBlockHandler, msWakeupHandler, pScreen); - if (priv->damage) { - DamageUnregister(priv->damage); - DamageDestroy(priv->damage); - } -} +} \ No newline at end of file diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 0c6841abfa7..57d7b2f0579 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -78,6 +78,21 @@ void msScreenFini(KdScreenInfo * screen); void msCardFini(KdCardInfo * card); +Bool msMapFramebuffer(KdScreenInfo * screen); + +Bool msUnmapFramebuffer(KdScreenInfo * screen); + +Bool msSetShadow(ScreenPtr pScreen); + +struct gbm_bo* +modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map); + +/* ms_damage.c */ + +Bool msDamageCreateRes(ScreenPtr pScreen); + +void msDamageCloseScreen(ScreenPtr pScreen); + /* ms_gamma.c */ Bool @@ -104,17 +119,6 @@ void msDisableAccel(ScreenPtr screen); void msFiniAccel(ScreenPtr screen); #endif /* GLAMOR */ -void msCloseScreen(ScreenPtr pScreen); - -Bool msMapFramebuffer(KdScreenInfo * screen); - -Bool msUnmapFramebuffer(KdScreenInfo * screen); - -Bool msSetShadow(ScreenPtr pScreen); - -struct gbm_bo* -modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map); - /* ms_gbm.c */ void* diff --git a/hw/kdrive/modesetting/ms_damage.c b/hw/kdrive/modesetting/ms_damage.c new file mode 100644 index 00000000000..198010d8a3b --- /dev/null +++ b/hw/kdrive/modesetting/ms_damage.c @@ -0,0 +1,194 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +#include + +/* Track and report front buffer damage to the kernel */ + +/* Heavily inspired from the Xorg modesetting driver */ + +static void +msFixupDamageRegion(msScrPriv *scrpriv, int w, int h, drmModeClip *clip, BoxPtr rect) +{ + Rotation randr = scrpriv->randr & (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270); + + switch (randr) { + case RR_Rotate_0: + clip->x1 = rect->x1; + clip->x2 = rect->x2; + clip->y1 = rect->y1; + clip->y2 = rect->y2; + break; + case RR_Rotate_90: + clip->x1 = rect->y1; + clip->y1 = w - rect->x2; + clip->x2 = rect->y2; + clip->y2 = w - rect->x1; + break; + case RR_Rotate_180: + clip->x1 = w - rect->x2; + clip->y1 = h - rect->y2; + clip->x2 = w - rect->x1; + clip->y2 = h - rect->y1; + break; + case RR_Rotate_270: + clip->x1 = h - rect->y2; + clip->y1 = rect->x1; + clip->x2 = h - rect->y1; + clip->y2 = rect->x2; + break; + default: + clip->x1 = 0; + clip->y1 = 0; + clip->x2 = w; + clip->y2 = h; + break; + } +} + +static void +msDamageBlockHandler(void *blockData, void *timeout) +{ + ScreenPtr pScreen = blockData; + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + RegionPtr dirty; + drmModeClip full_clip; + struct gbm_device *gbm; + uint32_t fb_id; + int fd; + uint32_t width; + uint32_t height; + unsigned num_cliprects; + + gbm = gbm_bo_get_device(priv->front); + fb_id = gbm_bo_get_fb(priv->front); + fd = gbm_device_get_fd(gbm); + + width = gbm_bo_get_width(priv->front); + height = gbm_bo_get_height(priv->front); + + full_clip = (drmModeClip){.x1 = 0, .y1 = 0, .x2 = width, .y2 = height,}; + + if (!priv->damage) { + goto bail; + } + + dirty = DamageRegion(priv->damage); + + num_cliprects = REGION_NUM_RECTS(dirty); + + if (num_cliprects) { + drmModeClip *clip = calloc(num_cliprects, sizeof(drmModeClip)); + BoxPtr rect = REGION_RECTS(dirty); + int ret; + + if (!clip) { + goto bail; + } + + for (int i = 0; i < num_cliprects; i++) { + msFixupDamageRegion(priv, width, height, &clip[i], &rect[i]); + } + + /* TODO query connector property to see if this is needed */ + ret = drmModeDirtyFB(fd, fb_id, clip, num_cliprects); + + /* if we're swamping it with work, try one at a time */ + if (ret) { + for (int i = 0; i < num_cliprects; i++) { + ret = drmModeDirtyFB(fd, fb_id, &clip[i], 1); + if (ret) { + break; + } + } + } + + free(clip); + + if (ret) { + goto bail; + } + } + + DamageEmpty(priv->damage); + return; + +bail: + drmModeDirtyFB(fd, fb_id, &full_clip, 1); + if (priv->damage) { + DamageEmpty(priv->damage); + } +} + +static void +msDamageWakeupHandler(void *blockData, int result) +{ +} + +Bool +msDamageCreateRes(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); + struct gbm_device *gbm; + uint32_t fb_id; + int fd; + + gbm = gbm_bo_get_device(priv->front); + fb_id = gbm_bo_get_fb(priv->front); + fd = gbm_device_get_fd(gbm); + + /* Damage tracking not supported/needed */ + if (drmModeDirtyFB(fd, fb_id, NULL, 0) && + ((errno == EINVAL) || (errno == ENOSYS))) { + return TRUE; + } + + priv->damage = DamageCreate(NULL, NULL, DamageReportNone, TRUE, + pScreen, rootPixmap); + + if (priv->damage) { + DamageRegister(&rootPixmap->drawable, priv->damage); + } + + if (!RegisterBlockAndWakeupHandlers(msDamageBlockHandler, msDamageWakeupHandler, pScreen)) { + if (priv->damage) { + DamageUnregister(priv->damage); + DamageDestroy(priv->damage); + priv->damage = NULL; + } + return FALSE; + } + + priv->blockHandler = TRUE; + + return TRUE; +} + +void +msDamageCloseScreen(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *priv = screen->driver; + + if (!priv->blockHandler) { + return; + } + + RemoveBlockAndWakeupHandlers(msDamageBlockHandler, msDamageWakeupHandler, pScreen); + if (priv->damage) { + DamageUnregister(priv->damage); + DamageDestroy(priv->damage); + } +} diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index b1858e922aa..47f9d5032c8 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -321,5 +321,5 @@ KdCardFuncs msFuncs = { .getColors = msGetColors, .putColors = msPutColors, - .closeScreen = msCloseScreen, + .closeScreen = msDamageCloseScreen, }; From 737b47b2dc0a2918044683a23b0ed40f1675f43d Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 20:59:31 +0300 Subject: [PATCH 35/47] kdrive/modesetting: Split visual mask setting to a separate function Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 84 +---------------------------- hw/kdrive/modesetting/modesetting.h | 3 ++ hw/kdrive/modesetting/ms_gbm.c | 82 ++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 82 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 92f17032f6e..5513ea60bf0 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -270,13 +270,9 @@ modesetting_claim_connector_crtc(msPriv *priv, uint32_t conn, int crtc) static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) { -#ifdef GLAMOR MsScreenConf *config = screen->closure; -#endif msPriv *priv = screen->card->driver; int fd = gbm_device_get_fd(priv->gbm); - uint32_t format; - Bool rb_swap = FALSE; scrpriv->connector = modesetting_find_connector(priv, fd, &scrpriv->conn_id); if (!scrpriv->connector) { @@ -319,83 +315,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = gbm_bo_get_height(scrpriv->front); screen->rate = scrpriv->mode ? scrpriv->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ - format = gbm_bo_get_format(scrpriv->front); - - switch (format) { - case GBM_FORMAT_C8: - case GBM_FORMAT_R8: - screen->fb.depth = 8; - screen->fb.bitsPerPixel = 8; - screen->fb.visuals = (1 << GrayScale); - screen->fb.redMask = 0xff; - screen->fb.greenMask = 0x00; - screen->fb.blueMask = 0x00; - break; - case GBM_FORMAT_XBGR1555: - rb_swap = TRUE; - case GBM_FORMAT_XRGB1555: - screen->fb.depth = 15; - screen->fb.bitsPerPixel = 16; - screen->fb.visuals = (1 << TrueColor); - screen->fb.redMask = 0x1f << 10; - screen->fb.greenMask = 0x1f << 5; - screen->fb.blueMask = 0x1f; - break; - case GBM_FORMAT_BGR565: - rb_swap = TRUE; - case GBM_FORMAT_RGB565: - screen->fb.depth = 16; - screen->fb.bitsPerPixel = 16; - screen->fb.visuals = (1 << TrueColor); - screen->fb.redMask = 0x1f << 11; - screen->fb.greenMask = 0x3f << 5; - screen->fb.blueMask = 0x1f; - break; - case GBM_FORMAT_BGR888: - rb_swap = TRUE; - case GBM_FORMAT_RGB888: - screen->fb.depth = 24; - screen->fb.bitsPerPixel = 24; - screen->fb.visuals = (1 << TrueColor); - screen->fb.redMask = 0xff << 16; - screen->fb.greenMask = 0xff << 8; - screen->fb.blueMask = 0xff; - break; - case GBM_FORMAT_XBGR8888: - rb_swap = TRUE; - case GBM_FORMAT_XRGB8888: - screen->fb.depth = 24; - screen->fb.bitsPerPixel = 32; - screen->fb.visuals = (1 << TrueColor); - screen->fb.redMask = 0xff << 16; - screen->fb.greenMask = 0xff << 8; - screen->fb.blueMask = 0xff; - break; - case GBM_FORMAT_XBGR2101010: - rb_swap = TRUE; - case GBM_FORMAT_XRGB2101010: - screen->fb.depth = 30; - screen->fb.bitsPerPixel = 32; - screen->fb.visuals = (1 << TrueColor); - screen->fb.redMask = 0x3ff << 20; - screen->fb.greenMask = 0x3ff <<10; - screen->fb.blueMask = 0x3ff; - break; - } - - /* XXX Tiled buffers don't need r-b swap, unless it's depth 30 on gles */ - if (!gbm_bo_get_map(scrpriv->front)) { - if (screen->fb.depth != 30 || - !config->glamor_info.force_es) { - rb_swap = FALSE; - } - } - - if (rb_swap) { - int tmp = screen->fb.blueMask; - screen->fb.blueMask = screen->fb.redMask; - screen->fb.redMask = tmp; - } + gbm_bo_set_screen_fb_info(scrpriv->front, screen, config->glamor_info.force_es); scrpriv->randr = screen->randr; if (!msMapFramebuffer(screen)) { @@ -666,4 +586,4 @@ msCardFini(KdCardInfo * card) close(fd); free(priv); card->driver = NULL; -} \ No newline at end of file +} diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 57d7b2f0579..cca2c918b48 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -139,6 +139,9 @@ gbm_format_get_depth(uint32_t format); struct gbm_bo* gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format); +void +gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles); + /* ms_query.c */ drmModeModeInfo* diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index e1c447a58ff..bcf9a9520e0 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -330,3 +330,85 @@ gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_ return NULL; } + +void +gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles) +{ + uint32_t format = gbm_bo_get_format(bo); + Bool rb_swap = FALSE; + + switch (format) { + case GBM_FORMAT_C8: + case GBM_FORMAT_R8: + screen->fb.depth = 8; + screen->fb.bitsPerPixel = 8; + screen->fb.visuals = (1 << GrayScale); + screen->fb.redMask = 0xff; + screen->fb.greenMask = 0x00; + screen->fb.blueMask = 0x00; + break; + case GBM_FORMAT_XBGR1555: + rb_swap = TRUE; + case GBM_FORMAT_XRGB1555: + screen->fb.depth = 15; + screen->fb.bitsPerPixel = 16; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0x1f << 10; + screen->fb.greenMask = 0x1f << 5; + screen->fb.blueMask = 0x1f; + break; + case GBM_FORMAT_BGR565: + rb_swap = TRUE; + case GBM_FORMAT_RGB565: + screen->fb.depth = 16; + screen->fb.bitsPerPixel = 16; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0x1f << 11; + screen->fb.greenMask = 0x3f << 5; + screen->fb.blueMask = 0x1f; + break; + case GBM_FORMAT_BGR888: + rb_swap = TRUE; + case GBM_FORMAT_RGB888: + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 24; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0xff << 16; + screen->fb.greenMask = 0xff << 8; + screen->fb.blueMask = 0xff; + break; + case GBM_FORMAT_XBGR8888: + rb_swap = TRUE; + case GBM_FORMAT_XRGB8888: + screen->fb.depth = 24; + screen->fb.bitsPerPixel = 32; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0xff << 16; + screen->fb.greenMask = 0xff << 8; + screen->fb.blueMask = 0xff; + break; + case GBM_FORMAT_XBGR2101010: + rb_swap = TRUE; + case GBM_FORMAT_XRGB2101010: + screen->fb.depth = 30; + screen->fb.bitsPerPixel = 32; + screen->fb.visuals = (1 << TrueColor); + screen->fb.redMask = 0x3ff << 20; + screen->fb.greenMask = 0x3ff <<10; + screen->fb.blueMask = 0x3ff; + break; + } + + /* XXX Tiled buffers don't need r-b swap, unless it's depth 30 on gles */ + if (!gbm_bo_get_map(bo)) { + if (screen->fb.depth != 30 || !is_gles) { + rb_swap = FALSE; + } + } + + if (rb_swap) { + int tmp = screen->fb.blueMask; + screen->fb.blueMask = screen->fb.redMask; + screen->fb.redMask = tmp; + } +} From 3427a6e63c0dbdc30ca9adc44ee96dabbcf02cce Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 21:07:20 +0300 Subject: [PATCH 36/47] kdrive/modesetting: Rename the glamor functions Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.h | 8 ++++---- hw/kdrive/modesetting/ms_glamor.c | 8 ++++---- hw/kdrive/modesetting/msinit.c | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index cca2c918b48..6df344a2543 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -110,13 +110,13 @@ void msPutColors(ScreenPtr pScreen, int n, xColorItem * pdefs); Bool msGlamorCreateRes(ScreenPtr pScreen); -Bool msInitAccel(ScreenPtr screen); +Bool msGlamorInit(ScreenPtr screen); -void msEnableAccel(ScreenPtr screen); +void msGlamorEnable(ScreenPtr screen); -void msDisableAccel(ScreenPtr screen); +void msGlamorDisable(ScreenPtr screen); -void msFiniAccel(ScreenPtr screen); +void msGlamorFini(ScreenPtr screen); #endif /* GLAMOR */ /* ms_gbm.c */ diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 95c2c0dcd1f..2d97f7aea39 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -81,7 +81,7 @@ msGlamorMapFront(ScreenPtr pScreen) } Bool -msInitAccel(ScreenPtr pScreen) +msGlamorInit(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; @@ -105,19 +105,19 @@ msInitAccel(ScreenPtr pScreen) } void -msEnableAccel(ScreenPtr pScreen) +msGlamorEnable(ScreenPtr pScreen) { KdGlamorEnable(pScreen); } void -msDisableAccel(ScreenPtr pScreen) +msGlamorDisable(ScreenPtr pScreen) { KdGlamorDisable(pScreen); } void -msFiniAccel(ScreenPtr pScreen) +msGlamorFini(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 47f9d5032c8..bb41d9b11f9 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -312,10 +312,10 @@ KdCardFuncs msFuncs = { /* no cursor funcs */ #ifdef GLAMOR - .initAccel = msInitAccel, - .enableAccel = msEnableAccel, - .disableAccel = msDisableAccel, - .finiAccel = msFiniAccel, + .initAccel = msGlamorInit, + .enableAccel = msGlamorEnable, + .disableAccel = msGlamorDisable, + .finiAccel = msGlamorFini, #endif .getColors = msGetColors, From 9d21e621df3411e03bf0940ba567e7051b38f13f Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Thu, 24 Sep 2026 21:17:10 +0300 Subject: [PATCH 37/47] kdrive/modesetting: query renderable modifiers Not doing anything with them yet. In preparation for further work Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.h | 3 +++ hw/kdrive/modesetting/ms_glamor.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 6df344a2543..e756e4f142e 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -44,6 +44,9 @@ typedef struct _msScrPriv { Bool error; Bool setPixmapBits; + + uint32_t num_render_modifiers; + uint64_t *render_modifiers; } msScrPriv; typedef struct _msScreenConf { diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 2d97f7aea39..5ea363ec16d 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -10,6 +10,8 @@ #include "glamor.h" +#include + static Bool msGlamorMapFront(ScreenPtr pScreen); @@ -87,6 +89,8 @@ msGlamorInit(ScreenPtr pScreen) KdScreenInfo *screen = pScreenPriv->screen; MsScreenConf *config = screen->closure; msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + uint32_t format; if (!config->glamor_info.dri_path) { config->glamor_info.dri_fd = dup(gbm_device_get_fd(priv->gbm)); @@ -101,6 +105,25 @@ msGlamorInit(ScreenPtr pScreen) return FALSE; } + /* + * TODO: Don't assume all formats support the same modifiers + * + * Not that we can do much if we are forced to chose a different format + */ + format = gbm_bo_get_format(scrpriv->front); + if (!glamor_get_modifiers(pScreen, format, + &scrpriv->num_render_modifiers, + &scrpriv->render_modifiers)) { + scrpriv->num_render_modifiers = 0; + scrpriv->render_modifiers = NULL; + } + + if (scrpriv->num_render_modifiers == 1 && + scrpriv->render_modifiers[0] == DRM_FORMAT_MOD_INVALID) { + free(scrpriv->render_modifiers); + scrpriv->num_render_modifiers = 0; + } + return TRUE; } @@ -122,6 +145,10 @@ msGlamorFini(ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; MsScreenConf *config = screen->closure; + msScrPriv *scrpriv = screen->driver; + free(scrpriv->render_modifiers); + scrpriv->render_modifiers = NULL; + scrpriv->num_render_modifiers = 0; KdGlamorFini(pScreen, &config->glamor_info); } From 429a841328ba1b97f4f26b8e66d308178c7bbb76 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 25 Sep 2026 00:26:57 +0300 Subject: [PATCH 38/47] kdrive/modesetting: Plug in modifier support Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 53 +++++------ hw/kdrive/modesetting/modesetting.h | 8 +- hw/kdrive/modesetting/ms_gbm.c | 45 +++++++-- hw/kdrive/modesetting/ms_glamor.c | 142 +++++++++++++++++++--------- hw/kdrive/modesetting/ms_randr.c | 9 +- 5 files changed, 172 insertions(+), 85 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 5513ea60bf0..dc88a5bdcf6 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -15,30 +15,26 @@ #endif struct gbm_bo* -modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) +modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map, Bool keep_depth) { -#ifdef GLAMOR - MsScreenConf *config = screen->closure; -#endif struct gbm_bo *ret = NULL; uint32_t format, format_swap; - /* - * XXX This all simplifies with modifier support - * - * Just query the renderable modifiers on the render card, - * and allocate a gbm bo on the scanout card using those modifiers. - * - * If that fails, fall back to dumb buffers. + MsScreenConf *config = screen->closure; + msScrPriv *scrpriv = screen->driver; + /* TODO: Query scanout modifiers in CardInit, + * intersect with render modifiers queried in msGlamorInit */ + uint64_t *modifiers = scrpriv ? scrpriv->render_modifiers : NULL; + int num_modifiers = scrpriv ? scrpriv->num_render_modifiers : 0; + /* XXX depth 30 needs more care because of the visual mask swap */ + Bool careful = screen->fb.depth == 30 && !config->glamor_info.force_es; #ifdef GLAMOR if (screen->dumb) { need_map = TRUE; - } else if (config->glamor_info.dri_path) { + } else if (careful && config->glamor_info.dri_path) { /* - * Until modifier support, we want to be conservative here. - * * If the render card is different fron the scanout card, assume the modifier sets are disjoint. * If the cards are the same, and it is from nvidia, and the gbm backend is mesa or dumb, * assume that buffers are not renderable. @@ -51,7 +47,7 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) if (dri_fd >= 0) { close(dri_fd); } - } else { + } else if (careful) { drmVersionPtr version; Bool is_nvidia = TRUE; Bool backend_is_mesa = FALSE; @@ -83,6 +79,8 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) } } } +#else + need_map = TRUE; #endif while (!ret) { @@ -95,28 +93,27 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map) format_swap = tmp; } -#ifdef GLAMOR - if (!need_map) { - if (!ret) { - ret = gbm_create_front_bo(priv->gbm, FALSE /* do map */, screen->width, screen->height, format); - } - if (!ret) { - ret = gbm_create_front_bo(priv->gbm, FALSE /* do map */, screen->width, screen->height, format_swap); - } + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, need_map, screen->width, screen->height, format, modifiers, num_modifiers); + } + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, need_map, screen->width, screen->height, format_swap, modifiers, num_modifiers); } -#endif if (!ret) { - ret = gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format); + ret = gbm_create_front_bo(priv->gbm, !need_map, screen->width, screen->height, format, modifiers, num_modifiers); } if (!ret) { - ret = gbm_create_front_bo(priv->gbm, TRUE /* do map */, screen->width, screen->height, format_swap); + ret = gbm_create_front_bo(priv->gbm, !need_map, screen->width, screen->height, format_swap, modifiers, num_modifiers); } if (!ret) { int old_depth = screen->fb.depth; int old_bpp = screen->fb.bitsPerPixel; - if (screen->fb.depth > 30) { + + if (keep_depth) { + break; + } else if (screen->fb.depth > 30) { screen->fb.depth = 30; screen->fb.bitsPerPixel = 24; } else if (screen->fb.depth > 24) { @@ -304,7 +301,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; } - scrpriv->front = modesetting_open(priv, screen, FALSE /* need_map */); + scrpriv->front = modesetting_open(priv, screen, screen->dumb /* need_map */, FALSE /* keep_depth */); if (!scrpriv->front) { LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not create a front buffer\n", screen->card->mynum, screen->mynum); diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index e756e4f142e..0f11b790b17 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -42,8 +42,7 @@ typedef struct _msScrPriv { Bool blockHandler; Bool shadow; - Bool error; - Bool setPixmapBits; + Bool allow_modifier_strip; uint32_t num_render_modifiers; uint64_t *render_modifiers; @@ -88,7 +87,7 @@ Bool msUnmapFramebuffer(KdScreenInfo * screen); Bool msSetShadow(ScreenPtr pScreen); struct gbm_bo* -modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map); +modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map, Bool keep_depth); /* ms_damage.c */ @@ -140,7 +139,8 @@ int gbm_format_get_depth(uint32_t format); struct gbm_bo* -gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format); +gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format, + uint64_t *modifiers, int num_modifiers); void gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles); diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index bcf9a9520e0..784ec26a251 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -7,6 +7,8 @@ #include "modesetting.h" +#include + /* TODO: Stuff that should be in msutil */ typedef struct { @@ -121,7 +123,8 @@ gbm_bo_create_and_map_once(struct gbm_device *gbm, } static struct gbm_bo* -gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t width, uint32_t height, uint32_t format) +gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t width, uint32_t height, uint32_t format, + uint64_t *modifiers, int num_modifiers) { #if 0 uint32_t flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING | GBM_BO_USE_FRONT_RENDERING; @@ -131,6 +134,21 @@ gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t wi struct gbm_bo *bo = NULL; + /* Implicit modifiers are ok */ + Bool modifiers_ok = !num_modifiers; + + for (int i = 0; !modifiers_ok && i < num_modifiers; i++) { + switch (modifiers[i]) { + case DRM_FORMAT_MOD_LINEAR: + case DRM_FORMAT_MOD_INVALID: + modifiers_ok = TRUE; + } + } + + if (!modifiers_ok) { + return NULL; + } + #if 0 /* non-dumb buffers require unmap + map to flush writes, which is far slower than ShadowFB */ bo = gbm_bo_create_and_map_once(gbm, data, width, height, format, flags); if (!bo) { @@ -145,7 +163,8 @@ gbm_bo_create_and_map(struct gbm_device *gbm, gbm_user_data_t *data, uint32_t wi } static struct gbm_bo* -gbm_bo_create_tiled(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format) +gbm_bo_create_tiled(struct gbm_device *gbm, uint32_t width, uint32_t height, uint32_t format, + uint64_t *modifiers, int num_modifiers) { struct gbm_bo *bo = NULL; @@ -156,11 +175,17 @@ gbm_bo_create_tiled(struct gbm_device *gbm, uint32_t width, uint32_t height, uin uint32_t flags2 = GBM_BO_USE_SCANOUT; if (!bo) { - bo = gbm_bo_create(gbm, width, height, format, flags); + bo = gbm_bo_create_with_modifiers2(gbm, width, height, format, + modifiers, num_modifiers, flags); } if (!bo) { - bo = gbm_bo_create(gbm, width, height, format, flags2); + bo = gbm_bo_create_with_modifiers2(gbm, width, height, format, + modifiers, num_modifiers, flags2); + } + + if (num_modifiers && + !(num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) { } return bo; @@ -292,7 +317,8 @@ gbm_format_get_depth(uint32_t format) } struct gbm_bo* -gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format) +gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format, + uint64_t *modifiers, int num_modifiers) { struct gbm_bo *ret = NULL; gbm_user_data_t *data = NULL; @@ -302,8 +328,8 @@ gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_ goto fail; } - ret = do_map ? gbm_bo_create_and_map(gbm, data, width, height, format) : - gbm_bo_create_tiled(gbm, width, height, format); + ret = do_map ? gbm_bo_create_and_map(gbm, data, width, height, format, modifiers, num_modifiers) : + gbm_bo_create_tiled(gbm, width, height, format, modifiers, num_modifiers); if (!ret) { goto fail; } @@ -315,6 +341,11 @@ gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_ goto fail; } + if (!do_map && num_modifiers && + !(num_modifiers == 1 && modifiers[0] == DRM_FORMAT_MOD_INVALID)) { + data->used_modifiers = TRUE; + } + return ret; fail: diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 5ea363ec16d..2441bfb5d06 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -13,73 +13,118 @@ #include static Bool -msGlamorMapFront(ScreenPtr pScreen); - -Bool -msGlamorCreateRes(ScreenPtr pScreen) +msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; msScrPriv *scrpriv = screen->driver; - PixmapPtr rootPixmap; - - struct gbm_format_name_desc desc = {0}; - uint32_t format; - uint64_t modifier; - const char *format_name; + KdFrameBuffer saved_framebuffer = screen->fb; - rootPixmap = (*pScreen->GetScreenPixmap)(pScreen); + /* TODO: query glamor */ + MsScreenConf *config = screen->closure; + Bool is_gles = config->glamor_info.force_es; - if (!gbm_bo_get_map(scrpriv->front)) { - Bool used_modifiers = gbm_bo_get_used_modifiers(scrpriv->front); - if (!screen->dumb && - glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, scrpriv->front, used_modifiers)) { - LogMessage(X_INFO, "Xmodesetting(%d): Using a tiled front buffer\n", pScreen->myNum); - } else { - if (!msGlamorMapFront(pScreen)) { - LogMessage(X_ERROR, "Xmodesetting(%d): Could not map the front buffer\n", - pScreen->myNum); - return FALSE; - } + struct gbm_bo *old_front; + struct gbm_bo *new_front = NULL; - LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); + if (strip_modifiers) { + if (!need_map && !scrpriv->allow_modifier_strip) { + return FALSE; } - } else { - LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); + screen->driver = NULL; } - format = gbm_bo_get_format(scrpriv->front); - modifier = gbm_bo_get_modifier(scrpriv->front); - format_name = gbm_format_get_name(format, &desc); - LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d, format: %s, modifier: 0x%lx\n", - pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel, format_name, modifier); + old_front = scrpriv->front; + new_front = modesetting_open(priv, screen, need_map, TRUE /* keep_depth */); + screen->driver = scrpriv; + if (!new_front) { + return FALSE; + } + gbm_bo_set_screen_fb_info(new_front, screen, is_gles); + if (memcmp(&saved_framebuffer, &screen->fb, sizeof(screen->fb))) { + /* Visual masks changed, the bo is unusable */ + /* XXX We could still use this if we had a way to change visual masks this late */ + screen->fb = saved_framebuffer; + gbm_bo_destroy(new_front); + LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use a new front with different visual masks\n", pScreen->myNum); + return FALSE; + } + + if (!msSetScreenBo(pScreen, new_front, TRUE /* flip */)) { + gbm_bo_destroy(new_front); + LogMessage(X_ERROR, "Xmodesetting(%d): Could not flip to the new front bo\n", pScreen->myNum); + return FALSE; + } + + if (!gbm_bo_get_map(new_front)) { + PixmapPtr rootPixmap = (*pScreen->GetScreenPixmap)(pScreen); + Bool used_modifiers = gbm_bo_get_used_modifiers(new_front); + + if (!glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, new_front, used_modifiers)) { + /* Put the old front back, destroy the new front */ + msSetScreenBo(pScreen, old_front, FALSE /* flip */); + LogMessage(X_ERROR, "Xmodesetting(%d): Could not texture the front bo\n", pScreen->myNum); + return FALSE; + } + } + + gbm_bo_destroy(old_front); return TRUE; } static Bool -msGlamorMapFront(ScreenPtr pScreen) +msGlamorTileFront(ScreenPtr pScreen, Bool map_fallback) +{ + if (msGlamorTryNewFront(pScreen, FALSE /* strip_modifiers */, FALSE /* need_map */) || + msGlamorTryNewFront(pScreen, TRUE /* strip_modifiers */, FALSE /* need_map */)) { + return TRUE; + } + + LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use a textured gbm front, using a cpu-mapped front buffer\n", pScreen->myNum); + + if (map_fallback) { + if (!msGlamorTryNewFront(pScreen, FALSE /* strip_modifiers */, TRUE /* need_map */)) { + msGlamorTryNewFront(pScreen, TRUE /* strip_modifiers */, TRUE /* need_map */); + } + } + return FALSE; +} + +Bool +msGlamorCreateRes(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - msPriv *priv = screen->card->driver; - struct gbm_bo *new_front = NULL; + msScrPriv *scrpriv = screen->driver; - LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use tiled gbm front, trying to use a mapped front bo\n", pScreen->myNum); + struct gbm_format_name_desc desc = {0}; + uint32_t format; + uint64_t modifier; + const char *format_name; - new_front = modesetting_open(priv, screen, TRUE /* need_map */); - if (!new_front || - !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { - goto bail; + if (!screen->dumb) { + Bool map_fallback = !gbm_bo_get_map(scrpriv->front); + if (!msGlamorTileFront(pScreen, map_fallback) && + !gbm_bo_get_map(scrpriv->front)) { + LogMessage(X_ERROR, "Xmodesetting(%d): Could not create a usable front buffer\n", pScreen->myNum); + return FALSE; + } } - return TRUE; - -bail: - if (new_front) { - gbm_bo_destroy(new_front); + if (gbm_bo_get_map(scrpriv->front)) { + LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); + } else { + LogMessage(X_INFO, "Xmodesetting(%d): Using a textured front buffer\n", pScreen->myNum); } - return FALSE; + + format = gbm_bo_get_format(scrpriv->front); + modifier = gbm_bo_get_modifier(scrpriv->front); + format_name = gbm_format_get_name(format, &desc); + LogMessage(X_INFO, "Xmodesetting(%d): Front buffer depth: %d, bpp: %d, format: %s, modifier: 0x%lx\n", + pScreen->myNum, screen->fb.depth, screen->fb.bitsPerPixel, format_name, modifier); + return TRUE; } Bool @@ -91,6 +136,7 @@ msGlamorInit(ScreenPtr pScreen) msPriv *priv = screen->card->driver; msScrPriv *scrpriv = screen->driver; uint32_t format; + int caps = GLAMOR_EGL_CAP_NONE; if (!config->glamor_info.dri_path) { config->glamor_info.dri_fd = dup(gbm_device_get_fd(priv->gbm)); @@ -101,10 +147,13 @@ msGlamorInit(ScreenPtr pScreen) } } - if (!KdGlamorInit(pScreen, &config->glamor_info, NULL)) { + if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { return FALSE; } + /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/work_items/14475#note_3659774 */ + scrpriv->allow_modifier_strip = !!(caps & GLAMOR_EGL_CAP_TEXTURE_GBM_BO); + /* * TODO: Don't assume all formats support the same modifiers * @@ -118,6 +167,9 @@ msGlamorInit(ScreenPtr pScreen) scrpriv->render_modifiers = NULL; } + /* TODO: Query scanout modifiers in CardInit, + * intersect with the render modifiers, and cache them + */ if (scrpriv->num_render_modifiers == 1 && scrpriv->render_modifiers[0] == DRM_FORMAT_MOD_INVALID) { free(scrpriv->render_modifiers); diff --git a/hw/kdrive/modesetting/ms_randr.c b/hw/kdrive/modesetting/ms_randr.c index be7133f2162..7d716119d23 100644 --- a/hw/kdrive/modesetting/ms_randr.c +++ b/hw/kdrive/modesetting/ms_randr.c @@ -20,6 +20,12 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) drmModeModeInfo *old_mode; int old_width, old_height, old_rate; + /* TODO: Query scanout modifiers in CardInit, + * intersect with render modifiers queried in msGlamorInit + */ + uint64_t *modifiers = scrpriv->render_modifiers; + int num_modifiers = scrpriv->num_render_modifiers; + old_mode = scrpriv->mode; old_width = screen->width; @@ -41,7 +47,8 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) height != screen->height) { uint32_t format = gbm_bo_get_format(scrpriv->front); Bool do_map = !!gbm_bo_get_map(scrpriv->front); - new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format); + new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format, + modifiers, num_modifiers); if (!new_front || !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { goto bail; From 5a01e0579c6057beb27025638bd3cde03a806d46 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 25 Sep 2026 02:26:37 +0300 Subject: [PATCH 39/47] kdrive/modesetting: Filter multi-plane modifiers Same reason as xf86 modesetting Signed-off-by: stefan11111 --- hw/kdrive/modesetting/ms_glamor.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 2441bfb5d06..12034805cbd 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -137,6 +137,7 @@ msGlamorInit(ScreenPtr pScreen) msScrPriv *scrpriv = screen->driver; uint32_t format; int caps = GLAMOR_EGL_CAP_NONE; + int write_pos = 0; if (!config->glamor_info.dri_path) { config->glamor_info.dri_fd = dup(gbm_device_get_fd(priv->gbm)); @@ -170,10 +171,30 @@ msGlamorInit(ScreenPtr pScreen) /* TODO: Query scanout modifiers in CardInit, * intersect with the render modifiers, and cache them */ - if (scrpriv->num_render_modifiers == 1 && - scrpriv->render_modifiers[0] == DRM_FORMAT_MOD_INVALID) { + + /* Don't choose multi-plane formats for our screen pixmap. + * These will get used with frontbuffer rendering, which will + * lead to worse-than-tearing with multi-plane formats, as the + * primary and auxiliary planes go out of sync. */ + for (int i = 0; i < scrpriv->num_render_modifiers; i++) { + if (gbm_device_get_format_modifier_plane_count(priv->gbm, format, scrpriv->render_modifiers[i]) > 1) { + continue; + } + scrpriv->render_modifiers[write_pos++] = scrpriv->render_modifiers[i]; + } + + if (write_pos == 0 || + (scrpriv->num_render_modifiers == 1 && + scrpriv->render_modifiers[0] == DRM_FORMAT_MOD_INVALID)) { free(scrpriv->render_modifiers); + scrpriv->render_modifiers = NULL; scrpriv->num_render_modifiers = 0; + } else if (write_pos < scrpriv->num_render_modifiers) { + void* tmp = realloc(scrpriv->render_modifiers, + write_pos * sizeof(scrpriv->render_modifiers)); + if (tmp) { + scrpriv->render_modifiers = tmp; + } } return TRUE; From bbc32a016fcfc5d06de56b6ff4a51f592d874fa9 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Fri, 25 Sep 2026 19:50:04 +0300 Subject: [PATCH 40/47] kdrive/modesetting: Get RandR working again Some issues accumulated when tiled buffers and modifiers were implemented Rotations don't yet work with tiled buffers Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 8 ++++++-- hw/kdrive/modesetting/ms_glamor.c | 19 ++---------------- hw/kdrive/modesetting/ms_randr.c | 17 +++++++++++++--- hw/kdrive/modesetting/ms_util.c | 31 ++++++++++++++++++++++++++++- 4 files changed, 52 insertions(+), 23 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index dc88a5bdcf6..a60144b9eb1 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -301,7 +301,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; } - scrpriv->front = modesetting_open(priv, screen, screen->dumb /* need_map */, FALSE /* keep_depth */); + scrpriv->front = modesetting_open(priv, screen, screen->dumb || screen->randr != RR_Rotate_0 /* need_map */, FALSE /* keep_depth */); if (!scrpriv->front) { LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not create a front buffer\n", screen->card->mynum, screen->mynum); @@ -380,6 +380,10 @@ msMapFramebuffer(KdScreenInfo * screen) MsScreenConf *config = screen->closure; if (!gbm_bo_get_map(scrpriv->front)) { + /* TODO: Do something useful */ + if (scrpriv->randr != RR_Rotate_0) { + return FALSE; + } scrpriv->shadow = FALSE; } else if (config->shadow >= 0) { scrpriv->shadow = config->shadow; @@ -433,7 +437,7 @@ msSetShadow(ScreenPtr pScreen) if (screen->fb.bitsPerPixel == 24) update = shadowUpdate32to24; - else if (scrpriv->randr) + else if (scrpriv->randr != RR_Rotate_0) update = shadowUpdateRotatePacked; else update = shadowUpdatePacked; diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 12034805cbd..67affb887b1 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -25,7 +25,6 @@ msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) MsScreenConf *config = screen->closure; Bool is_gles = config->glamor_info.force_es; - struct gbm_bo *old_front; struct gbm_bo *new_front = NULL; if (strip_modifiers) { @@ -35,7 +34,6 @@ msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) screen->driver = NULL; } - old_front = scrpriv->front; new_front = modesetting_open(priv, screen, need_map, TRUE /* keep_depth */); screen->driver = scrpriv; if (!new_front) { @@ -52,25 +50,12 @@ msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) return FALSE; } - if (!msSetScreenBo(pScreen, new_front, TRUE /* flip */)) { + if (!msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { gbm_bo_destroy(new_front); - LogMessage(X_ERROR, "Xmodesetting(%d): Could not flip to the new front bo\n", pScreen->myNum); + LogMessage(X_ERROR, "Xmodesetting(%d): Could not swap to the new front bo\n", pScreen->myNum); return FALSE; } - if (!gbm_bo_get_map(new_front)) { - PixmapPtr rootPixmap = (*pScreen->GetScreenPixmap)(pScreen); - Bool used_modifiers = gbm_bo_get_used_modifiers(new_front); - - if (!glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, new_front, used_modifiers)) { - /* Put the old front back, destroy the new front */ - msSetScreenBo(pScreen, old_front, FALSE /* flip */); - LogMessage(X_ERROR, "Xmodesetting(%d): Could not texture the front bo\n", pScreen->myNum); - return FALSE; - } - } - - gbm_bo_destroy(old_front); return TRUE; } diff --git a/hw/kdrive/modesetting/ms_randr.c b/hw/kdrive/modesetting/ms_randr.c index 7d716119d23..50fdb8ea2a3 100644 --- a/hw/kdrive/modesetting/ms_randr.c +++ b/hw/kdrive/modesetting/ms_randr.c @@ -43,16 +43,27 @@ msSetMode(ScreenPtr pScreen, int width, int height, int rate) screen->rate = rate; /* Create a new front with the new sizes */ - if (width != screen->width || - height != screen->height) { + if (width != old_width || + height != old_height) { uint32_t format = gbm_bo_get_format(scrpriv->front); Bool do_map = !!gbm_bo_get_map(scrpriv->front); + uint64_t modifier = gbm_bo_get_modifier(scrpriv->front); + + /* Try the current modifier first */ new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format, - modifiers, num_modifiers); + &modifier, 1); + if (!new_front) { + new_front = gbm_create_front_bo(priv->gbm, do_map, width, height, format, + modifiers, num_modifiers); + } if (!new_front || !msSetScreenBo(pScreen, new_front, FALSE /* flip */)) { goto bail; } + } else { + if (!msSetScreenBo(pScreen, scrpriv->front, TRUE /* flip */)) { + goto bail; + } } return TRUE; diff --git a/hw/kdrive/modesetting/ms_util.c b/hw/kdrive/modesetting/ms_util.c index 03180b141e6..31e4e9d46ba 100644 --- a/hw/kdrive/modesetting/ms_util.c +++ b/hw/kdrive/modesetting/ms_util.c @@ -7,6 +7,10 @@ #include "modesetting.h" +#ifdef GLAMOR +#include "glamor.h" +#endif + /* XXX This really belongs in os/, like the version from glamor_egl */ Bool msFdMatch(int fd1, int fd2) @@ -96,6 +100,9 @@ msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) struct gbm_bo *old_front; Bool wasEnabled = pScreenPriv->enabled; msScrPriv oldscr; + PixmapPtr rootPixmap; + + rootPixmap = (*pScreen->GetScreenPixmap)(pScreen); if (wasEnabled) { KdDisableScreen(pScreen); @@ -124,7 +131,7 @@ msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) /* * Set frame buffer mapping */ - (*pScreen->ModifyPixmapHeader) ((*pScreen->GetScreenPixmap)(pScreen), + (*pScreen->ModifyPixmapHeader) (rootPixmap, pScreen->width, pScreen->height, screen->fb.depth, @@ -136,6 +143,18 @@ msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) KdSetSubpixelOrder(pScreen, scrpriv->randr); + /* Texture the front if needed */ + if (!flip && !gbm_bo_get_map(bo)) { +#ifdef GLAMOR + Bool used_modifiers = gbm_bo_get_used_modifiers(bo); + if (screen->dumb || + !glamor_egl_create_textured_pixmap_from_gbm_bo(rootPixmap, bo, used_modifiers)) +#endif + { + goto bail; + } + } + /* Scan out the new bo on the screen's crtc */ if (wasEnabled) { KdEnableScreen(pScreen); @@ -153,6 +172,16 @@ msSetScreenBo(ScreenPtr pScreen, struct gbm_bo *bo, Bool flip) msMapFramebuffer(screen); msSetScreenSizes(screen->pScreen); + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) (rootPixmap, + pScreen->width, + pScreen->height, + screen->fb.depth, + screen->fb.bitsPerPixel, + screen->fb.byteStride, + screen->fb.frameBuffer); if (wasEnabled) { KdEnableScreen(pScreen); } From b2dddc972cc05637d75855b27959e694f96f7b97 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 01:10:21 +0300 Subject: [PATCH 41/47] kdrive/modesetting: Fix 24 bpp front Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 12 ++++++++++-- hw/kdrive/modesetting/modesetting.h | 2 ++ hw/kdrive/modesetting/ms_gbm.c | 7 +++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index a60144b9eb1..862dadf17d4 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -115,7 +115,7 @@ modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map, Bool keep_de break; } else if (screen->fb.depth > 30) { screen->fb.depth = 30; - screen->fb.bitsPerPixel = 24; + screen->fb.bitsPerPixel = 32; } else if (screen->fb.depth > 24) { screen->fb.depth = 24; screen->fb.bitsPerPixel = 32; @@ -314,6 +314,12 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) gbm_bo_set_screen_fb_info(scrpriv->front, screen, config->glamor_info.force_es); + /* Make fbSetupScreen happy */ + if (screen->fb.bitsPerPixel == 24) { + screen->fb.bitsPerPixel = 32; + scrpriv->is_24bpp = TRUE; + } + scrpriv->randr = screen->randr; if (!msMapFramebuffer(screen)) { goto fail; @@ -385,6 +391,8 @@ msMapFramebuffer(KdScreenInfo * screen) return FALSE; } scrpriv->shadow = FALSE; + } else if (scrpriv->is_24bpp) { + scrpriv->shadow = TRUE; } else if (config->shadow >= 0) { scrpriv->shadow = config->shadow; } else if (scrpriv->randr != RR_Rotate_0) { @@ -435,7 +443,7 @@ msSetShadow(ScreenPtr pScreen) window = msWindowLinear; update = 0; - if (screen->fb.bitsPerPixel == 24) + if (scrpriv->is_24bpp == 24) update = shadowUpdate32to24; else if (scrpriv->randr != RR_Rotate_0) update = shadowUpdateRotatePacked; diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 0f11b790b17..48a0702fd3d 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -42,6 +42,8 @@ typedef struct _msScrPriv { Bool blockHandler; Bool shadow; + Bool is_24bpp; + Bool allow_modifier_strip; uint32_t num_render_modifiers; diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index 784ec26a251..0fabcc32490 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -174,6 +174,13 @@ gbm_bo_create_tiled(struct gbm_device *gbm, uint32_t width, uint32_t height, uin /* Used by nvidia */ uint32_t flags2 = GBM_BO_USE_SCANOUT; + /* We can't use a tiled buffer for these formats */ + switch (format) { + case GBM_FORMAT_RGB888: + case GBM_FORMAT_BGR888: + return NULL; + } + if (!bo) { bo = gbm_bo_create_with_modifiers2(gbm, width, height, format, modifiers, num_modifiers, flags); From 5538927f38d93070e2508a5b961982cab8d83298 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 12:26:03 +0300 Subject: [PATCH 42/47] kdrive/modesetting: Simplify `modesetting_open` Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 96 ++++++----------------------- hw/kdrive/modesetting/modesetting.h | 5 +- hw/kdrive/modesetting/ms_gbm.c | 25 ++++++++ hw/kdrive/modesetting/ms_glamor.c | 3 +- 4 files changed, 49 insertions(+), 80 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 862dadf17d4..6dff6dd86f2 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -15,96 +15,38 @@ #endif struct gbm_bo* -modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map, Bool keep_depth) +modesetting_open(KdScreenInfo *screen, Bool need_map, Bool keep_depth) { struct gbm_bo *ret = NULL; - uint32_t format, format_swap; - MsScreenConf *config = screen->closure; - msScrPriv *scrpriv = screen->driver; - /* TODO: Query scanout modifiers in CardInit, - * intersect with render modifiers queried in msGlamorInit - */ - uint64_t *modifiers = scrpriv ? scrpriv->render_modifiers : NULL; - int num_modifiers = scrpriv ? scrpriv->num_render_modifiers : 0; - - /* XXX depth 30 needs more care because of the visual mask swap */ - Bool careful = screen->fb.depth == 30 && !config->glamor_info.force_es; #ifdef GLAMOR + msScrPriv *scrpriv = screen->driver; + MsScreenConf *config = screen->closure; + Rotation randr = scrpriv ? scrpriv->randr : screen->randr; + if (screen->dumb) { need_map = TRUE; - } else if (careful && config->glamor_info.dri_path) { - /* - * If the render card is different fron the scanout card, assume the modifier sets are disjoint. - * If the cards are the same, and it is from nvidia, and the gbm backend is mesa or dumb, - * assume that buffers are not renderable. - */ - int dri_fd = open(config->glamor_info.dri_path, O_RDWR); - if (!msFdMatch(gbm_device_get_fd(priv->gbm), dri_fd)) { - need_map = TRUE; - } - - if (dri_fd >= 0) { - close(dri_fd); - } - } else if (careful) { - drmVersionPtr version; - Bool is_nvidia = TRUE; - Bool backend_is_mesa = FALSE; - Bool linear_only = FALSE; - const char *backend_name; - - version = drmGetVersion(gbm_device_get_fd(priv->gbm)); - if (version) { - is_nvidia = !version->name || !strcmp(version->name, "nvidia-drm"); - drmFreeVersion(version); - } - backend_name = gbm_device_get_backend_name(priv->gbm); - if (!backend_name) { - linear_only = TRUE; - } else if (!strcmp(backend_name, "dumb")) { - linear_only = TRUE; - } else if (!strcmp(backend_name, "drm")) { - backend_is_mesa = TRUE; - } - - /** - * Nvidia's egl libraries do not allow creating GL_TEXTURE_2D textures from linear buffers. + } else if (randr != RR_Rotate_0) { + need_map = TRUE; + } else if (screen->fb.depth == 30 && config->glamor_info.force_es) { + /* TODO: depth 30 needs more care because of the visual mask swap + * Is it worth it to actually do this? + * if yes, check the commit history for how to do this * - * See: https://gitlab.freedesktop.org/xorg/xserver/-/work_items/1444 + * For now, just assume that we can texture it + * It makes things a lot simpler */ - if (is_nvidia) { - if (linear_only || backend_is_mesa) { - need_map = TRUE; - } - } } -#else - need_map = TRUE; #endif while (!ret) { - format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, FALSE /* rb_swap */); - format_swap = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, TRUE /* rb_swap */); - - if (config->format_swap) { - uint32_t tmp = format; - format = format_swap; - format_swap = tmp; - } - - if (!ret) { - ret = gbm_create_front_bo(priv->gbm, need_map, screen->width, screen->height, format, modifiers, num_modifiers); - } - if (!ret) { - ret = gbm_create_front_bo(priv->gbm, need_map, screen->width, screen->height, format_swap, modifiers, num_modifiers); - } - - if (!ret) { - ret = gbm_create_front_bo(priv->gbm, !need_map, screen->width, screen->height, format, modifiers, num_modifiers); +#ifdef GLAMOR + if (!need_map) { + ret = gbm_create_front_for_screen(screen, FALSE /* do_map */, config->format_swap); } +#endif if (!ret) { - ret = gbm_create_front_bo(priv->gbm, !need_map, screen->width, screen->height, format_swap, modifiers, num_modifiers); + ret = gbm_create_front_for_screen(screen, TRUE /* do_map */, config->format_swap); } if (!ret) { @@ -301,7 +243,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; } - scrpriv->front = modesetting_open(priv, screen, screen->dumb || screen->randr != RR_Rotate_0 /* need_map */, FALSE /* keep_depth */); + scrpriv->front = modesetting_open(screen, FALSE /* need_map */, FALSE /* keep_depth */); if (!scrpriv->front) { LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not create a front buffer\n", screen->card->mynum, screen->mynum); diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 48a0702fd3d..531dbbfded4 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -89,7 +89,7 @@ Bool msUnmapFramebuffer(KdScreenInfo * screen); Bool msSetShadow(ScreenPtr pScreen); struct gbm_bo* -modesetting_open(msPriv *priv, KdScreenInfo *screen, Bool need_map, Bool keep_depth); +modesetting_open(KdScreenInfo *screen, Bool need_map, Bool keep_depth); /* ms_damage.c */ @@ -144,6 +144,9 @@ struct gbm_bo* gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format, uint64_t *modifiers, int num_modifiers); +struct gbm_bo* +gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap); + void gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles); diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index 0fabcc32490..69dc4a3ebd6 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -369,6 +369,31 @@ gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_ return NULL; } +struct gbm_bo* +gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap) +{ + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + uint32_t format = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, do_swap /* rb_swap */); + uint32_t format_swap = gbm_front_format_for_depth(screen->fb.depth, screen->fb.bitsPerPixel, !do_swap /* rb_swap */); + struct gbm_bo *ret = NULL; + + /* TODO: Query scanout modifiers in CardInit, + * intersect with render modifiers queried in msGlamorInit + */ + uint64_t *modifiers = scrpriv ? scrpriv->render_modifiers : NULL; + int num_modifiers = scrpriv ? scrpriv->num_render_modifiers : 0; + + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, do_map, screen->width, screen->height, format, modifiers, num_modifiers); + } + if (!ret) { + ret = gbm_create_front_bo(priv->gbm, do_map, screen->width, screen->height, format_swap, modifiers, num_modifiers); + } + + return ret; +} + void gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles) { diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 67affb887b1..87a6729c08f 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -17,7 +17,6 @@ msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - msPriv *priv = screen->card->driver; msScrPriv *scrpriv = screen->driver; KdFrameBuffer saved_framebuffer = screen->fb; @@ -34,7 +33,7 @@ msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) screen->driver = NULL; } - new_front = modesetting_open(priv, screen, need_map, TRUE /* keep_depth */); + new_front = modesetting_open(screen, need_map, TRUE /* keep_depth */); screen->driver = scrpriv; if (!new_front) { return FALSE; From ccec4ac6a4828221d8453681b2a54a7c3906adbe Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 13:04:28 +0300 Subject: [PATCH 43/47] kdrive/modesetting: Create a mapped front first, have glamor only tile it Simplifies things a bit Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 7 +++- hw/kdrive/modesetting/modesetting.h | 4 +- hw/kdrive/modesetting/ms_gbm.c | 4 +- hw/kdrive/modesetting/ms_glamor.c | 59 ++++------------------------- 4 files changed, 16 insertions(+), 58 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 6dff6dd86f2..9e2fe218833 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -243,7 +243,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = scrpriv->mode ? scrpriv->mode->vdisplay : 1080; } - scrpriv->front = modesetting_open(screen, FALSE /* need_map */, FALSE /* keep_depth */); + scrpriv->front = modesetting_open(screen, TRUE /* need_map */, FALSE /* keep_depth */); if (!scrpriv->front) { LogMessage(X_ERROR, "Xmodesetting(card %d, screen %d): Could not create a front buffer\n", screen->card->mynum, screen->mynum); @@ -254,7 +254,10 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = gbm_bo_get_height(scrpriv->front); screen->rate = scrpriv->mode ? scrpriv->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ - gbm_bo_set_screen_fb_info(scrpriv->front, screen, config->glamor_info.force_es); + /* Set the visual masks assuming we will be able to texture this bo + * This allows us to create a mapped front here, and have glamor texture it if it can + */ + gbm_bo_set_screen_fb_info(scrpriv->front, screen, config->glamor_info.force_es, TRUE /* gl_masks */); /* Make fbSetupScreen happy */ if (screen->fb.bitsPerPixel == 24) { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 531dbbfded4..6a44d108b6c 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -44,8 +44,6 @@ typedef struct _msScrPriv { Bool is_24bpp; - Bool allow_modifier_strip; - uint32_t num_render_modifiers; uint64_t *render_modifiers; } msScrPriv; @@ -148,7 +146,7 @@ struct gbm_bo* gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap); void -gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles); +gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles, Bool gl_masks); /* ms_query.c */ diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index 69dc4a3ebd6..c34ad554698 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -395,7 +395,7 @@ gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap) } void -gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles) +gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles, Bool gl_masks) { uint32_t format = gbm_bo_get_format(bo); Bool rb_swap = FALSE; @@ -463,7 +463,7 @@ gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles) } /* XXX Tiled buffers don't need r-b swap, unless it's depth 30 on gles */ - if (!gbm_bo_get_map(bo)) { + if (gl_masks || !gbm_bo_get_map(bo)) { if (screen->fb.depth != 30 || !is_gles) { rb_swap = FALSE; } diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 87a6729c08f..3050cf4c3b5 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -13,39 +13,21 @@ #include static Bool -msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) +msGlamorTileFront(ScreenPtr pScreen) { KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; - msScrPriv *scrpriv = screen->driver; - KdFrameBuffer saved_framebuffer = screen->fb; - - /* TODO: query glamor */ - MsScreenConf *config = screen->closure; - Bool is_gles = config->glamor_info.force_es; struct gbm_bo *new_front = NULL; - if (strip_modifiers) { - if (!need_map && !scrpriv->allow_modifier_strip) { - return FALSE; - } - screen->driver = NULL; - } - - new_front = modesetting_open(screen, need_map, TRUE /* keep_depth */); - screen->driver = scrpriv; + new_front = modesetting_open(screen, FALSE /* need_map */, TRUE /* keep_depth */); if (!new_front) { return FALSE; } - gbm_bo_set_screen_fb_info(new_front, screen, is_gles); - if (memcmp(&saved_framebuffer, &screen->fb, sizeof(screen->fb))) { - /* Visual masks changed, the bo is unusable */ - /* XXX We could still use this if we had a way to change visual masks this late */ - screen->fb = saved_framebuffer; + /* Maybe we could switch to this bo, but why? */ + if (gbm_bo_get_map(new_front)) { gbm_bo_destroy(new_front); - LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use a new front with different visual masks\n", pScreen->myNum); return FALSE; } @@ -58,24 +40,6 @@ msGlamorTryNewFront(ScreenPtr pScreen, Bool strip_modifiers, Bool need_map) return TRUE; } -static Bool -msGlamorTileFront(ScreenPtr pScreen, Bool map_fallback) -{ - if (msGlamorTryNewFront(pScreen, FALSE /* strip_modifiers */, FALSE /* need_map */) || - msGlamorTryNewFront(pScreen, TRUE /* strip_modifiers */, FALSE /* need_map */)) { - return TRUE; - } - - LogMessage(X_ERROR, "Xmodesetting(%d): Cannot use a textured gbm front, using a cpu-mapped front buffer\n", pScreen->myNum); - - if (map_fallback) { - if (!msGlamorTryNewFront(pScreen, FALSE /* strip_modifiers */, TRUE /* need_map */)) { - msGlamorTryNewFront(pScreen, TRUE /* strip_modifiers */, TRUE /* need_map */); - } - } - return FALSE; -} - Bool msGlamorCreateRes(ScreenPtr pScreen) { @@ -89,18 +53,15 @@ msGlamorCreateRes(ScreenPtr pScreen) const char *format_name; if (!screen->dumb) { - Bool map_fallback = !gbm_bo_get_map(scrpriv->front); - if (!msGlamorTileFront(pScreen, map_fallback) && - !gbm_bo_get_map(scrpriv->front)) { - LogMessage(X_ERROR, "Xmodesetting(%d): Could not create a usable front buffer\n", pScreen->myNum); - return FALSE; + if (!msGlamorTileFront(pScreen)) { + LogMessage(X_INFO, "Xmodesetting(%d): Could not create a usable tiled front buffer\n", pScreen->myNum); } } if (gbm_bo_get_map(scrpriv->front)) { LogMessage(X_INFO, "Xmodesetting(%d): Using a cpu mapped front buffer\n", pScreen->myNum); } else { - LogMessage(X_INFO, "Xmodesetting(%d): Using a textured front buffer\n", pScreen->myNum); + LogMessage(X_INFO, "Xmodesetting(%d): Using a tiled front buffer\n", pScreen->myNum); } format = gbm_bo_get_format(scrpriv->front); @@ -120,7 +81,6 @@ msGlamorInit(ScreenPtr pScreen) msPriv *priv = screen->card->driver; msScrPriv *scrpriv = screen->driver; uint32_t format; - int caps = GLAMOR_EGL_CAP_NONE; int write_pos = 0; if (!config->glamor_info.dri_path) { @@ -132,13 +92,10 @@ msGlamorInit(ScreenPtr pScreen) } } - if (!KdGlamorInit(pScreen, &config->glamor_info, &caps)) { + if (!KdGlamorInit(pScreen, &config->glamor_info, NULL)) { return FALSE; } - /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/work_items/14475#note_3659774 */ - scrpriv->allow_modifier_strip = !!(caps & GLAMOR_EGL_CAP_TEXTURE_GBM_BO); - /* * TODO: Don't assume all formats support the same modifiers * From fa06fc272ca2812f3bcf0c73b5b1f5ded8a0a5c6 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 13:56:33 +0300 Subject: [PATCH 44/47] kdrive/modesetting: Fix visual masks in `msGlamorTileFront` This makes things way simpler Signed-off-by: stefan11111 --- hw/kdrive/modesetting/modesetting.c | 14 +------------- hw/kdrive/modesetting/modesetting.h | 2 +- hw/kdrive/modesetting/ms_gbm.c | 10 +++++++--- hw/kdrive/modesetting/ms_glamor.c | 28 ++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 17 deletions(-) diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 9e2fe218833..637faa514a7 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -28,14 +28,6 @@ modesetting_open(KdScreenInfo *screen, Bool need_map, Bool keep_depth) need_map = TRUE; } else if (randr != RR_Rotate_0) { need_map = TRUE; - } else if (screen->fb.depth == 30 && config->glamor_info.force_es) { - /* TODO: depth 30 needs more care because of the visual mask swap - * Is it worth it to actually do this? - * if yes, check the commit history for how to do this - * - * For now, just assume that we can texture it - * It makes things a lot simpler - */ } #endif @@ -209,7 +201,6 @@ modesetting_claim_connector_crtc(msPriv *priv, uint32_t conn, int crtc) static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) { - MsScreenConf *config = screen->closure; msPriv *priv = screen->card->driver; int fd = gbm_device_get_fd(priv->gbm); @@ -254,10 +245,7 @@ msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) screen->height = gbm_bo_get_height(scrpriv->front); screen->rate = scrpriv->mode ? scrpriv->mode->vrefresh : 0; /* XXX 0 means accept any rate on msEnable */ - /* Set the visual masks assuming we will be able to texture this bo - * This allows us to create a mapped front here, and have glamor texture it if it can - */ - gbm_bo_set_screen_fb_info(scrpriv->front, screen, config->glamor_info.force_es, TRUE /* gl_masks */); + gbm_bo_set_screen_fb_info(scrpriv->front, screen, FALSE /* is_gles */); /* Make fbSetupScreen happy */ if (screen->fb.bitsPerPixel == 24) { diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 6a44d108b6c..275f7bfac69 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -146,7 +146,7 @@ struct gbm_bo* gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap); void -gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles, Bool gl_masks); +gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles); /* ms_query.c */ diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index c34ad554698..8bd2304ae96 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -395,7 +395,7 @@ gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap) } void -gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles, Bool gl_masks) +gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles) { uint32_t format = gbm_bo_get_format(bo); Bool rb_swap = FALSE; @@ -462,8 +462,12 @@ gbm_bo_set_screen_fb_info(struct gbm_bo *bo, KdScreenInfo *screen, Bool is_gles, break; } - /* XXX Tiled buffers don't need r-b swap, unless it's depth 30 on gles */ - if (gl_masks || !gbm_bo_get_map(bo)) { + /* XXX Tiled buffers don't need r-b swap, unless it's depth 30 on gles + * + * This is because glamor_setup_formats tells glamor to expect pixels + * in rgb format for all depth, except depth 30 on gles + */ + if (!gbm_bo_get_map(bo)) { if (screen->fb.depth != 30 || !is_gles) { rb_swap = FALSE; } diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 3050cf4c3b5..07c6ba1730b 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -18,8 +18,17 @@ msGlamorTileFront(ScreenPtr pScreen) KdScreenPriv(pScreen); KdScreenInfo *screen = pScreenPriv->screen; + KdFrameBuffer saved_framebuffer = screen->fb; + + /* TODO: query glamor */ + MsScreenConf *config = screen->closure; + Bool is_gles = config->glamor_info.force_es; + struct gbm_bo *new_front = NULL; + /* By design, kdrive depth and bpp can't change between initAccel and finiAccel + * https://www.x.org/Development/Documentation/KdriveDrivers/ + */ new_front = modesetting_open(screen, FALSE /* need_map */, TRUE /* keep_depth */); if (!new_front) { return FALSE; @@ -37,6 +46,25 @@ msGlamorTileFront(ScreenPtr pScreen) return FALSE; } + /* Update visual masks if needed */ + gbm_bo_set_screen_fb_info(new_front, screen, is_gles); + if (memcmp(&saved_framebuffer, &screen->fb, sizeof(screen->fb))) { + /* TODO: Make this generic + * For now, the only thing that can happen is r-b masks need swapping + */ + + for (int i = 0; i < pScreen->numVisuals; i++) { + VisualPtr pVisual = &pScreen->visuals[i]; + if (pVisual->redMask == screen->fb.blueMask && + pVisual->blueMask == screen->fb.redMask) { + int off = pVisual->offsetRed; + pVisual->offsetRed = pVisual->offsetBlue; + pVisual->offsetBlue = off; + pVisual->redMask = screen->fb.redMask; + pVisual->blueMask = screen->fb.blueMask; + } + } + } return TRUE; } From f185ade4e6e37359894801e079cf8892cd111c38 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 14:08:31 +0300 Subject: [PATCH 45/47] kdrive: Set bitsPerRGB to 10 for depth 30 visuals Leave smaller depth alone, the bitsPerRGB value gets reported correctly for them Signed-off-by: stefan11111 --- hw/kdrive/src/kdrive.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c index 6772e2857e0..b242196c68e 100644 --- a/hw/kdrive/src/kdrive.c +++ b/hw/kdrive/src/kdrive.c @@ -1095,7 +1095,9 @@ static void KdAddScreen(KdScreenInfo * screen, int argc, char **argv) bm = screen->fb.blueMask; } fbSetVisualTypesAndMasks(screenInfo.formats[i].depth, - visuals, 8, rm, gm, bm); + visuals, + screenInfo.formats[i].depth == 30 ? 10 : 8, /* XXX bitsPerRGB */ + rm, gm, bm); } AddScreen(KdScreenInit, argc, argv, screen); From 354e8843612596f2912aedcae0c54b9d137c1219 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 15:21:29 +0300 Subject: [PATCH 46/47] kdrive/modesetting: Add options `-notile` `-planar` Signed-off-by: stefan11111 --- hw/kdrive/modesetting/Xmodesetting.man | 8 ++++++++ hw/kdrive/modesetting/modesetting.c | 2 ++ hw/kdrive/modesetting/modesetting.h | 2 ++ hw/kdrive/modesetting/ms_glamor.c | 10 ++++++---- hw/kdrive/modesetting/msinit.c | 14 ++++++++++++++ 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/hw/kdrive/modesetting/Xmodesetting.man b/hw/kdrive/modesetting/Xmodesetting.man index 72754901da6..2f02a4b1493 100644 --- a/hw/kdrive/modesetting/Xmodesetting.man +++ b/hw/kdrive/modesetting/Xmodesetting.man @@ -26,6 +26,14 @@ May also lead to flickering. .TP 8 .B -swap Sets the prefered format color ordering to BGR instead of RGB. +.TP 8 +.B -notile +Don't use a tiled front buffer. Needed to support rotations. +.TP 8 +.B -planar +Allow creating a front buffer with planar modifiers. +Could potentially increase performance on hw that supports planar front buffers. +Will most likely lead to bad rendering artifacts on such hw. .SH CONFIGURATION . Like all kdrive X servers, diff --git a/hw/kdrive/modesetting/modesetting.c b/hw/kdrive/modesetting/modesetting.c index 637faa514a7..bea57f4ddd9 100644 --- a/hw/kdrive/modesetting/modesetting.c +++ b/hw/kdrive/modesetting/modesetting.c @@ -26,6 +26,8 @@ modesetting_open(KdScreenInfo *screen, Bool need_map, Bool keep_depth) if (screen->dumb) { need_map = TRUE; + } else if (config->no_tile) { + need_map = TRUE; } else if (randr != RR_Rotate_0) { need_map = TRUE; } diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 275f7bfac69..146b0d36374 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -51,6 +51,8 @@ typedef struct _msScrPriv { typedef struct _msScreenConf { Bool shadow; Bool format_swap; + Bool no_tile; + Bool planar; KdGlamorInfo glamor_info; } MsScreenConf; diff --git a/hw/kdrive/modesetting/ms_glamor.c b/hw/kdrive/modesetting/ms_glamor.c index 07c6ba1730b..9074e1d56ed 100644 --- a/hw/kdrive/modesetting/ms_glamor.c +++ b/hw/kdrive/modesetting/ms_glamor.c @@ -145,11 +145,13 @@ msGlamorInit(ScreenPtr pScreen) * These will get used with frontbuffer rendering, which will * lead to worse-than-tearing with multi-plane formats, as the * primary and auxiliary planes go out of sync. */ - for (int i = 0; i < scrpriv->num_render_modifiers; i++) { - if (gbm_device_get_format_modifier_plane_count(priv->gbm, format, scrpriv->render_modifiers[i]) > 1) { - continue; + if (!config->planar) { + for (int i = 0; i < scrpriv->num_render_modifiers; i++) { + if (gbm_device_get_format_modifier_plane_count(priv->gbm, format, scrpriv->render_modifiers[i]) > 1) { + continue; + } + scrpriv->render_modifiers[write_pos++] = scrpriv->render_modifiers[i]; } - scrpriv->render_modifiers[write_pos++] = scrpriv->render_modifiers[i]; } if (write_pos == 0 || diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index bb41d9b11f9..95c478afa4b 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -240,6 +240,10 @@ ddxUseMsg(void) ("-noshadow Disable the ShadowFB layer if possible\n"); ErrorF ("-swap Prefer BGR format color ordering instead of RGB\n"); + ErrorF + ("-notile Don't use a tiled front buffer\n"); + ErrorF + ("-planar Allow planar modifiers for the front bo\n"); ErrorF("\n"); } @@ -276,6 +280,16 @@ ddxProcessArgument(int argc, char **argv, int i) return 1; } + if (!strcmp(argv[i], "-notile")) { + msCurrScreen->no_tile = TRUE; + return 1; + } + + if (!strcmp(argv[i], "-planar")) { + msCurrScreen->planar = TRUE; + return 1; + } + glamor_arg = KdGlamorParse(&msCurrScreen->glamor_info, argc, argv, i); if (glamor_arg) { return glamor_arg; From 31f32b05b57b39397d8a24b8fa5a8993dfd90485 Mon Sep 17 00:00:00 2001 From: stefan11111 Date: Sat, 26 Sep 2026 15:53:37 +0300 Subject: [PATCH 47/47] kdrive/modesetting: Add hw cursor support Signed-off-by: stefan11111 --- hw/kdrive/modesetting/meson.build | 1 + hw/kdrive/modesetting/modesetting.h | 25 +++ hw/kdrive/modesetting/ms_cursor.c | 330 ++++++++++++++++++++++++++++ hw/kdrive/modesetting/ms_gbm.c | 36 +++ hw/kdrive/modesetting/msinit.c | 6 +- 5 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 hw/kdrive/modesetting/ms_cursor.c diff --git a/hw/kdrive/modesetting/meson.build b/hw/kdrive/modesetting/meson.build index d6acf11960b..caecc48d2c7 100644 --- a/hw/kdrive/modesetting/meson.build +++ b/hw/kdrive/modesetting/meson.build @@ -1,6 +1,7 @@ srcs = [ 'modesetting.c', 'msinit.c', + 'ms_cursor.c', 'ms_damage.c', 'ms_gamma.c', 'ms_gbm.c', diff --git a/hw/kdrive/modesetting/modesetting.h b/hw/kdrive/modesetting/modesetting.h index 146b0d36374..75e1ffcb661 100644 --- a/hw/kdrive/modesetting/modesetting.h +++ b/hw/kdrive/modesetting/modesetting.h @@ -18,6 +18,8 @@ #include "randrstr.h" #endif +#include "mipointrst.h" + typedef struct _msPriv { struct gbm_device *gbm; drmModeRes *resources; @@ -29,6 +31,12 @@ typedef struct _msPriv { uint32_t *used_connectors; } msPriv; +typedef struct _msCursPriv { + struct gbm_bo *bo; + + QueryBestSizeProcPtr QueryBestSize; +} msCursPriv; + typedef struct _msScrPriv { struct gbm_bo *front; drmModeConnector *connector; @@ -37,6 +45,8 @@ typedef struct _msScrPriv { uint32_t conn_id; uint32_t crtc_id; + msCursPriv cursor; + DamagePtr damage; Rotation randr; Bool blockHandler; @@ -91,6 +101,18 @@ Bool msSetShadow(ScreenPtr pScreen); struct gbm_bo* modesetting_open(KdScreenInfo *screen, Bool need_map, Bool keep_depth); +/* ms_cursor.c */ + +Bool msCursorInit(ScreenPtr pScreen); + +void msCursorEnable(ScreenPtr pScreen); + +void msCursorDisable(ScreenPtr pScreen); + +void msRecolorCursor(ScreenPtr pScreen, int ndef, xColorItem *pdef); + +void msCursorFini(ScreenPtr pScreen); + /* ms_damage.c */ Bool msDamageCreateRes(ScreenPtr pScreen); @@ -144,6 +166,9 @@ struct gbm_bo* gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_t height, uint32_t format, uint64_t *modifiers, int num_modifiers); +struct gbm_bo* +gbm_create_cursor_bo(struct gbm_device *gbm, uint32_t width, uint32_t height); + struct gbm_bo* gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap); diff --git a/hw/kdrive/modesetting/ms_cursor.c b/hw/kdrive/modesetting/ms_cursor.c new file mode 100644 index 00000000000..7234276a944 --- /dev/null +++ b/hw/kdrive/modesetting/ms_cursor.c @@ -0,0 +1,330 @@ +/* SPDX-License-Identifier: MIT OR X11 + * + * Copyright © 2026 stefan11111 + */ + +#include + +#include "modesetting.h" + +#include "cursorstr.h" +#include "mi/mipointer_priv.h" + +#include + +static Bool +msShowCursor(ScreenPtr pScreen, int xhot, int yhot); + +static void +msGetCursorSizes(int fd, int *w, int *h) +{ + uint64_t value = 0; + + int ret1 = drmGetCap(fd, DRM_CAP_CURSOR_WIDTH, &value); + *w = value; + + int ret2 = drmGetCap(fd, DRM_CAP_CURSOR_HEIGHT, &value); + *h = value; + + if (ret1 || ret2) { + *w = 64; + *h = 64; + } + + *w &= ~31; + + if (*w > 256) { + *w = 256; + } + + if (*h > 256) { + *h = 256; + } +} + +static void +msQueryBestSize(int class, unsigned short *pwidth, unsigned short *pheight, + ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + msCursPriv *pCurPriv = &scrpriv->cursor; + uint32_t width = gbm_bo_get_width(pCurPriv->bo); + uint32_t height = gbm_bo_get_width(pCurPriv->bo); + + switch (class) { + case CursorShape: + if (*pwidth > width) + *pwidth = width; + if (*pheight > height) + *pheight = height; + if (*pwidth > pScreen->width) + *pwidth = pScreen->width; + if (*pheight > pScreen->height) + *pheight = pScreen->height; + break; + default: + (*pCurPriv->QueryBestSize)(class, pwidth, pheight, pScreen); + break; + } +} + +/* Adapted from kdrive ati_cursor.c RadeonLoadCursor */ +static Bool +msLoadCursor(ScreenPtr pScreen, CursorPtr pCursor) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + msCursPriv *pCurPriv = &scrpriv->cursor; + CursorBitsPtr bits = pCursor->bits; + uint32_t *msk, *mskLine, *src, *srcLine; + + uint32_t width = gbm_bo_get_width(pCurPriv->bo); + uint32_t height = gbm_bo_get_width(pCurPriv->bo); + uint32_t stride = gbm_bo_get_stride(pCurPriv->bo) / sizeof(uint32_t); + uint32_t *ram = gbm_bo_get_map(pCurPriv->bo); + + int x, y; + + int w = bits->width; + int h = bits->height; + + if (w > width) { + w = width; + } + if (h > height) { + h = height; + } + + /* TODO: Deal with rotations */ + + if (bits->argb) { + srcLine = bits->argb; + for (y = 0; y < h; y++) { + src = srcLine; + srcLine += bits->width; + for (x = 0; x < w; x++) { + ram[y * stride + x] = *src++; + } + memset(ram + y * stride + x, 0, (width - x) * sizeof(*ram)); + } + for (; y < height; y++) { + memset(ram + y * stride, 0, width * sizeof(*ram)); + } + } else { + uint32_t colors[4]; + colors[0] = 0; + colors[1] = 0; + colors[2] = (((pCursor->backRed >> 8) << 16) | + ((pCursor->backGreen >> 8) << 8) | + ((pCursor->backBlue >> 8) << 0) | + 0xff000000); + colors[3] = (((pCursor->foreRed >> 8) << 16) | + ((pCursor->foreGreen >> 8) << 8) | + ((pCursor->foreBlue >> 8) << 0) | + 0xff000000); + mskLine = (uint32_t*)bits->mask; + srcLine = (uint32_t*)bits->source; + + /* words per line */ + int lwsrc = BitmapBytePad(bits->width) / sizeof(uint32_t); + + for (y = 0; y < height; y++) { + uint32_t m, s; + + msk = mskLine; + src = srcLine; + mskLine += lwsrc; + srcLine += lwsrc; + + for (x = 0; x < width / 32; x++) { + if (y < h && x < lwsrc) { + m = *msk++; + s = *src++; + } else { + m = 0; + s = 0; + } + + for (int k = 0; k < 32; k++) { + uint32_t val = (s & 1) | ((m & 1) << 1); + ram[y * stride + x * 32 + k] = colors[val]; + s >>= 1; + m >>= 1; + } + } + } + } + + return msShowCursor(pScreen, bits->xhot, bits->yhot); +} + +static Bool +msShowCursor(ScreenPtr pScreen, int xhot, int yhot) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + msCursPriv *pCurPriv = &scrpriv->cursor; + uint32_t width = gbm_bo_get_width(pCurPriv->bo); + uint32_t height = gbm_bo_get_width(pCurPriv->bo); + int fd = gbm_device_get_fd(priv->gbm); + uint32_t handle = gbm_bo_get_handle(pCurPriv->bo).u32; + + return !drmModeSetCursor2(fd, scrpriv->crtc_id, handle, width, height, xhot, yhot) || + !drmModeSetCursor(fd, scrpriv->crtc_id, handle, width, height); +} + +static Bool +msUnloadCursor(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + int fd = gbm_device_get_fd(priv->gbm); + + return !drmModeSetCursor2(fd, scrpriv->crtc_id, 0, 0, 0, 0, 0) || + !drmModeSetCursor(fd, scrpriv->crtc_id, 0, 0, 0); +} + +static Bool +msRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + +static Bool +msUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) +{ + return TRUE; +} + +static void +msMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + + int fd = gbm_device_get_fd(priv->gbm); + + drmModeMoveCursor(fd, scrpriv->crtc_id, x, y); +} + +static void +msSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +{ + KdScreenPriv(pScreen); + + if (!pScreenPriv->enabled) { + return; + } + + if (pCursor) { + msLoadCursor(pScreen, pCursor); + msMoveCursor(pDev, pScreen, x, y); + } else { + msUnloadCursor(pScreen); + } +} + +static Bool +msDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + return TRUE; +} + +static void +msDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScreen) +{ + return; +} + +static miPointerSpriteFuncRec msPointerSpriteFuncs = { + msRealizeCursor, + msUnrealizeCursor, + msSetCursor, + msMoveCursor, + msDeviceCursorInitialize, + msDeviceCursorCleanup +}; + +Bool +msCursorInit(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msPriv *priv = screen->card->driver; + msScrPriv *scrpriv = screen->driver; + msCursPriv *pCurPriv = &scrpriv->cursor; + + int fd = gbm_device_get_fd(priv->gbm); + int width, height; + + msGetCursorSizes(fd, &width, &height); + + if (width <= 0 || height <= 0) { + return FALSE; + } + + /* See if hw cursor is supported */ + if (drmModeSetCursor2(fd, scrpriv->crtc_id, 0, 0, 0, 0, 0) && errno == ENOSYS) { + if (drmModeSetCursor(fd, scrpriv->crtc_id, 0, 0, 0) && (errno == ENOSYS || errno == ENXIO)) { + return FALSE; + } + } + + pCurPriv->bo = gbm_create_cursor_bo(priv->gbm, width, height); + if (!pCurPriv->bo) { + return FALSE; + } + + pCurPriv->QueryBestSize = pScreen->QueryBestSize; + pScreen->QueryBestSize = msQueryBestSize; + + if (!miPointerInitialize(pScreen, + &msPointerSpriteFuncs, + &kdPointerScreenFuncs, + FALSE /* waitForUpdate */)) { + gbm_bo_destroy(pCurPriv->bo); + pCurPriv->bo = NULL; + return FALSE; + } + + LogMessage(X_INFO, "Xmodesetting(%d): Using a %dx%d hw cursor\n", pScreen->myNum, width, height); + return TRUE; +} + +void +msCursorEnable(ScreenPtr pScreen) +{ +} + +void +msCursorDisable(ScreenPtr pScreen) +{ +} + +void +msRecolorCursor(ScreenPtr pScreen, int ndef, xColorItem *pdef) +{ +} + +void +msCursorFini(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + msCursPriv *pCurPriv = &scrpriv->cursor; + + pScreen->QueryBestSize = pCurPriv->QueryBestSize; + + gbm_bo_destroy(pCurPriv->bo); +} diff --git a/hw/kdrive/modesetting/ms_gbm.c b/hw/kdrive/modesetting/ms_gbm.c index 8bd2304ae96..64ac7f56cfb 100644 --- a/hw/kdrive/modesetting/ms_gbm.c +++ b/hw/kdrive/modesetting/ms_gbm.c @@ -369,6 +369,42 @@ gbm_create_front_bo(struct gbm_device *gbm, Bool do_map, uint32_t width, uint32_ return NULL; } +struct gbm_bo* +gbm_create_cursor_bo(struct gbm_device *gbm, uint32_t width, uint32_t height) +{ + struct gbm_bo *ret = NULL; + gbm_user_data_t *data = NULL; + + data = calloc(1, sizeof(*data)); + if (!data) { + goto fail; + } + + ret = gbm_bo_create_and_map_once(gbm, data, + width, height, + GBM_FORMAT_ARGB8888, + GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE); + if (!ret) { + goto fail; + } + + gbm_bo_set_user_data(ret, data, destroy_user_data); + return ret; + +fail: + if (ret) { + gbm_bo_destroy(ret); + /* destroy_user_data takes care of the rest */ + return NULL; + } + + if (data) { + free(data); + } + + return NULL; +} + struct gbm_bo* gbm_create_front_for_screen(KdScreenInfo *screen, Bool do_map, Bool do_swap) { diff --git a/hw/kdrive/modesetting/msinit.c b/hw/kdrive/modesetting/msinit.c index 95c478afa4b..676384dd15e 100644 --- a/hw/kdrive/modesetting/msinit.c +++ b/hw/kdrive/modesetting/msinit.c @@ -323,7 +323,11 @@ KdCardFuncs msFuncs = { .scrfini = msScreenFini, .cardfini = msCardFini, - /* no cursor funcs */ + .initCursor = msCursorInit, + .enableCursor = msCursorEnable, + .disableCursor = msCursorDisable, + .finiCursor = msCursorFini, + .recolorCursor = msRecolorCursor, #ifdef GLAMOR .initAccel = msGlamorInit,