diff --git a/configure.ac b/configure.ac index a30d074..6092535 100644 --- a/configure.ac +++ b/configure.ac @@ -262,7 +262,7 @@ dnl kdrive and its subsystems AC_ARG_ENABLE(kdrive, AS_HELP_STRING([--enable-kdrive], [Build kdrive servers (default: yes)]), [KDRIVE=$enableval], [KDRIVE=yes]) AC_ARG_ENABLE(xvesa, AS_HELP_STRING([--disable-xvesa], [Build Xvesa server (default: yes)]), [XVESA=$enableval], [XVESA=yes]) AC_ARG_ENABLE(xfbdev, AS_HELP_STRING([--disable-xfbdev], [Build Xfbdev server (default: yes)]), [XFBDEV=$enableval], [XFBDEV=yes]) - +AC_ARG_ENABLE(xmodesetting, AS_HELP_STRING([--disable-xmodesetting], [Build Xmodesetting server (default: yes)]), [XMODESETTING=$enableval], [XMODESETTING=yes]) dnl chown/chmod to be setuid root as part of build dnl Replaces InstallXserverSetUID in imake @@ -548,7 +548,16 @@ if test "$KDRIVE" = yes; then AC_DEFINE(KDRIVEFBDEV, 1, [Build fbdev-based kdrive server]) fi fi - + + + PKG_CHECK_MODULES(GBM, "gbm", [GBM=yes], [GBM=no]) + PKG_CHECK_MODULES(LIBDRM, "libdrm", [LIBDRM=yes], [LIBDRM=no]) + if test "x$GBM" != "xno" -a "x$LIBDRM" != "xno"; then + if test "x$XMODESETTING" != "xno"; then + AC_DEFINE(KDRIVEMODESETTING, 1, [Build modesetting-based kdrive server]) + fi + fi + # damage shadow extension fb mi KDRIVE_INC='-I$(top_srcdir)/kdrive/src' KDRIVE_PURE_INCS="$KDRIVE_INC $MIEXT_DAMAGE_INC $MIEXT_SHADOW_INC $XEXT_INC $FB_INC $MI_INC" @@ -579,6 +588,7 @@ AC_SUBST(KDRIVE_LIBS) AM_CONDITIONAL(KDRIVELINUX, [test "x$KDRIVELINUX" = xyes]) AM_CONDITIONAL(KDRIVEVESA, [test x"$ac_cv_header_asm_vm86_h" = xyes -a "x$XVESA" != "xno"]) AM_CONDITIONAL(KDRIVEFBDEV, [test x"$ac_cv_header_linux_fb_h" = xyes -a "x$XFBDEV" != "xno"]) +AM_CONDITIONAL(KDRIVEMODESETTING, [test "x$XMODESETTING" != "xno"]) dnl and the rest of these are generic, so they're in config.h AC_DEFINE(XResExtension, 1, [Build XRes extension]) @@ -661,6 +671,7 @@ xfixes/Makefile kdrive/Makefile kdrive/fbdev/Makefile kdrive/linux/Makefile +kdrive/modesetting/Makefile kdrive/src/Makefile kdrive/vesa/Makefile ]) diff --git a/kdrive/Makefile.am b/kdrive/Makefile.am index 8f0bd76..21c2add 100644 --- a/kdrive/Makefile.am +++ b/kdrive/Makefile.am @@ -6,6 +6,10 @@ if KDRIVEFBDEV FBDEV_SUBDIRS = fbdev endif +if KDRIVEMODESETTING +MODESETTING_SUBDIRS = modesetting +endif + if KDRIVELINUX LINUX_SUBDIRS = linux endif @@ -14,6 +18,7 @@ SUBDIRS = \ src \ $(LINUX_SUBDIRS) \ $(FBDEV_SUBDIRS) \ - $(VESA_SUBDIRS) + $(VESA_SUBDIRS) \ + $(MODESETTING_SUBDIRS) DIST_SUBDIRS = vesa fbdev src linux diff --git a/kdrive/modesetting/Makefile.am b/kdrive/modesetting/Makefile.am new file mode 100644 index 0000000..13f7032 --- /dev/null +++ b/kdrive/modesetting/Makefile.am @@ -0,0 +1,31 @@ +AM_CPPFLAGS = \ + @KDRIVE_INCS@ \ + @KDRIVE_CFLAGS@ \ + $(shell pkg-config --cflags libdrm gbm) + +noinst_LIBRARIES = libmodesetting.a + +bin_PROGRAMS = Xmodesetting + +libmodesetting_a_SOURCES = \ + modesetting.c \ + modesetting.h + +Xmodesetting_SOURCES = \ + msinit.c + +Xmodesetting_LDFLAGS = $(shell pkg-config --libs libdrm gbm) + +Xmodesetting_LDADD = \ + libmodesetting.a \ + @KDRIVE_LIBS@ \ + @XSERVER_LIBS@ + +Xmodesetting_DEPENDENCIES = \ + libmodesetting.a @KDRIVE_LIBS@ + +install-exec-hook: +if INSTALL_SETUID + chown root $(DESTDIR)$(bindir)/Xmodesetting + chmod u+s $(DESTDIR)$(bindir)/Xmodesetting +endif diff --git a/kdrive/modesetting/modesetting.c b/kdrive/modesetting/modesetting.c new file mode 100644 index 0000000..5c710a8 --- /dev/null +++ b/kdrive/modesetting/modesetting.c @@ -0,0 +1,698 @@ +/* + * + * Copyright © 1999 Keith Packard + * Copyright � 2026 stefan11111 + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include "modesetting.h" +#include + +#include + +typedef struct { + drmModeConnector *connector; + drmModeRes *resources; + + void *map_data; + void *map_addr; + + uint32_t fb_id; +} gbm_user_data_t; + +extern int KdTsPhyScreen; + +const char *msDevicePath = NULL; + +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) +{ + uint32_t width = data->connector->modes[0].hdisplay; + uint32_t height = data->connector->modes[0].vdisplay; + + uint32_t format = GBM_FORMAT_XRGB8888; + 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; + uint32_t flags_dumb = GBM_BO_USE_SCANOUT | GBM_BO_USE_WRITE; + + struct gbm_bo *bo = NULL; + + 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); + } + 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 drmModeConnector* +modesetting_find_connector(drmModeRes *res, int fd, uint32_t *conn_id) +{ + for (int i = 0; i < res->count_connectors; i++) { + drmModeConnector *conn; + *conn_id = res->connectors[i]; + conn = drmModeGetConnector(fd, *conn_id); + if (!conn) { + continue; + } + + if (conn->modes && conn->count_modes) { + return conn; + } + + drmModeFreeConnector(conn); + } + return NULL; +} + +static struct gbm_bo* +modesetting_open(int fd) +{ + struct gbm_device *gbm = NULL; + struct gbm_bo *ret = NULL; + gbm_user_data_t *data = NULL; + + uint32_t conn_id; + uint32_t crtc_id; + + gbm = gbm_create_device(fd); + if (!gbm) { + return NULL; + } + + data = calloc(1, sizeof(*data)); + if (!data) { + goto alloc_fail; + } + + data->resources = drmModeGetResources(fd); + if (!data->resources) { + goto res_fail; + } + + crtc_id = data->resources->crtcs[0]; + + data->connector = modesetting_find_connector(data->resources, fd, &conn_id); + if (!data->connector) { + goto conn_fail; + } + + ret = gbm_bo_create_and_map(gbm, data); + if (!ret) { + goto bo_fail; + } + + /* From here on, destroy_user_data cleans up any errors */ + gbm_bo_set_user_data(ret, data, destroy_user_data); + + data->fb_id = gbm_bo_create_fb(ret); + if (!data->fb_id) { + goto create_fb_fail; + } + + if (drmModeSetCrtc(fd, crtc_id, data->fb_id, 0, 0, &conn_id, 1, &data->connector->modes[0])) { + goto set_crtc_fail; + } + + return ret; + +bo_fail: + drmModeFreeConnector(data->connector); +conn_fail: + drmModeFreeResources(data->resources); +res_fail: + free(data); +alloc_fail: + gbm_device_destroy(gbm); + return NULL; + +set_crtc_fail: +create_fb_fail: + gbm_bo_destroy(ret); + return NULL; +} + +static Bool msInitialize(KdCardInfo * card, msPriv * priv) +{ + int fd; + + if (msDevicePath == NULL) + msDevicePath = "/dev/dri/card0"; + + if ((fd = open(msDevicePath, O_RDWR)) < 0) { + ErrorF("Error opening drm device %s: %s\n", + msDevicePath, strerror(errno)); + return FALSE; + } + + priv->front = modesetting_open(fd); + if (!priv->front) { + perror("Could not get front gbm bo\n"); + close(fd); + return FALSE; + } + + return TRUE; +} + + + +Bool msCardInit(KdCardInfo * card) +{ + msPriv *priv; + + priv = malloc(sizeof(msPriv)); + if (!priv) + return FALSE; + + if (!msInitialize(card, priv)) { + free(priv); + return FALSE; + } + card->driver = priv; + + return TRUE; +} + +#if 0 /* The only supported format's pixels are already contiguous */ +static Pixel msMakeContig(Pixel orig, Pixel others) +{ + Pixel low; + + low = lowbit(orig) >> 1; + while (low && (others & low) == 0) { + orig |= low; + low >>= 1; + } + return orig; +} +#endif + +static Bool msScreenInitialize(KdScreenInfo * screen, msScrPriv * scrpriv) +{ + msPriv *priv = screen->card->driver; + + screen->width = gbm_bo_get_width(priv->front); + screen->height = gbm_bo_get_height(priv->front); + screen->rate = 60; /* FIXME: If we actually need this, querry this somehow */ + + 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; + +#if 0 /* The only supported format's pixels are already contiguous */ + /* + * This is a kludge so that Render will work -- fill in the gaps + * in the pixel + */ + screen->fb.redMask = msMakeContig(screen->fb.redMask, + screen->fb.greenMask | + screen->fb.blueMask); + + screen->fb.greenMask = msMakeContig(screen->fb.greenMask, + screen->fb.redMask | + screen->fb.blueMask); + + screen->fb.blueMask = msMakeContig(screen->fb.blueMask, + screen->fb.redMask | + screen->fb.greenMask); +#endif + + 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); + msPriv *priv = pScreenPriv->card->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; + KdMouseMatrix m; + msPriv *priv = screen->card->driver; + unsigned long stride = gbm_bo_get_stride(priv->front); + + /* TODO: add an option to disable shadowfb */ + scrpriv->shadow = TRUE; + + KdComputeMouseMatrix(&m, scrpriv->randr, screen->width, screen->height); + + KdSetMouseMatrix(&m); + + screen->width = gbm_bo_get_width(priv->front); + screen->height = gbm_bo_get_height(priv->front); + screen->memory_base = gbm_bo_get_map(priv->front); + screen->memory_size = stride * screen->height; + + if (scrpriv->shadow) { + if (!KdShadowFbAlloc(screen, + scrpriv-> + randr & (RR_Rotate_90 | RR_Rotate_270))) + return FALSE; + screen->off_screen_base = screen->memory_size; + } else { + screen->fb.byteStride = stride; + screen->fb.pixelStride = stride / 4; + screen->fb.frameBuffer = gbm_bo_get_map(priv->front); + screen->off_screen_base = + screen->fb.byteStride * screen->height; + } + + return TRUE; +} + +static void msSetScreenSizes(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + KdScreenInfo *screen = pScreenPriv->screen; + msScrPriv *scrpriv = screen->driver; + msPriv *priv = screen->card->driver; + + if (scrpriv->randr & (RR_Rotate_0 | RR_Rotate_180)) { + pScreen->width = gbm_bo_get_width(priv->front); + pScreen->height = gbm_bo_get_height(priv->front); + pScreen->mmWidth = screen->width_mm; + pScreen->mmHeight = screen->height_mm; + } else { + pScreen->width = gbm_bo_get_height(priv->front); + pScreen->height = gbm_bo_get_width(priv->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; + msPriv *priv = screen->card->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; + RRScreenSizePtr pSize; + 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; + + pSize = RRRegisterSize(pScreen, + screen->width, + screen->height, + screen->width_mm, screen->height_mm); + + randr = KdSubRotation(scrpriv->randr, screen->randr); + + RRSetCurrentConfig(pScreen, randr, 0, 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 (!msMapFramebuffer(screen)) + goto bail4; + + KdShadowUnset(screen->pScreen); + + if (!msSetShadow(screen->pScreen)) + goto bail4; + + msSetScreenSizes(screen->pScreen); + + /* + * Set frame buffer mapping + */ + (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap(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 msRandRInit(ScreenPtr pScreen) +{ + rrScrPrivPtr pScrPriv; + + if (!RRScreenInit(pScreen)) + return FALSE; + + pScrPriv = rrGetScrPriv(pScreen); + pScrPriv->rrGetInfo = msRandRGetInfo; + pScrPriv->rrSetConfig = msRandRSetConfig; + 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; +} + +Bool msCreateResources(ScreenPtr pScreen) +{ + return msSetShadow(pScreen); +} + +void msPreserve(KdCardInfo * card) +{ +} + +Bool msEnable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + msPriv *priv = pScreenPriv->card->driver; + + struct gbm_device *gbm = gbm_bo_get_device(priv->front); + int fd = gbm_device_get_fd(gbm); + + drmSetMaster(fd); + + return TRUE; +} + +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; +} + +void msDisable(ScreenPtr pScreen) +{ + KdScreenPriv(pScreen); + msPriv *priv = pScreenPriv->card->driver; + + struct gbm_device *gbm = gbm_bo_get_device(priv->front); + int fd = gbm_device_get_fd(gbm); + + drmDropMaster(fd); +} + +void msRestore(KdCardInfo * card) +{ +} + +void msScreenFini(KdScreenInfo * screen) +{ +} + +void msCardFini(KdCardInfo * card) +{ + msPriv *priv = card->driver; + + struct gbm_device *gbm = gbm_bo_get_device(priv->front); + int fd = gbm_device_get_fd(gbm); + + gbm_bo_destroy(priv->front); + close(fd); + free(priv); +} diff --git a/kdrive/modesetting/modesetting.h b/kdrive/modesetting/modesetting.h new file mode 100644 index 0000000..74960e0 --- /dev/null +++ b/kdrive/modesetting/modesetting.h @@ -0,0 +1,75 @@ +/* + * + * Copyright © 1999 Keith Packard + * Copyright � 2026 stefan11111 + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _MODESETTING_H_ +#define _MODESETTING_H_ +#include +#include + +#include +#include +#include + +#include "kdrive.h" + +#include "randrstr.h" + +typedef struct _msPriv { + struct gbm_bo *front; + __u16 red[256]; + __u16 green[256]; + __u16 blue[256]; +} msPriv; + +typedef struct _msScrPriv { + Rotation randr; + Bool shadow; +} msScrPriv; + +extern const char *msDevicePath; + +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); +#endif /* _MODESETTING_H_ */ diff --git a/kdrive/modesetting/msinit.c b/kdrive/modesetting/msinit.c new file mode 100644 index 0000000..093e57d --- /dev/null +++ b/kdrive/modesetting/msinit.c @@ -0,0 +1,101 @@ +/* + * + * Copyright © 1999 Keith Packard + * Copyright � 2026 stefan11111 + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include + +static const KdCardFuncs msFuncs = { + msCardInit, /* cardinit */ + msScreenInit, /* scrinit */ + msInitScreen, /* initScreen */ + msFinishInitScreen, /* finishInitScreen */ + msCreateResources, /* createRes */ + msPreserve, /* preserve */ + msEnable, /* enable */ + msDPMS, /* dpms */ + msDisable, /* disable */ + msRestore, /* restore */ + msScreenFini, /* scrfini */ + msCardFini, /* cardfini */ + + NULL, /* initCursor */ + NULL, /* enableCursor */ + NULL, /* disableCursor */ + NULL, /* finiCursor */ + NULL, /* recolorCursor */ + + NULL, /* initAccel */ + NULL, /* enableAccel */ + NULL, /* disableAccel */ + NULL, /* finiAccel */ + + NULL, /* getColors */ + NULL, /* putColors */ +}; + +void InitCard(char *name) +{ + KdCardInfoAdd(&msFuncs, 0); +} + +void InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) +{ + KdInitOutput(pScreenInfo, argc, argv); +} + +void InitInput(int argc, char **argv) +{ + KdInitInput(&LinuxMouseFuncs, &LinuxKeyboardFuncs); +} + +void ddxUseMsg(void) +{ + KdUseMsg(); + ErrorF("\nXmodesetting Device Usage:\n"); + ErrorF + ("-dev path Modesetting device to use. Defaults to /dev/dri/card0\n"); + ErrorF("\n"); +} + +int ddxProcessArgument(int argc, char **argv, int i) +{ + + if (!strcmp(argv[i], "-version")) { + kdVersion("Xmodesetting"); + exit(0); + } + + if (!strcmp(argv[i], "-dev")) { + if (i + 1 < argc) { + msDevicePath = argv[i + 1]; + return 2; + } + UseMsg(); + exit(1); + } + + return KdProcessArgument(argc, argv, i); +}