2016-02-10 09:35:39 +01:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
|
2019-07-08 14:00:27 +02:00
|
|
|
static void
|
|
|
|
xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode)
|
|
|
|
{
|
|
|
|
const xRRModeInfo *mode_info = &rrmode->mode;
|
|
|
|
|
|
|
|
mode->next = mode;
|
|
|
|
mode->prev = mode;
|
|
|
|
mode->name = "";
|
|
|
|
mode->VScan = 1;
|
|
|
|
mode->Private = NULL;
|
|
|
|
mode->HDisplay = mode_info->width;
|
|
|
|
mode->HSyncStart = mode_info->hSyncStart;
|
|
|
|
mode->HSyncEnd = mode_info->hSyncEnd;
|
|
|
|
mode->HTotal = mode_info->hTotal;
|
|
|
|
mode->HSkew = mode_info->hSkew;
|
|
|
|
mode->VDisplay = mode_info->height;
|
|
|
|
mode->VSyncStart = mode_info->vSyncStart;
|
|
|
|
mode->VSyncEnd = mode_info->vSyncEnd;
|
|
|
|
mode->VTotal = mode_info->vTotal;
|
|
|
|
mode->Flags = mode_info->modeFlags;
|
|
|
|
mode->Clock = mode_info->dotClock / 1000.0;
|
|
|
|
mode->VRefresh = mode_refresh(mode_info); /* Or RRVerticalRefresh() */
|
|
|
|
mode->HSync = mode_hsync(mode_info);
|
|
|
|
}
|
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
static RRModePtr
|
|
|
|
xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height)
|
|
|
|
{
|
|
|
|
RROutputPtr output = RRFirstOutput(pScreen);
|
|
|
|
|
|
|
|
if (output == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return xwl_output_find_mode(output->devPrivate, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
static RRModePtr
|
|
|
|
xwlVidModeGetCurrentRRMode(ScreenPtr pScreen)
|
|
|
|
{
|
|
|
|
struct xwl_emulated_mode *emulated_mode;
|
|
|
|
struct xwl_output *xwl_output;
|
|
|
|
RROutputPtr output;
|
|
|
|
|
|
|
|
output = RRFirstOutput(pScreen);
|
|
|
|
if (output == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
xwl_output = output->devPrivate;
|
|
|
|
emulated_mode =
|
|
|
|
xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient());
|
|
|
|
|
|
|
|
if (emulated_mode) {
|
|
|
|
return xwl_output_find_mode(xwl_output,
|
|
|
|
emulated_mode->width,
|
|
|
|
emulated_mode->height);
|
|
|
|
} else {
|
|
|
|
return xwl_output_find_mode(xwl_output, -1, -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-10 09:35:39 +01:00
|
|
|
static Bool
|
|
|
|
xwlVidModeGetCurrentModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
|
|
|
|
{
|
|
|
|
DisplayModePtr pMod;
|
2019-07-08 18:35:27 +02:00
|
|
|
RRModePtr rrmode;
|
2016-02-10 09:35:39 +01:00
|
|
|
|
|
|
|
pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey);
|
|
|
|
if (pMod == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
rrmode = xwlVidModeGetCurrentRRMode(pScreen);
|
|
|
|
if (rrmode == NULL)
|
2016-02-10 09:35:39 +01:00
|
|
|
return FALSE;
|
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
xwlRRModeToDisplayMode(rrmode, pMod);
|
2016-02-10 09:35:39 +01:00
|
|
|
|
2019-07-08 14:00:27 +02:00
|
|
|
*mode = pMod;
|
2016-02-10 09:35:39 +01:00
|
|
|
if (dotClock != NULL)
|
2019-07-08 14:00:27 +02:00
|
|
|
*dotClock = pMod->Clock;
|
2016-02-10 09:35:39 +01:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static vidMonitorValue
|
|
|
|
xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
|
|
|
|
{
|
|
|
|
vidMonitorValue ret = { NULL, };
|
2019-07-08 18:35:27 +02:00
|
|
|
RRModePtr rrmode;
|
2016-02-10 09:35:39 +01:00
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
rrmode = xwlVidModeGetCurrentRRMode(pScreen);
|
|
|
|
if (rrmode == NULL)
|
2016-02-10 09:35:39 +01:00
|
|
|
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:
|
2019-07-08 18:35:27 +02:00
|
|
|
ret.f = mode_hsync(&rrmode->mode) * 100.0;
|
2016-02-10 09:35:39 +01:00
|
|
|
break;
|
|
|
|
case VIDMODE_MON_VREFRESH_LO:
|
|
|
|
case VIDMODE_MON_VREFRESH_HI:
|
2019-07-08 18:35:27 +02:00
|
|
|
ret.f = mode_refresh(&rrmode->mode) * 100.0;
|
2016-02-10 09:35:39 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock)
|
|
|
|
{
|
2019-07-08 18:35:27 +02:00
|
|
|
RRModePtr rrmode;
|
2016-02-10 09:35:39 +01:00
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
rrmode = xwlVidModeGetCurrentRRMode(pScreen);
|
|
|
|
if (rrmode == NULL)
|
2016-02-10 09:35:39 +01:00
|
|
|
return 0;
|
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
return rrmode->mode.dotClock / 1000.0;
|
2016-02-10 09:35:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2016-03-21 09:53:17 +01:00
|
|
|
/* Support only no zoom */
|
|
|
|
return (zoom == 1);
|
2016-02-10 09:35:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y)
|
|
|
|
{
|
2016-03-21 09:53:17 +01:00
|
|
|
RROutputPtr output;
|
|
|
|
RRCrtcPtr crtc;
|
|
|
|
|
|
|
|
output = RRFirstOutput(pScreen);
|
|
|
|
if (output == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
crtc = output->crtc;
|
|
|
|
if (crtc == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Support only default viewport */
|
|
|
|
return (x == crtc->x && y == crtc->y);
|
2016-02-10 09:35:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2019-07-08 18:35:27 +02:00
|
|
|
RRModePtr rrmode;
|
2016-02-10 09:35:39 +01:00
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay);
|
|
|
|
if (rrmode == NULL)
|
2016-02-10 09:35:39 +01:00
|
|
|
return MODE_ERROR;
|
|
|
|
|
|
|
|
/* Only support mode with the same HSync/VRefresh as we advertise */
|
2019-07-08 18:35:27 +02:00
|
|
|
if (mode->HSync == mode_hsync(&rrmode->mode) &&
|
|
|
|
mode->VRefresh == mode_refresh(&rrmode->mode))
|
2016-02-10 09:35:39 +01:00
|
|
|
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)
|
|
|
|
{
|
2019-07-08 18:35:27 +02:00
|
|
|
RRModePtr rrmode;
|
2016-02-10 09:35:39 +01:00
|
|
|
|
2019-07-08 18:35:27 +02:00
|
|
|
rrmode = xwlVidModeGetRRMode(pScreen, mode->HDisplay, mode->VDisplay);
|
|
|
|
return rrmode ? MODE_OK : MODE_ERROR;
|
2016-02-10 09:35:39 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|