xserver: Branch 'master'
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Thu Feb 13 23:27:24 UTC 2025
hw/vfb/InitOutput.c | 191 ++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 143 insertions(+), 48 deletions(-)
New commits:
commit 7933cc24d0f4eae9009eaeaaaa1a791ebc9b3947
Author: Andy Myers <andy.myers at zetier.com>
Date: Fri Dec 6 15:16:50 2024 -0500
xvfb: Add multiple CRTC support
Multiple CRTCs can be added on a per-screen basis with the new -crtcs
option. Each CRTC has one associated output. Outputs beyond the first
are disabled by default and can be enabled by setting a mode. Outputs
can be disabled again by setting the associated CRTC's mode and output
to None.
Signed-off-by: Andy Myers <andy.myers at zetier.com>
Part-of: <https://gitlab.freedesktop.org/xorg/xserver/-/merge_requests/1749>
diff --git a/hw/vfb/InitOutput.c b/hw/vfb/InitOutput.c
index 773831afd..94a227b40 100644
--- a/hw/vfb/InitOutput.c
+++ b/hw/vfb/InitOutput.c
@@ -81,8 +81,17 @@ from The Open Group.
#define VFB_DEFAULT_WHITEPIXEL 1
#define VFB_DEFAULT_BLACKPIXEL 0
#define VFB_DEFAULT_LINEBIAS 0
+#define VFB_DEFAULT_NUM_CRTCS 1
#define XWD_WINDOW_NAME_LEN 60
+typedef struct {
+ int width;
+ int height;
+ int x;
+ int y;
+ int numOutputs;
+} vfbCrtcInfo, *vfbCrtcInfoPtr;
+
typedef struct {
int width;
int paddedBytesWidth;
@@ -92,6 +101,8 @@ typedef struct {
int bitsPerPixel;
int sizeInBytes;
int ncolors;
+ int numCrtcs;
+ vfbCrtcInfoPtr crtcs;
char *pfbMemory;
XWDColor *pXWDCmap;
XWDFileHeader *pXWDHeader;
@@ -140,6 +151,43 @@ static Bool Render = TRUE;
if (needswap) { CARD32 _s = _src; cpswapl(_s, _dst); } \
else _dst = _src;
+static void
+vfbAddCrtcInfo(vfbScreenInfoPtr screen, int numCrtcs)
+{
+ int i;
+ int count = numCrtcs - screen->numCrtcs;
+
+ if (count > 0) {
+ vfbCrtcInfoPtr crtcs =
+ reallocarray(screen->crtcs, numCrtcs, sizeof(*crtcs));
+ if (!crtcs)
+ FatalError("Not enough memory for %d CRTCs", numCrtcs);
+
+ memset(crtcs + screen->numCrtcs, 0, count * sizeof(*crtcs));
+
+ for (i = screen->numCrtcs; i < numCrtcs; ++i) {
+ crtcs[i].width = screen->width;
+ crtcs[i].height = screen->height;
+ }
+
+ screen->crtcs = crtcs;
+ screen->numCrtcs = numCrtcs;
+ }
+}
+
+static vfbScreenInfoPtr
+vfbInitializeScreenInfo(vfbScreenInfoPtr screen)
+{
+ *screen = defaultScreenInfo;
+ vfbAddCrtcInfo(screen, VFB_DEFAULT_NUM_CRTCS);
+
+ /* First CRTC initializes with one output */
+ if (screen->numCrtcs > 0)
+ screen->crtcs[0].numOutputs = 1;
+
+ return screen;
+}
+
static void
vfbInitializePixmapDepths(void)
{
@@ -196,6 +244,8 @@ freeScreenInfo(vfbScreenInfoPtr pvfb)
free(pvfb->pXWDHeader);
break;
}
+
+ free(pvfb->crtcs);
}
void
@@ -262,6 +312,9 @@ ddxUseMsg(void)
#ifdef MITSHM
ErrorF("-shmem put framebuffers in shared memory\n");
#endif
+
+ ErrorF("-crtcs n number of CRTCs per screen (default: %d)\n",
+ VFB_DEFAULT_NUM_CRTCS);
}
int
@@ -277,7 +330,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
}
if (lastScreen == -1)
- currentScreen = &defaultScreenInfo;
+ currentScreen = vfbInitializeScreenInfo(&defaultScreenInfo);
else
currentScreen = &vfbScreens[lastScreen];
@@ -301,7 +354,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
if (!vfbScreens)
FatalError("Not enough memory for screen %d\n", screenNum);
for (; vfbNumScreens <= screenNum; ++vfbNumScreens)
- vfbScreens[vfbNumScreens] = defaultScreenInfo;
+ vfbInitializeScreenInfo(&vfbScreens[vfbNumScreens]);
}
if (3 != sscanf(argv[i + 2], "%dx%dx%d",
@@ -382,6 +435,24 @@ ddxProcessArgument(int argc, char *argv[], int i)
}
#endif
+ if (strcmp(argv[i], "-crtcs") == 0) { /* -crtcs n */
+ int numCrtcs;
+
+ CHECK_FOR_REQUIRED_ARGUMENTS(1);
+ numCrtcs = atoi(argv[i + 1]);
+
+ if (numCrtcs < 1) {
+ ErrorF("Invalid number of CRTCs %d\n", numCrtcs);
+ UseMsg();
+ FatalError("Invalid number of CRTCs (%d) passed to -crtcs\n",
+ numCrtcs);
+
+ }
+
+ vfbAddCrtcInfo(currentScreen, numCrtcs);
+ return 2;
+ }
+
return 0;
}
@@ -785,10 +856,22 @@ vfbRRCrtcSet(ScreenPtr pScreen,
int x,
int y,
Rotation rotation,
- int numOutput,
+ int numOutputs,
RROutputPtr *outputs)
{
- return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutput, outputs);
+ vfbCrtcInfoPtr pvci = crtc->devPrivate;
+
+ if (pvci) {
+ if (mode) {
+ pvci->width = mode->mode.width;
+ pvci->height = mode->mode.height;
+ }
+
+ pvci->x = x;
+ pvci->y = y;
+ pvci->numOutputs = numOutputs;
+ }
+ return RRCrtcNotify(crtc, mode, x, y, rotation, NULL, numOutputs, outputs);
}
static Bool
@@ -804,17 +887,20 @@ static Bool
vfbRandRInit(ScreenPtr pScreen)
{
rrScrPrivPtr pScrPriv;
+
#if RANDR_12_INTERFACE
- RRModePtr mode;
- RRCrtcPtr crtc;
- RROutputPtr output;
+ RRModePtr mode;
+ RRCrtcPtr crtc;
+ RROutputPtr output;
xRRModeInfo modeInfo;
- char name[64];
+ char name[64];
+ int i;
+ vfbScreenInfoPtr pvfb = &vfbScreens[pScreen->myNum];
#endif
int mmWidth, mmHeight;
- if (!RRScreenInit (pScreen))
- return FALSE;
+ if (!RRScreenInit(pScreen))
+ return FALSE;
pScrPriv = rrGetScrPriv(pScreen);
pScrPriv->rrGetInfo = vfbRRGetInfo;
#if RANDR_12_INTERFACE
@@ -827,44 +913,53 @@ vfbRandRInit(ScreenPtr pScreen)
pScrPriv->rrOutputValidateMode = vfbRROutputValidateMode;
pScrPriv->rrModeDestroy = NULL;
- mmWidth = pScreen->width * 25.4 / monitorResolution;
- mmHeight = pScreen->height * 25.4 / monitorResolution;
-
- 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;
-
- /* This is to avoid xrandr to complain about the gamma missing */
- RRCrtcGammaSetSize (crtc, 256);
-
- 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;
- if (!RROutputSetPhysicalSize (output, mmWidth, mmHeight))
- return FALSE;
- RRCrtcNotify (crtc, mode, 0, 0, RR_Rotate_0, NULL, 1, &output);
+ RRScreenSetSizeRange(pScreen, 1, 1, pScreen->width, pScreen->height);
+
+ for (i = 0; i < pvfb->numCrtcs; i++) {
+ vfbCrtcInfoPtr pvci = &pvfb->crtcs[i];
+
+ mmWidth = pvci->width * 25.4 / monitorResolution;
+ mmHeight = pvci->height * 25.4 / monitorResolution;
+
+ crtc = RRCrtcCreate(pScreen, pvci);
+ if (!crtc)
+ return FALSE;
+
+ /* Set gamma to avoid xrandr complaints */
+ RRCrtcGammaSetSize(crtc, 256);
+
+ /* Setup an Output for each CRTC: 'screen' for the first, then 'screen_N' */
+ snprintf(name, sizeof(name), i == 0 ? "screen" : "screen_%d", i);
+ output = RROutputCreate(pScreen, name, strlen(name), NULL);
+ if (!output)
+ return FALSE;
+ if (!RROutputSetClones(output, NULL, 0))
+ return FALSE;
+ if (!RROutputSetCrtcs(output, &crtc, 1))
+ return FALSE;
+ if (!RROutputSetConnection(output, RR_Connected))
+ return FALSE;
+ if (!RROutputSetPhysicalSize(output, mmWidth, mmHeight))
+ return FALSE;
+
+ /* Setup a Mode and notify only for CRTCs with Outputs */
+ if (pvci->numOutputs > 0) {
+ snprintf(name, sizeof(name), "%dx%d", pvci->width, pvci->height);
+ memset(&modeInfo, '\0', sizeof(modeInfo));
+ modeInfo.width = pvci->width;
+ modeInfo.height = pvci->height;
+ modeInfo.nameLength = strlen(name);
+
+ mode = RRModeGet(&modeInfo, name);
+ if (!mode)
+ return FALSE;
+ if (!RROutputSetModes(output, &mode, 1, 0))
+ return FALSE;
+ if (!RRCrtcNotify(crtc, mode, pvci->x, pvci->y, RR_Rotate_0, NULL,
+ 1, &output))
+ return FALSE;
+ }
+ }
#endif
return TRUE;
}
More information about the xorg-commit
mailing list