xwayland: Add vidmode mode changing emulation support

Add support for fake mode changes using viewport, for apps which want to
change the resolution when going fullscreen.

Reviewed-by: Olivier Fourdan <ofourdan@redhat.com>
Acked-by: Michel Dänzer <mdaenzer@redhat.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
This commit is contained in:
Hans de Goede 2019-07-09 09:31:13 +02:00
parent bcad1b813a
commit 38de626081

View File

@ -106,26 +106,25 @@ xwlRRModeToDisplayMode(RRModePtr rrmode, DisplayModePtr mode)
static RRModePtr static RRModePtr
xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height) xwlVidModeGetRRMode(ScreenPtr pScreen, int32_t width, int32_t height)
{ {
RROutputPtr output = RRFirstOutput(pScreen); struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
if (output == NULL) if (!xwl_output)
return NULL; return NULL;
return xwl_output_find_mode(output->devPrivate, width, height); return xwl_output_find_mode(xwl_output, width, height);
} }
static RRModePtr static RRModePtr
xwlVidModeGetCurrentRRMode(ScreenPtr pScreen) xwlVidModeGetCurrentRRMode(ScreenPtr pScreen)
{ {
struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
struct xwl_emulated_mode *emulated_mode; struct xwl_emulated_mode *emulated_mode;
struct xwl_output *xwl_output;
RROutputPtr output;
output = RRFirstOutput(pScreen); if (!xwl_output)
if (output == NULL)
return NULL; return NULL;
xwl_output = output->devPrivate;
emulated_mode = emulated_mode =
xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient()); xwl_output_get_emulated_mode_for_client(xwl_output, GetCurrentClient());
@ -199,39 +198,79 @@ xwlVidModeGetMonitorValue(ScreenPtr pScreen, int valtyp, int indx)
static int static int
xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock) xwlVidModeGetDotClock(ScreenPtr pScreen, int Clock)
{ {
RRModePtr rrmode; return Clock;
rrmode = xwlVidModeGetCurrentRRMode(pScreen);
if (rrmode == NULL)
return 0;
return rrmode->mode.dotClock / 1000.0;
} }
static int static int
xwlVidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock) xwlVidModeGetNumOfClocks(ScreenPtr pScreen, Bool *progClock)
{ {
return 1; /* We emulate a programmable clock, rather then a fixed set of clocks */
*progClock = TRUE;
return 0;
} }
static Bool static Bool
xwlVidModeGetClocks(ScreenPtr pScreen, int *Clocks) xwlVidModeGetClocks(ScreenPtr pScreen, int *Clocks)
{ {
*Clocks = xwlVidModeGetDotClock(pScreen, 0); return FALSE; /* Programmable clock, no clock list */
}
/* GetFirstModeline and GetNextModeline are used from Xext/vidmode.c like this:
* if (pVidMode->GetFirstModeline(pScreen, &mode, &dotClock)) {
* do {
* ...
* if (...)
* break;
* } while (pVidMode->GetNextModeline(pScreen, &mode, &dotClock));
* }
* IOW our caller basically always loops over all the modes. There never is a
* return to the mainloop between GetFirstModeline and NextModeline calls where
* other parts of the server may change our state so we do not need to worry
* about xwl_output->randr_output->modes changing underneath us.
* Thus we can simply implement these two callbacks by storing the enumeration
* index in pVidMode->Next.
*/
static Bool
xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
{
struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
VidModePtr pVidMode;
DisplayModePtr pMod;
intptr_t index;
pMod = dixLookupPrivate(&pScreen->devPrivates, xwlVidModePrivateKey);
pVidMode = VidModeGetPtr(pScreen);
if (xwl_output == NULL || pMod == NULL || pVidMode == NULL)
return FALSE;
index = (intptr_t)pVidMode->Next;
if (index >= xwl_output->randr_output->numModes)
return FALSE;
xwlRRModeToDisplayMode(xwl_output->randr_output->modes[index], pMod);
index++;
pVidMode->Next = (void *)index;
*mode = pMod;
if (dotClock != NULL)
*dotClock = pMod->Clock;
return TRUE; return TRUE;
} }
static Bool
xwlVidModeGetNextModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
{
return FALSE;
}
static Bool static Bool
xwlVidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock) xwlVidModeGetFirstModeline(ScreenPtr pScreen, DisplayModePtr *mode, int *dotClock)
{ {
return xwlVidModeGetCurrentModeline(pScreen, mode, dotClock); VidModePtr pVidMode;
intptr_t index = 0;
pVidMode = VidModeGetPtr(pScreen);
if (pVidMode == NULL)
return FALSE;
pVidMode->Next = (void *)index; /* 0 */
return xwlVidModeGetNextModeline(pScreen, mode, dotClock);
} }
static Bool static Bool
@ -251,37 +290,27 @@ xwlVidModeZoomViewport(ScreenPtr pScreen, int zoom)
static Bool static Bool
xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y) xwlVidModeSetViewPort(ScreenPtr pScreen, int x, int y)
{ {
RROutputPtr output; struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
RRCrtcPtr crtc; struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
output = RRFirstOutput(pScreen); if (!xwl_output)
if (output == NULL)
return FALSE;
crtc = output->crtc;
if (crtc == NULL)
return FALSE; return FALSE;
/* Support only default viewport */ /* Support only default viewport */
return (x == crtc->x && y == crtc->y); return (x == xwl_output->x && y == xwl_output->y);
} }
static Bool static Bool
xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y) xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y)
{ {
RROutputPtr output; struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
RRCrtcPtr crtc; struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
output = RRFirstOutput(pScreen); if (!xwl_output)
if (output == NULL)
return FALSE; return FALSE;
crtc = output->crtc; *x = xwl_output->x;
if (crtc == NULL) *y = xwl_output->y;
return FALSE;
*x = crtc->x;
*y = crtc->y;
return TRUE; return TRUE;
} }
@ -289,8 +318,19 @@ xwlVidModeGetViewPort(ScreenPtr pScreen, int *x, int *y)
static Bool static Bool
xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode) xwlVidModeSwitchMode(ScreenPtr pScreen, DisplayModePtr mode)
{ {
/* Unsupported for now */ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
return FALSE; struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
RRModePtr rrmode;
if (!xwl_output)
return FALSE;
rrmode = xwl_output_find_mode(xwl_output, mode->HDisplay, mode->VDisplay);
if (rrmode == NULL)
return FALSE;
xwl_output_set_emulated_mode(xwl_output, GetCurrentClient(), rrmode, TRUE);
return TRUE;
} }
static Bool static Bool
@ -344,8 +384,10 @@ xwlVidModeAddModeline(ScreenPtr pScreen, DisplayModePtr mode)
static int static int
xwlVidModeGetNumOfModes(ScreenPtr pScreen) xwlVidModeGetNumOfModes(ScreenPtr pScreen)
{ {
/* We have only one mode */ struct xwl_screen *xwl_screen = xwl_screen_get(pScreen);
return 1; struct xwl_output *xwl_output = xwl_screen_get_first_output(xwl_screen);
return xwl_output ? xwl_output->randr_output->numModes : 0;
} }
static Bool static Bool