[PATCH 2/2 xf86-video-impact] Virtual screen

peter fuerst post at pfrst.de
Tue Sep 6 13:47:49 PDT 2011



Hello,

here comes the 2nd of two patches (to be applied in order) for updating
the SGI Impact video driver for the Xorg X server.

with kind regards

peter

(PS: sorry for being that late ;-)

---

This patch enables the use of a virtual screen with XImpact by mmap'ing the
shadow-framebuffer according - within limits - to the requested virtualX/
virtualY values, and by implementing ImpactAdjustFrame().
The virtual resolution is just limited by the available shadow-framebuffer
(DMA-pool) size:
- The kernel mmap's at most 16MB (e.g. 2048x2048 Pixels @ 32bpp) for one
   DMA-pool.
- For Indigo2 this memory had to be restricted to 12MB (e.g. 1772x1772
   Pixels @ 32bpp)


Signed-off-by: peter fuerst <post at pfrst.de>

---

  xorg/driver/xf86-video-impact/src/impact.h        |    1 +
  xorg/driver/xf86-video-impact/src/impact_driver.c |   37 +++++++++++-----
  xorg/driver/xf86-video-impact/src/impact_shadow.c |  115 +++++++++++++++++++++++++++++++-------------------
  3 files changed, 98 insertions(+), 55 deletions(-)


diff --git a/src/impact.h b/src/impact.h
index ce6b148..97ceca9 100644
--- a/xorg/driver/xf86-video-impact/src/impact.h	Thu Jul 21 03:39:43 2011
+++ b/xorg/driver/xf86-video-impact/src/impact.h	Sun Sep  4 22:35:24 2011
@@ -125,6 +125,7 @@ void ImpactBackupRex(ScrnInfoPtr);
  void ImpactRestoreRex(ScrnInfoPtr);
  void ImpactBackupXmap(ScrnInfoPtr);
  void ImpactRestoreXmap(ScrnInfoPtr);
+void ImpactAdjustFrame(int, int, int, int);

  /* newort_cmap.c */
  static __inline__ unsigned


diff --git a/src/impact_driver.c b/src/impact_driver.c
index cb16b4a..0d11ab6 100644
--- a/xorg/driver/xf86-video-impact/src/impact_driver.c	Sun Jul 24 21:37:47 2011
+++ b/xorg/driver/xf86-video-impact/src/impact_driver.c	Mon Sep  5 03:36:25 2011
@@ -270,6 +270,7 @@ ImpactProbe(DriverPtr drv, int flags)
  					pScrn->ScreenInit = ImpactScreenInit;
  					pScrn->EnterVT = ImpactEnterVT;
  					pScrn->LeaveVT = ImpactLeaveVT;
+					pScrn->AdjustFrame = ImpactAdjustFrame;
  					pScrn->driverPrivate =
  						(void*)(busID | (long)probedIDs[j].ip<<16);
  					foundScreen = TRUE;
@@ -401,7 +402,14 @@ ImpactPreInit(ScrnInfoPtr pScrn, int flags)
  	xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pImpact->Options);

  	/* Set fields in ScreenInfoRec && ImpactRec */
-	pScrn->videoRam = IMPACT_FIXED_W_SCRN * (pScrn->bitsPerPixel >> 3);
+	if (!(i = pScrn->display->virtualX * pScrn->display->virtualY))
+		i = IMPACT_FIXED_W_SCRN * IMPACT_FIXED_H_SCRN;
+	/* ...and round up to full (4k-)pages. */
+	pScrn->videoRam = (i * (pScrn->bitsPerPixel / 8) / 1024 + 3) & ~3;
+
+	/* Hmm, the I2-card hangs with more than 3k DMA-pages... */
+	if (!IMPACTSR(pImpact) && pScrn->videoRam > 3*4096)
+		pScrn->videoRam = 3*4096;

  	/* get revisions of REX3, etc. */
  	if ( !ImpactMapRegs(pScrn) )
@@ -454,8 +462,8 @@ ImpactPreInit(ScrnInfoPtr pScrn, int flags)
  	i = xf86ValidateModes(
  			pScrn, pScrn->monitor->Modes,
  			pScrn->display->modes, clockRanges,
-			NULL, 256, 2048,
-			pScrn->bitsPerPixel, 128, 2048,
+			NULL, IMPACT_FIXED_W_SCRN, 2048,
+			pScrn->bitsPerPixel, IMPACT_FIXED_H_SCRN, 2048,
  			pScrn->display->virtualX,
  			pScrn->display->virtualY,
  			pScrn->videoRam * 1024,
@@ -811,13 +819,16 @@ ImpactMapRegs(ScrnInfoPtr pScrn)
  		ErrorF("ImpactMapRegs: failed to open /dev/fb%d (%s)\n",
  			pImpact->busID , strerror(errno));
  	else {
-		size_t size = IMPACTSR(pImpact) ? 0x200000:sizeof(ImpactI2Regs);
+		unsigned size = IMPACTSR(pImpact) ? sizeof(ImpactSRRegs):sizeof(ImpactI2Regs);
  		pImpact->pImpactRegs =
  			mmap((void*)0, size, PROT_READ|PROT_WRITE,
  				MAP_SHARED, pImpact->devFD, 0);
-		if (MAP_FAILED == pImpact->pImpactRegs) {
+		if (pImpact->pImpactRegs != MAP_FAILED)
+			ErrorF("ImpactMapRegs: mapped %u B @ %p\n",
+				size, pImpact->pImpactRegs);
+		else {
  			ErrorF("ImpactMapRegs: Could not mmap card registers"
-				" (0x%08lx,0x%x) (%s)\n", 0, size, strerror(errno));
+				" (%p,0x%x) (%s)\n", (void*)0, size, strerror(errno));
  			pImpact->pImpactRegs = 0;
  		}
  	}
@@ -837,11 +848,15 @@ ImpactMapShadowFB(ScrnInfoPtr pScrn)
  		ErrorF("ImpactMapShadowFB: failed to open fb-dev\n");
  	else {
  		pImpact->ShadowPtr =
-			mmap((void*)0, 0x800000, PROT_READ|PROT_WRITE,
+			mmap((void*)0, 1024*pScrn->videoRam, PROT_READ|PROT_WRITE,
  				MAP_SHARED, pImpact->devFD, IMPACT_FB_MMAP_OFF(3));
-		if (MAP_FAILED == pImpact->ShadowPtr) {
+		if (pImpact->ShadowPtr != MAP_FAILED)
+			ErrorF("ImpactMapShadowFB: mapped %ukB @ %p\n",
+				pScrn->videoRam, pImpact->ShadowPtr);
+		else {
  			ErrorF("ImpactMapShadowFB: Could not mmap shadow buffer"
-				" (0x%08lx,0x800000) (%s)\n", IMPACT_FB_MMAP_OFF(3), strerror(errno));
+				" (%p,0x%xkB) (%s)\n", (void*)IMPACT_FB_MMAP_OFF(3),
+				pScrn->videoRam, strerror(errno));
  			pImpact->ShadowPtr = 0;
  		}
  	}
@@ -853,7 +868,7 @@ static void
  ImpactUnmapRegs(ScrnInfoPtr pScrn)
  {
  	ImpactPtr pImpact = IMPACTPTR(pScrn);
-	size_t size = IMPACTSR(pImpact) ? 0x200000:sizeof(ImpactI2Regs);
+	unsigned size = IMPACTSR(pImpact) ? sizeof(ImpactSRRegs):sizeof(ImpactI2Regs);

  	if (pImpact->pImpactRegs)
  		munmap( pImpact->pImpactRegs, size );
@@ -867,7 +882,7 @@ ImpactUnmapShadowFB(ScrnInfoPtr pScrn)
  	ImpactPtr pImpact = IMPACTPTR(pScrn);

  	if (pImpact->ShadowPtr)
-		munmap( pImpact->ShadowPtr, 0x800000 );
+		munmap( pImpact->ShadowPtr, 1024*pScrn->videoRam );
  	pImpact->ShadowPtr = 0;
  }



diff --git a/src/impact_shadow.c b/src/impact_shadow.c
index 6bc711e..9aacc4e 100644
--- a/xorg/driver/xf86-video-impact/src/impact_shadow.c	Wed Jul 27 21:59:04 2011
+++ b/xorg/driver/xf86-video-impact/src/impact_shadow.c	Mon Sep  5 02:11:26 2011
@@ -32,16 +32,15 @@ int ImpactDepth24Flags(void)
   * Common sanity check and adjustment for all ImpactRefreshArea...
   */
  static __inline__ int
-ImpactAdjRefreshBox(const BoxPtr obox, BoxPtr nbox)
+ImpactAdjRefreshBox(BoxPtr box, int x0, int y0)
  {
  	/*
  	 * NB: Box defines [x1,x2[ x [x2,y2[, not [x1,x2] x [x2,y2] !
  	 */
-	*nbox = *obox;
-	if (nbox->x1 < 0) nbox->x1 = 0;
-	if (nbox->y1 < 0) nbox->y1 = 0;
-	if (IMPACT_FIXED_W_SCRN < nbox->x2) nbox->x2 = IMPACT_FIXED_W_SCRN;
-	if (IMPACT_FIXED_H_SCRN < nbox->y2) nbox->y2 = IMPACT_FIXED_H_SCRN;
+	if (box->x1 < x0) box->x1 = x0;
+	if (box->y1 < y0) box->y1 = y0;
+	if (x0 + IMPACT_FIXED_W_SCRN < box->x2) box->x2 = x0 + IMPACT_FIXED_W_SCRN;
+	if (y0 + IMPACT_FIXED_H_SCRN < box->y2) box->y2 = y0 + IMPACT_FIXED_H_SCRN;
  	/*
  	 * We may need to do some adjustment, since
  	 * 1) the actual number of pixels *must* match the settings
@@ -49,9 +48,9 @@ ImpactAdjRefreshBox(const BoxPtr obox, BoxPtr nbox)
  	 * 2) we draw pairs of pixels.
  	 * Otherwise... (try it :))
  	 */
-	nbox->x1 &= ~1;
-	nbox->x2 = ++nbox->x2 & ~1;
-	return (nbox->x2 <= nbox->x1 || nbox->y2 <= nbox->y1);
+	box->x1 &= ~1;
+	box->x2 = ++box->x2 & ~1;
+	return (box->x2 <= box->x1 || box->y2 <= box->y1);
  }


@@ -59,20 +58,20 @@ ImpactAdjRefreshBox(const BoxPtr obox, BoxPtr nbox)
   * Common per-box-prologue for PIO-version of ImpactRefreshArea*
   */
  static __inline__ int
-ImpactPreRefreshBoxPIO(mgicfifo_t *cfifo, const BoxPtr obox, BoxPtr nbox)
+ImpactPreRefreshBoxPIO(mgicfifo_t *cfifo, BoxPtr box, int x0, int y0)
  {
  	int h, w, i;

-	if (ImpactAdjRefreshBox(obox, nbox))
+	if (ImpactAdjRefreshBox(box, x0, y0))
  		return 0;

-	w = nbox->x2 - nbox->x1;
-	h = nbox->y2 - nbox->y1;
+	w = box->x2 - box->x1;
+	h = box->y2 - box->y1;

  	/* setup PIO to RE */
  	impact_cmd_pp1fillmode(cfifo, 0x6300, IMPACT_LO_COPY);
-	impact_cmd_blockxystarti(cfifo, nbox->x1, nbox->y1);
-	impact_cmd_blockxyendi(cfifo, nbox->x2-1, nbox->y2-1);
+	impact_cmd_blockxystarti(cfifo, box->x1-x0, box->y1-y0);
+	impact_cmd_blockxyendi(cfifo, box->x2-x0-1, box->y2-y0-1);
  	impact_cmd_fillmode(cfifo, 0x00c00000);
  	impact_cmd_xfrmode(cfifo, 0x00080);
  	impact_cmd_xfrsize(cfifo, w, h);
@@ -103,8 +102,11 @@ ImpactPostRefreshBoxPIO(mgicfifo_t *cfifo)
   * into 32-bpp values from the current palette in software.
   */
  static void
-ImpactRefreshArea8(ImpactPtr pImpact, mgicfifo_t *cfifo, int num, BoxPtr pbox)
+ImpactRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
+	ImpactPtr pImpact = IMPACTPTR(pScrn);
+	mgicfifo_t *cfifo = IMPACTSR(pImpact) ?
+		&pImpact->pImpactRegs->sr.cfifo:&pImpact->pImpactRegs->i2.cfifo;
  	unsigned pal[256];
  	int i;

@@ -112,14 +114,15 @@ ImpactRefreshArea8(ImpactPtr pImpact, mgicfifo_t *cfifo, int num, BoxPtr pbox)
  		pal[i] = ImpactGetPalReg(pImpact, i);

  	for (; num--; pbox++) {
-		BoxRec sanebox;
+		BoxRec sanebox = *pbox;
  		unsigned char *base;
  		int dy;
  		TRACEV("ImpactRefreshArea8: %d [%d..%d[x[%d..%d[\n",
  				num, pbox->x1,pbox->x2, pbox->y1,pbox->y2 );

  		(*pImpact->WaitCfifoEmpty)(pImpact->pImpactRegs);
-		if (ImpactPreRefreshBoxPIO(cfifo,pbox,&sanebox) <= 0)
+		if (ImpactPreRefreshBoxPIO(cfifo,&sanebox,
+				pScrn->frameX0, pScrn->frameY0) <= 0)
  			continue;

  		base = (unsigned char*)pImpact->ShadowPtr 
@@ -144,23 +147,13 @@ ImpactRefreshArea8(ImpactPtr pImpact, mgicfifo_t *cfifo, int num, BoxPtr pbox)
  void
  ImpactI2RefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
-	if (num > 0)
-	{	ImpactPtr pImpact = IMPACTPTR(pScrn);
-		ImpactRegsPtr pImpactRegs = pImpact->pImpactRegs;
-
-		ImpactRefreshArea8(pImpact, &pImpactRegs->i2.cfifo, num, pbox);
-	}
+	if (num > 0) ImpactRefreshArea8(pScrn, num, pbox);
  }

  void
  ImpactSRRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
-	if (num > 0)
-	{	ImpactPtr pImpact = IMPACTPTR(pScrn);
-		ImpactRegsPtr pImpactRegs = pImpact->pImpactRegs;
-
-		ImpactRefreshArea8(pImpact, &pImpactRegs->sr.cfifo, num, pbox);
-	}
+	if (num > 0) ImpactRefreshArea8(pScrn, num, pbox);
  }


@@ -247,7 +240,8 @@ ImpactI2FindCflushmode(ImpactPtr pImpact)


  static __inline__ int
-ImpactRefreshBoxDMA(int isSR, mgicfifo_t *cfifo, BoxPtr box, unsigned bpitch)
+ImpactRefreshBoxDMA(int isSR, mgicfifo_t *cfifo, BoxPtr box, unsigned bpitch,
+	int x0, int y0)
  {
  	int w = box->x2 - box->x1;
  	int h = box->y2 - box->y1;
@@ -262,8 +256,8 @@ ImpactRefreshBoxDMA(int isSR, mgicfifo_t *cfifo, BoxPtr box, unsigned bpitch)
  	impact_cmd_packedcolor(cfifo, 0);
  	impact_cmd_red(cfifo, 0);
  	impact_cmd_drbpointers(cfifo, 0xc8240);
-	impact_cmd_blockxystarti(cfifo, box->x1, box->y1);
-	impact_cmd_blockxyendi(cfifo, box->x2-1, box->y2-1);
+	impact_cmd_blockxystarti(cfifo, box->x1-x0, box->y1-y0);
+	impact_cmd_blockxyendi(cfifo, box->x2-x0-1, box->y2-y0-1);
  	impact_cmd_fillmode(cfifo, 0x01400000);
  	impact_cmd_xfrmode(cfifo, 0x00080);
  	impact_cmd_hq_pixelformat(cfifo, 0x600);
@@ -308,19 +302,20 @@ ImpactPostRefreshBoxDMA(mgicfifo_t *cfifo)


  static void
-ImpactRefreshArea32DMA(ImpactPtr pImpact, int num, BoxPtr pbox)
+ImpactRefreshArea32DMA(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
+	ImpactPtr pImpact = IMPACTPTR(pScrn);
  	ImpactRegsPtr pImpactRegs = pImpact->pImpactRegs;
  	mgicfifo_t *cfifo =
  		IMPACTSR(pImpact) ? &pImpactRegs->sr.cfifo:&pImpactRegs->i2.cfifo;
  	unsigned bpitch = pImpact->ShadowPitch;

  	for (; num-- > 0; pbox++) {
-		BoxRec sanebox;
+		BoxRec sanebox = *pbox;
  		TRACEV("ImpactRefreshArea32: %d [%d..%d]x[%d..%d]\n",
  			num, pbox->x1,pbox->x2, pbox->y1,pbox->y2);

-		if (ImpactAdjRefreshBox(pbox, &sanebox))
+		if (ImpactAdjRefreshBox(&sanebox, pScrn->frameX0, pScrn->frameY0))
  			continue;

  		if (pImpact->FlushBoxCache)
@@ -328,7 +323,8 @@ ImpactRefreshArea32DMA(ImpactPtr pImpact, int num, BoxPtr pbox)
  						&sanebox, bpitch);

  		(*pImpact->WaitDMAOver)(pImpactRegs);
-		ImpactRefreshBoxDMA(IMPACTSR(pImpact), cfifo, &sanebox, bpitch);
+		ImpactRefreshBoxDMA(IMPACTSR(pImpact), cfifo, &sanebox, bpitch,
+			pScrn->frameX0, pScrn->frameY0);
  		(*pImpact->WaitDMAOver)(pImpactRegs);
  		ImpactPostRefreshBoxDMA(cfifo);
  	}
@@ -341,22 +337,24 @@ ImpactRefreshArea32DMA(ImpactPtr pImpact, int num, BoxPtr pbox)
   * for very small boxes or boxes, no wider than about a dozen pixels.
   */
  static void
-ImpactRefreshArea32PIO(ImpactPtr pImpact, int num, BoxPtr pbox)
+ImpactRefreshArea32PIO(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
+	ImpactPtr pImpact = IMPACTPTR(pScrn);
  	ImpactRegsPtr pImpactRegs = pImpact->pImpactRegs;
  	mgicfifo_t *cfifo =
  		IMPACTSR(pImpact) ? &pImpactRegs->sr.cfifo:&pImpactRegs->i2.cfifo;
  	unsigned bpitch = pImpact->ShadowPitch;

  	for (; num--; pbox++) {
-		BoxRec sanebox;
+		BoxRec sanebox = *pbox;
  		unsigned char* base;
  		int dy;
  		TRACEV("ImpactRefreshArea32 PIO: %d [%d..%d[x[%d..%d[\n",
  				num, pbox->x1,pbox->x2, pbox->y1,pbox->y2 );

  		(*pImpact->WaitCfifoEmpty)(pImpactRegs);
-		if (ImpactPreRefreshBoxPIO(cfifo,pbox,&sanebox) <= 0)
+		if (ImpactPreRefreshBoxPIO(cfifo,&sanebox,
+				pScrn->frameX0, pScrn->frameY0) <= 0)
  			continue;

  		base = (unsigned char*)pImpact->ShadowPtr
@@ -406,9 +404,9 @@ ImpactIP28RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  			if (w < lim[h]) pio = 1;
  		}
  		if (pio)
-			ImpactRefreshArea32PIO(pImpact, 1, pbox);
+			ImpactRefreshArea32PIO(pScrn, 1, pbox);
  		else
-			ImpactRefreshArea32DMA(pImpact, 1, pbox);
+			ImpactRefreshArea32DMA(pScrn, 1, pbox);
  	}
  }

@@ -420,13 +418,42 @@ ImpactIP28RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  void
  ImpactIP22RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
-	ImpactRefreshArea32DMA(IMPACTPTR(pScrn), num, pbox);
+	ImpactRefreshArea32DMA(pScrn, num, pbox);
  }

  void
  ImpactSRRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
-	ImpactRefreshArea32DMA(IMPACTPTR(pScrn), num, pbox);
+	ImpactRefreshArea32DMA(pScrn, num, pbox);
+}
+
+void
+ImpactAdjustFrame(int scrnIndex, int x, int y, int flags)
+{
+	static int x0, y0;
+	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
+	ImpactPtr pImpact = IMPACTPTR(pScrn);
+
+	/* Pan by reasonable steps. */
+	pScrn->frameX0 = x &= ~7;
+	pScrn->frameY0 = y &= ~7;
+
+	if (x != x0 || y != y0) {
+		BoxRec all;
+		void (*rf)(ScrnInfoPtr, int, BoxPtr) =
+			1 == pImpact->Bpp ? pImpact->RefreshArea8:pImpact->RefreshArea32;
+		void (*cf)(int,char*,BoxPtr,unsigned) = pImpact->FlushBoxCache;
+
+		x0 = all.x1 = x; all.x2 = x + IMPACT_FIXED_W_SCRN;
+		y0 = all.y1 = y; all.y2 = y + IMPACT_FIXED_H_SCRN;
+
+		/* Since framebuffer is unchanged, avoid cache-flush overhead. */
+		pImpact->FlushBoxCache = 0;
+		/* This takes about 36ms (DMA) to 366ms (PIO) on a IP28/195MHz. */
+		(*rf)(pScrn, 1, &all);
+		pImpact->FlushBoxCache = cf;
+	}
+
  }

  /* eof */

*** eof ***


More information about the xorg-devel mailing list