xwayland: add partial xvidmode extension support

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
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
Olivier Fourdan 2016-02-10 09:35:39 +01:00 committed by Adam Jackson
parent b430f53bb7
commit 6070a749d9
4 changed files with 422 additions and 0 deletions

View File

@ -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)

View File

@ -0,0 +1,408 @@
/*
* 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 */

View File

@ -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)
{
@ -712,6 +717,9 @@ static const ExtensionModule xwayland_extensions[] = {
#ifdef GLXEXT
{ GlxExtensionInit, "GLX", &noGlxExtension },
#endif
#ifdef XF86VIDMODE
{ xwlVidModeExtensionInit, XF86VIDMODENAME, &noXFree86VidModeExtension },
#endif
};
void

View File

@ -190,4 +190,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