[PATCH 12/12 v3] xwayland: add partial xvidmode extension support
Olivier Fourdan
ofourdan at redhat.com
Wed Feb 10 08:35:39 UTC 2016
Older games (mostly those based on SDL 1.x) rely on the XVidMode
extension and would refuse to run without.
Add a simple, limited and read-only xvidmode support that reports the
current mode used so that games that rely on xvidmode extension can run
on XWayland.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=87806
Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
---
v2: Pretend Set/GetGamma work so that OpenArena can run in Xwayland
v3: Check HSync/VRefresh/HTotal/VTotal to accept the mode we advertised
Register xwlVidModePrivateKey() only once in xwlVidModeExtensionInit()
hw/xwayland/Makefile.am | 2 +
hw/xwayland/xwayland-vidmode.c | 409 +++++++++++++++++++++++++++++++++++++++++
hw/xwayland/xwayland.c | 8 +
hw/xwayland/xwayland.h | 4 +
4 files changed, 423 insertions(+)
create mode 100644 hw/xwayland/xwayland-vidmode.c
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index ab1bbb6..0905082 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -16,6 +16,7 @@ Xwayland_SOURCES = \
xwayland-shm.c \
xwayland-output.c \
xwayland-cvt.c \
+ xwayland-vidmode.c \
xwayland.h \
$(top_srcdir)/Xext/dpmsstubs.c \
$(top_srcdir)/Xi/stubs.c \
@@ -25,6 +26,7 @@ Xwayland_LDADD = \
$(glamor_lib) \
$(XWAYLAND_LIBS) \
$(XWAYLAND_SYS_LIBS) \
+ $(top_builddir)/Xext/libXvidmode.la \
$(XSERVER_SYS_LIBS)
Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
diff --git a/hw/xwayland/xwayland-vidmode.c b/hw/xwayland/xwayland-vidmode.c
new file mode 100644
index 0000000..e31eeaa
--- /dev/null
+++ b/hw/xwayland/xwayland-vidmode.c
@@ -0,0 +1,409 @@
+/*
+ * Copyright (c) 1999-2003 by The XFree86 Project, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Except as contained in this notice, the name of the copyright holder(s)
+ * and author(s) shall not be used in advertising or otherwise to promote
+ * the sale, use or other dealings in this Software without prior written
+ * authorization from the copyright holder(s) and author(s).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "misc.h"
+#include "os.h"
+#include "extinit.h"
+
+#ifdef XF86VIDMODE
+#include "xwayland.h"
+#include "randrstr.h"
+#include "vidmodestr.h"
+
+static DevPrivateKeyRec xwlVidModePrivateKeyRec;
+#define xwlVidModePrivateKey (&xwlVidModePrivateKeyRec)
+
+/* Taken from xrandr, h sync frequency in KHz */
+static double
+mode_hsync(const xRRModeInfo *mode_info)
+{
+ double rate;
+
+ if (mode_info->hTotal)
+ rate = (double) mode_info->dotClock / (double) mode_info->hTotal;
+ else
+ rate = 0.0;
+
+ return rate / 1000.0;
+}
+
+/* Taken from xrandr, v refresh frequency in Hz */
+static double
+mode_refresh(const xRRModeInfo *mode_info)
+{
+ double rate;
+ double vTotal = mode_info->vTotal;
+
+ if (mode_info->modeFlags & RR_DoubleScan)
+ vTotal *= 2.0;
+
+ if (mode_info->modeFlags & RR_Interlace)
+ vTotal /= 2.0;
+
+ if (mode_info->hTotal > 0.0 && vTotal > 0.0)
+ rate = ((double) mode_info->dotClock /
+ ((double) mode_info->hTotal * (double) vTotal));
+ else
+ rate = 0.0;
+
+ return rate;
+}
+
+static Bool
+xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
+{
+ DisplayModePtr pMod;
+ RROutputPtr output;
+ RRCrtcPtr crtc;
+ xRRModeInfo rrmode;
+
+ pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey);
+ if (pMod == NULL)
+ return FALSE;
+
+ output = RRFirstOutput(pScreen);
+ if (output == NULL)
+ return FALSE;
+
+ crtc = output->crtc;
+ if (crtc == NULL)
+ return FALSE;
+
+ rrmode = crtc->mode->mode;
+
+ pMod->next = pMod;
+ pMod->prev = pMod;
+ pMod->name = "";
+ pMod->VScan = 1;
+ pMod->Private = NULL;
+ pMod->HDisplay = rrmode.width;
+ pMod->HSyncStart = rrmode.hSyncStart;
+ pMod->HSyncEnd = rrmode.hSyncEnd;
+ pMod->HTotal = rrmode.hTotal;
+ pMod->HSkew = rrmode.hSkew;
+ pMod->VDisplay = rrmode.height;
+ pMod->VSyncStart = rrmode.vSyncStart;
+ pMod->VSyncEnd = rrmode.vSyncEnd;
+ pMod->VTotal = rrmode.vTotal;
+ pMod->Flags = rrmode.modeFlags;
+ pMod->Clock = rrmode.dotClock / 1000.0;
+ pMod->VRefresh = mode_refresh(&rrmode); /* Or RRVerticalRefresh() */
+ pMod->HSync = mode_hsync(&rrmode);
+ *mode = pMod;
+
+ if (dotClock != NULL)
+ *dotClock = rrmode.dotClock / 1000.0;
+
+ return TRUE;
+}
+
+static vidMonitorValue
+xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
+{
+ vidMonitorValue ret = { NULL, };
+ DisplayModePtr pMod;
+
+ if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+ return ret;
+
+ switch (valtyp) {
+ case VIDMODE_MON_VENDOR:
+ ret.ptr = XVENDORNAME;
+ break;
+ case VIDMODE_MON_MODEL:
+ ret.ptr = "XWAYLAND";
+ break;
+ case VIDMODE_MON_NHSYNC:
+ ret.i = 1;
+ break;
+ case VIDMODE_MON_NVREFRESH:
+ ret.i = 1;
+ break;
+ case VIDMODE_MON_HSYNC_LO:
+ case VIDMODE_MON_HSYNC_HI:
+ ret.f = 100.0 * pMod->HSync;
+ break;
+ case VIDMODE_MON_VREFRESH_LO:
+ case VIDMODE_MON_VREFRESH_HI:
+ ret.f = 100.0 * pMod->VRefresh;
+ break;
+ }
+ return ret;
+}
+
+static int
+xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock)
+{
+ DisplayModePtr pMod;
+
+ if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+ return 0;
+
+ return pMod->Clock;
+
+}
+
+static int
+xwlVidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock)
+{
+ return 1;
+}
+
+static Bool
+xwlVidModeGetClocks(ScreenPtr pScreen, int *Clocks)
+{
+ *Clocks = xwlVidModeGetDotClock(pScreen, 0);
+
+ return TRUE;
+}
+
+static Bool
+xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
+{
+ return FALSE;
+}
+
+static Bool
+xwlVidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
+{
+ return xwlVidModeGetCurrentModeline(pScreen, mode, dotClock);
+}
+
+static Bool
+xwlVidModeDeleteModeline(ScreenPtr pScreen, DisplayModePtr mode)
+{
+ /* Unsupported */
+ return FALSE;
+}
+
+static Bool
+xwlVidModeZoomViewport(ScreenPtr pScreen, int zoom)
+{
+ /* Unsupported for now */
+ return FALSE;
+}
+
+static Bool
+xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y)
+{
+ /* Unsupported for now */
+ return FALSE;
+}
+
+static Bool
+xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y)
+{
+ RROutputPtr output;
+ RRCrtcPtr crtc;
+
+ output = RRFirstOutput(pScreen);
+ if (output == NULL)
+ return FALSE;
+
+ crtc = output->crtc;
+ if (crtc == NULL)
+ return FALSE;
+
+ *x = crtc->x;
+ *y = crtc->y;
+
+ return TRUE;
+}
+
+static Bool
+xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
+{
+ /* Unsupported for now */
+ return FALSE;
+}
+
+static Bool
+xwlVidModeLockZoom(ScreenPtr pScreen, Bool lock)
+{
+ /* Unsupported for now, but pretend it works */
+ return TRUE;
+}
+
+static ModeStatus
+xwlVidModeCheckModeForMonitor(ScreenPtr pScreen, DisplayModePtr mode)
+{
+ DisplayModePtr pMod;
+
+ /* This should not happen */
+ if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+ return MODE_ERROR;
+
+ /* Only support mode with the same HSync/VRefresh as we advertise */
+ if (mode->HSync == pMod->HSync && mode->VRefresh == pMod->VRefresh)
+ return MODE_OK;
+
+ /* All the rest is unsupported - If we want to succeed, return MODE_OK instead */
+ return MODE_ONE_SIZE;
+}
+
+static ModeStatus
+xwlVidModeCheckModeForDriver(ScreenPtr pScreen, DisplayModePtr mode)
+{
+ DisplayModePtr pMod;
+
+ /* This should not happen */
+ if (!xwlVidModeGetCurrentModeline(pScreen, &pMod, NULL))
+ return MODE_ERROR;
+
+ if (mode->HTotal != pMod->HTotal)
+ return MODE_BAD_HVALUE;
+
+ if (mode->VTotal != pMod->VTotal)
+ return MODE_BAD_VVALUE;
+
+ /* Unsupported for now, but pretend it works */
+ return MODE_OK;
+}
+
+static void
+xwlVidModeSetCrtcForMode(ScreenPtr pScreen, DisplayModePtr mode)
+{
+ /* Unsupported */
+ return;
+}
+
+static Bool
+xwlVidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode)
+{
+ /* Unsupported */
+ return FALSE;
+}
+
+static int
+xwlVidModeGetNumOfModes(ScreenPtr pScreen)
+{
+ /* We have only one mode */
+ return 1;
+}
+
+static Bool
+xwlVidModeSetGamma(ScreenPtr pScreen, float red, float green, float blue)
+{
+ /* Unsupported for now, but pretend it works */
+ return TRUE;
+}
+
+static Bool
+xwlVidModeGetGamma(ScreenPtr pScreen, float *red, float *green, float *blue)
+{
+ /* Unsupported for now, but pretend it works */
+ return TRUE;
+}
+
+static Bool
+xwlVidModeSetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
+{
+ /* Unsupported for now */
+ return FALSE;
+}
+
+static Bool
+xwlVidModeGetGammaRamp(ScreenPtr pScreen, int size, CARD16 *r, CARD16 *g, CARD16 *b)
+{
+ /* Unsupported for now */
+ return FALSE;
+}
+
+static int
+xwlVidModeGetGammaRampSize(ScreenPtr pScreen)
+{
+ /* Unsupported for now */
+ return 0;
+}
+
+static Bool
+xwlVidModeInit(ScreenPtr pScreen)
+{
+ VidModePtr pVidMode = NULL;
+
+ pVidMode = VidModeInit(pScreen);
+ if (!pVidMode)
+ return FALSE;
+
+ pVidMode->Flags = 0;
+ pVidMode->Next = NULL;
+
+ pVidMode->GetMonitorValue = xwlVidModeGetMonitorValue;
+ pVidMode->GetCurrentModeline = xwlVidModeGetCurrentModeline;
+ pVidMode->GetFirstModeline = xwlVidModeGetFirstModeline;
+ pVidMode->GetNextModeline = xwlVidModeGetNextModeline;
+ pVidMode->DeleteModeline = xwlVidModeDeleteModeline;
+ pVidMode->ZoomViewport = xwlVidModeZoomViewport;
+ pVidMode->GetViewPort = xwlVidModeGetViewPort;
+ pVidMode->SetViewPort = xwlVidModeSetViewPort;
+ pVidMode->SwitchMode = xwlVidModeSwitchMode;
+ pVidMode->LockZoom = xwlVidModeLockZoom;
+ pVidMode->GetNumOfClocks = xwlVidModeGetNumOfClocks;
+ pVidMode->GetClocks = xwlVidModeGetClocks;
+ pVidMode->CheckModeForMonitor = xwlVidModeCheckModeForMonitor;
+ pVidMode->CheckModeForDriver = xwlVidModeCheckModeForDriver;
+ pVidMode->SetCrtcForMode = xwlVidModeSetCrtcForMode;
+ pVidMode->AddModeline = xwlVidModeAddModeline;
+ pVidMode->GetDotClock = xwlVidModeGetDotClock;
+ pVidMode->GetNumOfModes = xwlVidModeGetNumOfModes;
+ pVidMode->SetGamma = xwlVidModeSetGamma;
+ pVidMode->GetGamma = xwlVidModeGetGamma;
+ pVidMode->SetGammaRamp = xwlVidModeSetGammaRamp;
+ pVidMode->GetGammaRamp = xwlVidModeGetGammaRamp;
+ pVidMode->GetGammaRampSize = xwlVidModeGetGammaRampSize;
+
+ return TRUE;
+}
+
+void
+xwlVidModeExtensionInit(void)
+{
+ int i;
+ Bool enabled = FALSE;
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ if (xwlVidModeInit (screenInfo.screens[i]))
+ enabled = TRUE;
+ }
+ /* This means that the DDX doesn't want the vidmode extension enabled */
+ if (!enabled)
+ return;
+
+ if (!dixRegisterPrivateKey(xwlVidModePrivateKey, PRIVATE_SCREEN,
+ sizeof(DisplayModeRec)))
+ return;
+
+ VidModeAddExtension(FALSE);
+}
+
+#endif /* XF86VIDMODE */
+
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 3d36205..77a5c29 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -33,6 +33,11 @@
#include <compositeext.h>
#include <glx_extinit.h>
+#ifdef XF86VIDMODE
+#include <X11/extensions/xf86vmproto.h>
+_X_EXPORT Bool noXFree86VidModeExtension;
+#endif
+
void
ddxGiveUp(enum ExitCode error)
{
@@ -705,6 +710,9 @@ static const ExtensionModule xwayland_extensions[] = {
#ifdef GLXEXT
{ GlxExtensionInit, "GLX", &noGlxExtension },
#endif
+#ifdef XF86VIDMODE
+ { xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
+#endif
};
void
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index a7d7119..581997c 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -189,4 +189,8 @@ Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
uint32_t id, uint32_t version);
struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
+#ifdef XF86VIDMODE
+void xwlVidModeExtensionInit(void);
+#endif
+
#endif
--
2.5.0
More information about the xorg-devel
mailing list