Discussion:
[PATCH] xvfb: add randr support
Mike Frysinger
2013-01-12 17:55:58 UTC
Permalink
From: Lambros Lambrou <***@google.com>

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26391
Signed-off-by: Lambros Lambrou <***@google.com>
Signed-off-by: Mike Frysinger <***@gentoo.org>
---
hw/vfb/InitOutput.c | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 145 insertions(+)

diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c
index 97eccfd..672842f 100644
--- a/hw/vfb/InitOutput.c
+++ b/hw/vfb/InitOutput.c
@@ -66,6 +66,7 @@ from The Open Group.
#include "dix.h"
#include "miline.h"
#include "glx_extinit.h"
+#include "randrstr.h"

#define VFB_DEFAULT_WIDTH 1280
#define VFB_DEFAULT_HEIGHT 1024
@@ -785,6 +786,147 @@ vfbCloseScreen(ScreenPtr pScreen)
}

static Bool
+vfbRROutputValidateMode(ScreenPtr pScreen, RROutputPtr output, RRModePtr mode)
+{
+ rrScrPriv(pScreen);
+
+ if (pScrPriv->minWidth <= mode->mode.width &&
+ pScrPriv->maxWidth >= mode->mode.width &&
+ pScrPriv->minHeight <= mode->mode.height &&
+ pScrPriv->maxHeight >= mode->mode.height)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static Bool
+vfbRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
+ WindowPtr root = pScreen->root;
+ WindowPtr layer;
+ WindowPtr child;
+ BoxRec box;
+
+ pScreen->width = width;
+ pScreen->height = height;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
+
+ // Resize the root window & adjust its clipping
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT(pScreen, &root->winSize, &box, 1);
+ REGION_INIT(pScreen, &root->borderSize, &box, 1);
+ REGION_RESET(pScreen, &root->borderClip, &box);
+ root->drawable.width = pScreen->width;
+ root->drawable.height = pScreen->height;
+ REGION_BREAK(pScreen, &root->clipList);
+
+ // Update the clipping regions of all windows
+ for (child = root->firstChild; child; child = child->nextSib)
+ (*pScreen->MarkOverlappedWindows)(child, child, &layer);
+
+ if (root->firstChild)
+ (*pScreen->MarkOverlappedWindows)(root->firstChild,
+ root->firstChild,
+ NULL);
+ else
+ (*pScreen->MarkWindow)(root);
+
+ (*pScreen->ValidateTree)(root, NullWindow, VTOther);
+ (*pScreen->HandleExposures)(root);
+
+ // Reposition top-level windows to fit new root size
+ // XXX I assume this is what it does, but I'm not sure
+ ResizeChildrenWinSize(root, 0, 0, 0, 0);
+
+ // Check the pointer position
+ WindowsRestructured();
+
+ RRScreenSizeNotify(pScreen);
+ RRTellChanged(pScreen);
+
+ // Flush resulting events, etc to clients
+ FlushAllOutput();
+
+ return TRUE;
+}
+
+static Bool
+vfbRRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode, int x, int y,
+ Rotation rotation, int numOutput, RROutputPtr *outputs)
+{
+ return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput, outputs);
+}
+
+static Bool
+vfbRRGetInfo(ScreenPtr pScreen, Rotation *rotations)
+{
+ return TRUE;
+}
+
+static Bool
+vfbRandRInit(ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+#if RANDR_12_INTERFACE
+ RRModePtr mode;
+ RRCrtcPtr crtc;
+ RROutputPtr output;
+ xRRModeInfo modeInfo;
+ char name[64];
+#endif
+
+ if (!RRScreenInit(pScreen))
+ return FALSE;
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = vfbRRGetInfo;
+#if RANDR_12_INTERFACE
+ pScrPriv->rrCrtcSet = vfbRRCrtcSet;
+ pScrPriv->rrScreenSetSize = vfbRRScreenSetSize;
+ pScrPriv->rrOutputSetProperty = NULL;
+# if RANDR_13_INTERFACE
+ pScrPriv->rrOutputGetProperty = NULL;
+# endif
+ pScrPriv->rrOutputValidateMode = vfbRROutputValidateMode;
+ pScrPriv->rrModeDestroy = NULL;
+
+ RRScreenSetSizeRange(pScreen, 1, 1, pScreen->width, pScreen->height);
+
+ sprintf(name, "%dx%d", pScreen->width, pScreen->height);
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+ modeInfo.width = pScreen->width;
+ modeInfo.height = pScreen->height;
+ modeInfo.nameLength = strlen(name);
+
+ mode = RRModeGet(&modeInfo, name);
+ if (!mode)
+ return FALSE;
+
+ crtc = RRCrtcCreate(pScreen, NULL);
+ if (!crtc)
+ return FALSE;
+
+ output = RROutputCreate(pScreen, "screen", 6, NULL);
+ if (!output)
+ return FALSE;
+ if (!RROutputSetClones(output, NULL, 0))
+ return FALSE;
+ if (!RROutputSetModes(output, &mode, 1, 0))
+ return FALSE;
+ if (!RROutputSetCrtcs(output, &crtc, 1))
+ return FALSE;
+ if (!RROutputSetConnection(output, RR_Connected))
+ return FALSE;
+ RRCrtcNotify(crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
+#endif
+ return TRUE;
+}
+
+static Bool
vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
{
vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
@@ -860,6 +1002,9 @@ vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!ret)
return FALSE;

+ if (!vfbRandRInit(pScreen))
+ return FALSE;
+
pScreen->InstallColormap = vfbInstallColormap;
pScreen->UninstallColormap = vfbUninstallColormap;
pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
--
1.8.0.2
Michal Srb
2013-06-07 14:30:28 UTC
Permalink
Post by Mike Frysinger
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26391
---
hw/vfb/InitOutput.c | 145
++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 145
insertions(+)
diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c
index 97eccfd..672842f 100644
--- a/hw/vfb/InitOutput.c
+++ b/hw/vfb/InitOutput.c
@@ -66,6 +66,7 @@ from The Open Group.
#include "dix.h"
#include "miline.h"
#include "glx_extinit.h"
+#include "randrstr.h"
#define VFB_DEFAULT_WIDTH 1280
#define VFB_DEFAULT_HEIGHT 1024
@@ -785,6 +786,147 @@ vfbCloseScreen(ScreenPtr pScreen)
}
static Bool
+vfbRROutputValidateMode(ScreenPtr pScreen, RROutputPtr output, RRModePtr
mode) +{
+ rrScrPriv(pScreen);
+
+ if (pScrPriv->minWidth <= mode->mode.width &&
+ pScrPriv->maxWidth >= mode->mode.width &&
+ pScrPriv->minHeight <= mode->mode.height &&
+ pScrPriv->maxHeight >= mode->mode.height)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static Bool
+vfbRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
+ WindowPtr root = pScreen->root;
+ WindowPtr layer;
+ WindowPtr child;
+ BoxRec box;
+
+ pScreen->width = width;
+ pScreen->height = height;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
+
+ // Resize the root window & adjust its clipping
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+ REGION_INIT(pScreen, &root->winSize, &box, 1);
+ REGION_INIT(pScreen, &root->borderSize, &box, 1);
+ REGION_RESET(pScreen, &root->borderClip, &box);
+ root->drawable.width = pScreen->width;
+ root->drawable.height = pScreen->height;
+ REGION_BREAK(pScreen, &root->clipList);
+
+ // Update the clipping regions of all windows
+ for (child = root->firstChild; child; child = child->nextSib)
+ (*pScreen->MarkOverlappedWindows)(child, child, &layer);
+
+ if (root->firstChild)
+ (*pScreen->MarkOverlappedWindows)(root->firstChild,
+ root->firstChild,
+ NULL);
+ else
+ (*pScreen->MarkWindow)(root);
+
+ (*pScreen->ValidateTree)(root, NullWindow, VTOther);
+ (*pScreen->HandleExposures)(root);
+
+ // Reposition top-level windows to fit new root size
+ // XXX I assume this is what it does, but I'm not sure
+ ResizeChildrenWinSize(root, 0, 0, 0, 0);
+
+ // Check the pointer position
+ WindowsRestructured();
+
+ RRScreenSizeNotify(pScreen);
+ RRTellChanged(pScreen);
+
+ // Flush resulting events, etc to clients
+ FlushAllOutput();
+
+ return TRUE;
+}
+
+static Bool
+vfbRRCrtcSet(ScreenPtr pScreen, RRCrtcPtr crtc, RRModePtr mode, int x, int
y, + Rotation rotation, int numOutput, RROutputPtr *outputs) +{
+ return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput,
outputs); +}
+
+static Bool
+vfbRRGetInfo(ScreenPtr pScreen, Rotation *rotations)
+{
+ return TRUE;
+}
+
+static Bool
+vfbRandRInit(ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+#if RANDR_12_INTERFACE
+ RRModePtr mode;
+ RRCrtcPtr crtc;
+ RROutputPtr output;
+ xRRModeInfo modeInfo;
+ char name[64];
+#endif
+
+ if (!RRScreenInit(pScreen))
+ return FALSE;
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = vfbRRGetInfo;
+#if RANDR_12_INTERFACE
+ pScrPriv->rrCrtcSet = vfbRRCrtcSet;
+ pScrPriv->rrScreenSetSize = vfbRRScreenSetSize;
+ pScrPriv->rrOutputSetProperty = NULL;
+# if RANDR_13_INTERFACE
+ pScrPriv->rrOutputGetProperty = NULL;
+# endif
+ pScrPriv->rrOutputValidateMode = vfbRROutputValidateMode;
+ pScrPriv->rrModeDestroy = NULL;
+
+ RRScreenSetSizeRange(pScreen, 1, 1, pScreen->width, pScreen->height);
+
+ sprintf(name, "%dx%d", pScreen->width, pScreen->height);
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+ modeInfo.width = pScreen->width;
+ modeInfo.height = pScreen->height;
+ modeInfo.nameLength = strlen(name);
+
+ mode = RRModeGet(&modeInfo, name);
+ if (!mode)
+ return FALSE;
+
+ crtc = RRCrtcCreate(pScreen, NULL);
+ if (!crtc)
+ return FALSE;
+
+ output = RROutputCreate(pScreen, "screen", 6, NULL);
+ if (!output)
+ return FALSE;
+ if (!RROutputSetClones(output, NULL, 0))
+ return FALSE;
+ if (!RROutputSetModes(output, &mode, 1, 0))
+ return FALSE;
+ if (!RROutputSetCrtcs(output, &crtc, 1))
+ return FALSE;
+ if (!RROutputSetConnection(output, RR_Connected))
+ return FALSE;
+ RRCrtcNotify(crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
+#endif
+ return TRUE;
+}
+
+static Bool
vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
{
vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
@@ -860,6 +1002,9 @@ vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!ret)
return FALSE;
+ if (!vfbRandRInit(pScreen))
+ return FALSE;
+
pScreen->InstallColormap = vfbInstallColormap;
pScreen->UninstallColormap = vfbUninstallColormap;
pScreen->ListInstalledColormaps = vfbListInstalledColormaps;
Any comments to this one?

Tested-By: Michal Srb <***@suse.cz>

Michal Srb
Keith Packard
2013-06-07 16:46:55 UTC
Permalink
Post by Mike Frysinger
+static Bool
+vfbRRScreenSetSize(ScreenPtr pScreen, CARD16 width, CARD16 height,
+ CARD32 mmWidth, CARD32 mmHeight)
+{
This can be a whole lot shorter if you use SetRootClip, take a look at
hw/xwin/winrandr.c. Should be something like

SetRootClip(pScreen, FALSE);

pScreen->width = width;
pScreen->height = height;
pScreen->mmWidth = mmWidth;
pScreen->mmHeight = mmHeight;

SetRootClip(pScreen, TRUE);

RRScreenSizeNotify(pScreen);

Other than that, this looks fine to me!
--
***@intel.com
Michal Srb
2013-06-12 15:11:52 UTC
Permalink
From: Lambros Lambrou <***@google.com>

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=26391
Signed-off-by: Lambros Lambrou <***@google.com>
Signed-off-by: Mike Frysinger <***@gentoo.org>
Signed-off-by: Michal Srb <***@suse.com>
---
Second version, modified according to Keith suggestion.
Tested by adding second mode and switching - worked correctly.

diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c
index 97eccfd..bfca068 100644
--- a/hw/vfb/InitOutput.c
+++ b/hw/vfb/InitOutput.c
@@ -66,6 +66,7 @@ from The Open Group.
#include "dix.h"
#include "miline.h"
#include "glx_extinit.h"
+#include "randrstr.h"

#define VFB_DEFAULT_WIDTH 1280
#define VFB_DEFAULT_HEIGHT 1024
@@ -785,6 +786,125 @@ vfbCloseScreen(ScreenPtr pScreen)
}

static Bool
+vfbRROutputValidateMode(ScreenPtr pScreen,
+ RROutputPtr output,
+ RRModePtr mode)
+{
+ rrScrPriv(pScreen);
+
+ if (pScrPriv->minWidth <= mode->mode.width &&
+ pScrPriv->maxWidth >= mode->mode.width &&
+ pScrPriv->minHeight <= mode->mode.height &&
+ pScrPriv->maxHeight >= mode->mode.height)
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static Bool
+vfbRRScreenSetSize(ScreenPtr pScreen,
+ CARD16 width,
+ CARD16 height,
+ CARD32 mmWidth,
+ CARD32 mmHeight)
+{
+ // Prevent screen updates while we change things around
+ SetRootClip(pScreen, FALSE);
+
+ pScreen->width = width;
+ pScreen->height = height;
+ pScreen->mmWidth = mmWidth;
+ pScreen->mmHeight = mmHeight;
+
+ // Restore the ability to update screen, now with new dimensions
+ SetRootClip(pScreen, TRUE);
+
+ RRScreenSizeNotify (pScreen);
+ RRTellChanged(pScreen);
+
+ return TRUE;
+}
+
+static Bool
+vfbRRCrtcSet(ScreenPtr pScreen,
+ RRCrtcPtr crtc,
+ RRModePtr mode,
+ int x,
+ int y,
+ Rotation rotation,
+ int numOutput,
+ RROutputPtr *outputs)
+{
+ return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput, outputs);
+}
+
+static Bool
+vfbRRGetInfo(ScreenPtr pScreen, Rotation *rotations)
+{
+ return TRUE;
+}
+
+static Bool
+vfbRandRInit(ScreenPtr pScreen)
+{
+ rrScrPrivPtr pScrPriv;
+#if RANDR_12_INTERFACE
+ RRModePtr mode;
+ RRCrtcPtr crtc;
+ RROutputPtr output;
+ xRRModeInfo modeInfo;
+ char name[64];
+#endif
+
+ if (!RRScreenInit (pScreen))
+ return FALSE;
+ pScrPriv = rrGetScrPriv(pScreen);
+ pScrPriv->rrGetInfo = vfbRRGetInfo;
+#if RANDR_12_INTERFACE
+ pScrPriv->rrCrtcSet = vfbRRCrtcSet;
+ pScrPriv->rrScreenSetSize = vfbRRScreenSetSize;
+ pScrPriv->rrOutputSetProperty = NULL;
+#if RANDR_13_INTERFACE
+ pScrPriv->rrOutputGetProperty = NULL;
+#endif
+ pScrPriv->rrOutputValidateMode = vfbRROutputValidateMode;
+ pScrPriv->rrModeDestroy = NULL;
+
+ RRScreenSetSizeRange (pScreen,
+ 1, 1,
+ pScreen->width, pScreen->height);
+
+ sprintf (name, "%dx%d", pScreen->width, pScreen->height);
+ memset (&modeInfo, '\0', sizeof (modeInfo));
+ modeInfo.width = pScreen->width;
+ modeInfo.height = pScreen->height;
+ modeInfo.nameLength = strlen (name);
+
+ mode = RRModeGet (&modeInfo, name);
+ if (!mode)
+ return FALSE;
+
+ crtc = RRCrtcCreate (pScreen, NULL);
+ if (!crtc)
+ return FALSE;
+
+ output = RROutputCreate (pScreen, "screen", 6, NULL);
+ if (!output)
+ return FALSE;
+ if (!RROutputSetClones (output, NULL, 0))
+ return FALSE;
+ if (!RROutputSetModes (output, &mode, 1, 0))
+ return FALSE;
+ if (!RROutputSetCrtcs (output, &crtc, 1))
+ return FALSE;
+ if (!RROutputSetConnection (output, RR_Connected))
+ return FALSE;
+ RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
+#endif
+ return TRUE;
+}
+
+static Bool
vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
{
vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
@@ -860,6 +980,9 @@ vfbScreenInit(ScreenPtr pScreen, int argc, char **argv)
if (!ret)
return FALSE;

+ if (!vfbRandRInit(pScreen))
+ return FALSE;
+
pScreen->InstallColormap = vfbInstallColormap;
pScreen->UninstallColormap = vfbUninstallColormap;
pScreen->ListInstalledColormaps = vfbListInstalledColormaps;

Loading...