[PATCH xf86-video-cirrus] Add basic EXA acceleration for the alpine driver.

Matthieu Herrb matthieu.herrb at laas.fr
Mon Jun 10 13:12:17 PDT 2013


This provides only SolidFill and Copy acceleration, like XAA did.

Signed-off-by: Matthieu Herrb <matthieu.herrb at laas.fr>
---
 configure.ac     |  40 +++++++
 src/Makefile.am  |   9 +-
 src/alp.h        |   4 +
 src/alp_driver.c |  36 +++++-
 src/alp_exa.c    | 330 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/cir.h        |   7 ++
 6 files changed, 419 insertions(+), 7 deletions(-)
 create mode 100644 src/alp_exa.c

diff --git configure.ac configure.ac
index 9b3dcac..53309d6 100644
--- configure.ac
+++ configure.ac
@@ -89,6 +89,46 @@ AC_MSG_CHECKING([whether to include XAA support])
 AM_CONDITIONAL(XAA, test "x$XAA" = xyes)
 AC_MSG_RESULT([$XAA])
 
+AC_ARG_ENABLE(exa, AS_HELP_STRING([--disable-exa],
+				  [Disable EXA support [[default=enabled]]]),
+              [EXA="$enableval"],
+              [EXA=yes])
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $XORG_CFLAGS"
+# Properly handle EXA.
+AC_MSG_CHECKING([whether to enable EXA support])
+if test "x$EXA" = xyes; then
+        AC_MSG_RESULT(yes)
+
+        SAVE_CPPFLAGS="$CPPFLAGS"
+        CPPFLAGS="$CPPFLAGS $XORG_CFLAGS"
+        AC_CHECK_HEADER(exa.h,
+                       [have_exa_h="yes"], [have_exa_h="no"])
+        CPPFLAGS="$SAVE_CPPFLAGS"
+else
+        AC_MSG_RESULT(no)
+fi
+
+SAVE_CPPFLAGS="$CPPFLAGS"
+CPPFLAGS="$CPPFLAGS $XORG_CFLAGS"
+if test "x$have_exa_h" = xyes; then
+        AC_MSG_CHECKING([whether EXA version is at least 2.0.0])
+        AC_PREPROC_IFELSE([AC_LANG_PROGRAM([[
+#include "exa.h"
+#if EXA_VERSION_MAJOR < 2
+#error OLD EXA!
+#endif
+                          ]])],
+                          [USE_EXA=yes],
+                          [USE_EXA=no])
+        AC_MSG_RESULT($USE_EXA)
+
+        if test "x$USE_EXA" = xyes; then
+                AC_DEFINE(USE_EXA, 1, [Build support for Exa])
+        fi
+fi
+AM_CONDITIONAL(USE_EXA, test "x$USE_EXA" = xyes)
+
 if test "x$XSERVER_LIBPCIACCESS" = xyes; then
     PKG_CHECK_MODULES([PCIACCESS], [pciaccess >= 0.8.0])
     XORG_CFLAGS="$XORG_CFLAGS $PCIACCESS_CFLAGS"
diff --git src/Makefile.am src/Makefile.am
index c649b3d..0468be5 100644
--- src/Makefile.am
+++ src/Makefile.am
@@ -37,6 +37,11 @@ cirrus_drv_la_SOURCES = \
          cir_pcirename.h \
          compat-api.h
 
+if USE_EXA
+ALPINE_EXA_SRCS = \
+         alp_exa.c
+endif
+
 cirrus_alpine_la_LTLIBRARIES = cirrus_alpine.la
 cirrus_alpine_la_LDFLAGS = -module -avoid-version
 cirrus_alpine_ladir = @moduledir@/drivers
@@ -46,7 +51,9 @@ cirrus_alpine_la_SOURCES = \
          alp_hwcurs.c \
          alp_i2c.c \
          alp_xaa.c \
-         alp_xaam.c
+         alp_xaam.c \
+         $(ALPINE_EXA_SRCS)
+
 
 cirrus_laguna_la_LTLIBRARIES = cirrus_laguna.la
 cirrus_laguna_la_LDFLAGS = -module -avoid-version
diff --git src/alp.h src/alp.h
index c09e24b..5f1ad11 100644
--- src/alp.h
+++ src/alp.h
@@ -44,6 +44,10 @@ extern Bool AlpHWCursorInit(ScreenPtr pScreen, int size);
 extern Bool AlpXAAInit(ScreenPtr pScreen);
 extern Bool AlpXAAInitMMIO(ScreenPtr pScreen);
 #endif
+#ifdef USE_EXA
+extern Bool AlpEXAInit(ScreenPtr);
+#endif
+
 extern Bool AlpDGAInit(ScreenPtr pScreen);
 extern Bool AlpI2CInit(ScrnInfoPtr pScrn);
 
diff --git src/alp_driver.c src/alp_driver.c
index 36f2039..3d6b27a 100644
--- src/alp_driver.c
+++ src/alp_driver.c
@@ -223,7 +223,6 @@ AlpProbe(int entity)
     return pScrn;
 }
 
-
 static Bool
 AlpGetRec(ScrnInfoPtr pScrn)
 {
@@ -237,7 +236,7 @@ AlpGetRec(ScrnInfoPtr pScrn)
 	((CirPtr)pScrn->driverPrivate)->chip.alp = xnfcalloc(sizeof(AlpRec),1);
 
 #ifdef ALP_DEBUG
-	ErrorF("AlpGetRec 0x%x\n", CIRPTR(pScrn));
+	ErrorF("AlpGetRec 0x%lx\n", (intptr_t)CIRPTR(pScrn));
 #endif
 	return TRUE;
 }
@@ -1085,10 +1084,22 @@ AlpPreInit(ScrnInfoPtr pScrn, int flags)
 
 	/* Load XAA if needed */
 	if (!pCir->NoAccel) {
+#ifdef USE_EXA
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Loading EXA module...\n");
+	    if (xf86LoadSubModule(pScrn, "exa")) {
+		pCir->ExaDriver = exaDriverAlloc();
+		if (!pCir->ExaDriver) {
+		    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			       "Could no allocate EXA_DRIVER.\n");
+		    pCir->UseEXA = FALSE;
+		}
+		pCir->UseEXA = TRUE;
+	    }
+#endif
 #ifdef HAVE_XAA_H
 		if (!xf86LoadSubModule(pScrn, "xaa"))
 #else
-		if (1)
+		if (!pCir->UseEXA)
 #endif
                 {
 			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -1468,10 +1479,9 @@ AlpScreenInit(SCREEN_INIT_ARGS_DECL)
 #ifdef ALP_DEBUG
 	ErrorF("AlpScreenInit\n");
 #endif
-
 	hwp = VGAHWPTR(pScrn);
 	pCir = CIRPTR(pScrn);
-	
+
 	/* Map the VGA memory when the primary video */
 	if (!vgaHWMapMem(pScrn))
 	    return FALSE;
@@ -1657,6 +1667,20 @@ AlpScreenInit(SCREEN_INIT_ARGS_DECL)
 	      xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 
 			 "Could not initialize XAA\n");
 #endif
+#ifdef USE_EXA
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		       "Filling in EXA memory info\n");
+	    pCir->ExaDriver->offScreenBase = pCir->offscreen_offset;
+	    pCir->ExaDriver->memorySize = pCir->FbMapSize;
+	    if (AlpEXAInit(pScreen))
+		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			   "EXA Acceleration enabled\n");
+	    else {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "EXA Acceleration Init failed\n");
+		pCir->NoAccel = TRUE;
+	    }
+#endif
 	}
 
 #if 1
@@ -1764,7 +1788,7 @@ AlpAdjustFrame(ADJUST_FRAME_ARGS_DECL)
 		Base *= (pScrn->bitsPerPixel/4);
 
 #ifdef ALP_DEBUG
-	ErrorF("AlpAdjustFrame %d %d 0x%x %d %x\n", x, y, flags, Base, Base);
+	ErrorF("AlpAdjustFrame %d %d %d %x\n", x, y, Base, Base);
 #endif
 
 	if ((Base & ~0x000FFFFF) != 0) {
diff --git src/alp_exa.c src/alp_exa.c
new file mode 100644
index 0000000..c31a0ea
--- /dev/null
+++ src/alp_exa.c
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2013 Matthieu Herrb 
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT
+ * HOLDERS 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "xf86.h"
+#include "xf86_OSproc.h"
+#include "compiler.h"
+
+#include "xf86Pci.h"
+#include "vgaHW.h"
+
+#include "cir.h"
+#define _ALP_PRIVATE_
+#include "alp.h"
+
+#include "exa.h"
+
+#define WAIT	outb(pCir->PIOReg, 0x31); \
+		while(inb(pCir->PIOReg + 1) & pCir->chip.alp->waitMsk){};
+#define WAIT_1	outb(pCir->PIOReg, 0x31); \
+		while(inb(pCir->PIOReg + 1) & 0x1){};
+#define SetupForRop(rop) outw(pCir->PIOReg, translated_rop[rop])
+
+static Bool AlpPrepareSolid(PixmapPtr, int, Pixel, Pixel);
+static void AlpSolid(PixmapPtr, int, int, int, int);
+static Bool AlpPrepareCopy(PixmapPtr, PixmapPtr, int, int, int, Pixel);
+static void AlpCopy(PixmapPtr, int, int, int, int, int, int);
+static void AlpDone(PixmapPtr);
+static void AlpSync(ScreenPtr, int);
+
+static const CARD16 translated_rop[] =
+{
+  /* GXclear */        0x0032U,
+  /* GXand   */        0x0532U,
+  /* GXandreverse */   0x0932U,
+  /* GXcopy */         0x0D32U,
+  /* GXandinversted */ 0x5032U,
+  /* GXnoop */         0x0632U,
+  /* GXxor */          0x5932U,
+  /* GXor */           0x6D32U,
+  /* GXnor */          0x9032U,
+  /* GXequiv */        0x9532U,
+  /* GXinvert */       0x0B32U,
+  /* GXorReverse */    0xAD32U,
+  /* GXcopyInverted */ 0xD032U,
+  /* GXorInverted */   0xD632U,
+  /* GXnand */         0xDA32U,
+  /* GXset */          0x0E32U
+};
+
+
+static Bool
+AlpPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+    AlpPtr pAlp = ALPPTR(pCir);
+    int pitch = pCir->pitch;
+    
+#ifdef ALP_DEBUG
+    ErrorF("AlpSetupForSolidFill color=%x alu=%x planemask=%x\n",
+	   fg, alu, planemask);
+#endif
+    WAIT;
+    
+    SetupForRop(alu);
+    
+    switch (pCir -> Chipset) {
+      case PCI_CHIP_GD7548:
+	/* The GD7548 does not (apparently) support solid filling
+	   directly, it always need an actual source.
+	   We therefore use it as a pattern fill with a solid
+	   pattern */
+      {
+	  int source = pAlp->monoPattern8x8;
+	  /* source = 8x8 solid mono pattern */
+	  outw(pCir->PIOReg, ((source << 8) & 0xff00) | 0x2C);
+	  outw(pCir->PIOReg, ((source) & 0xff00) | 0x2D);
+	  outw(pCir->PIOReg, ((source >> 8) & 0x3f00) | 0x2E);
+	  /* memset() may not be the fastest */
+	  memset((char *)pCir->FbBase + pAlp->monoPattern8x8, 0xFF, 8);
+	  write_mem_barrier();
+	  break;
+      }
+      default:
+	/* GR33 = 0x04 => does not exist on GD7548 */
+	outw(pCir->PIOReg, 0x0433);
+    }
+    
+    /* GR30 = color expansion, pattern copy */
+    /* Choses 8bpp / 16bpp color expansion */
+    outw(pCir->PIOReg, 0xC030 |((pScrn->bitsPerPixel - 8) << 9));
+    
+    outw(pCir->PIOReg, ((fg << 8) & 0xff00) | 0x01);
+    outw(pCir->PIOReg, ((fg) & 0xff00) | 0x11);
+    outw(pCir->PIOReg, ((fg >> 8) & 0xff00) | 0x13);
+    outw(pCir->PIOReg, 0x15);
+    
+    /* Set dest pitch */
+    outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+    outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+    
+    return TRUE;
+}
+
+static void
+AlpSolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+    int dest;
+    int hh, ww;
+    int pitch = pCir->pitch;
+    
+    ww = ((x2 - x1) * pScrn->bitsPerPixel / 8) - 1;
+    hh = (y2 - y1) - 1;
+    dest = y1 * pitch + x1 * pScrn->bitsPerPixel / 8;
+    
+    WAIT;
+    
+    /* Width */
+    outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+    outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+    /* Height */
+    outw(pCir->PIOReg, ((hh << 8) & 0xff00) | 0x22);
+    outw(pCir->PIOReg, ((hh) & 0x0700) | 0x23);
+    
+    /* dest */
+    outw(pCir->PIOReg, ((dest << 8) & 0xff00) | 0x28);
+    outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+    outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+    if (!pCir->chip.alp->autoStart)
+	outw(pCir->PIOReg, 0x0231);
+    
+#ifdef ALP_DEBUG
+    ErrorF("AlpSubsequentSolidFillRect x=%d y=%d w=%d h=%d\n",
+	   x1, y1, x2 - x1, y2 - y1);
+#endif
+}
+
+static Bool 
+AlpPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
+	       int xdir, int ydir, int alu, Pixel planemask)
+{
+    ScreenPtr pScreen = pSrcPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+    int pitch = pCir->pitch;
+
+#ifdef ALP_DEBUG
+    ErrorF("AlpPrepareCopy xdir=%d ydir=%d alu=%x planemask=%x\n",
+	   xdir, ydir, alu, planemask);
+#endif
+    WAIT;
+    SetupForRop(alu);
+    /* Set dest pitch */
+    outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x24);
+    outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x25);
+    /* Set source pitch */
+    outw(pCir->PIOReg, ((pitch << 8) & 0xff00) | 0x26);
+    outw(pCir->PIOReg, ((pitch) & 0x1f00) | 0x27);
+    return TRUE;
+}
+
+static void
+AlpCopy(PixmapPtr pDstPixmap, int srcX, int srcY, int dstX, int dstY, 
+	int width, int height)
+{
+    ScreenPtr pScreen = pDstPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+    int source, dest;
+    int  hh, ww;
+    int decrement = 0;
+    int pitch = pCir->pitch;
+    
+    ww = (width * pScrn->bitsPerPixel / 8) - 1;
+    hh = height - 1;
+    dest = dstY * pitch + dstX * pScrn->bitsPerPixel / 8;
+    source = srcY * pitch + srcX * pScrn->bitsPerPixel / 8;
+    if (dest > source) {
+	decrement = 1 << 8;
+	dest += hh * pitch + ww;
+	source += hh * pitch + ww;
+    }
+    
+    WAIT;
+    
+    outw(pCir->PIOReg, decrement | 0x30);
+    
+    /* Width */
+    outw(pCir->PIOReg, ((ww << 8) & 0xff00) | 0x20);
+    outw(pCir->PIOReg, ((ww) & 0x1f00) | 0x21);
+    /* Height */
+    outw(pCir->PIOReg, ((hh << 8) & 0xff00) | 0x22);
+    outw(pCir->PIOReg, ((hh) & 0x0700) | 0x23);
+    
+    
+    /* source */
+    outw(pCir->PIOReg, ((source << 8) & 0xff00) | 0x2C);
+    outw(pCir->PIOReg, ((source) & 0xff00) | 0x2D);
+    outw(pCir->PIOReg, ((source >> 8) & 0x3f00)| 0x2E);
+    
+    /* dest */
+    outw(pCir->PIOReg, ((dest  << 8) & 0xff00) | 0x28);
+    outw(pCir->PIOReg, ((dest) & 0xff00) | 0x29);
+    outw(pCir->PIOReg, ((dest >> 8) & 0x3f00) | 0x2A);
+    if (!pCir->chip.alp->autoStart)
+	outw(pCir->PIOReg, 0x0231);
+    
+#ifdef ALP_DEBUG
+    ErrorF("AlpCopy x1=%d y1=%d x2=%d y2=%d w=%d h=%d\n",
+	   srcX, srcY, dstX, dstY, width, height);
+    ErrorF("AlpSCopy s=%d d=%d ww=%d hh=%d\n",
+	   source, dest, ww, hh);
+#endif
+}
+
+static void
+AlpDone(PixmapPtr pPixmap)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+#ifdef ALP_DEBUG
+    ErrorF("AlpDone\n");
+#endif
+}
+
+static void
+AlpSync(ScreenPtr pScreen, int marker)
+{
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+
+#ifdef ALP_DEBUG
+    ErrorF("AlpSync\n");
+#endif
+    WAIT_1;
+    return;
+}
+
+
+static void
+AlpAccelEngineInit(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+
+    outw(pCir->PIOReg, 0x200E); /* enable writes to gr33 */
+    /* Setup things for autostart */
+    if (pCir->properties & ACCEL_AUTOSTART) {
+        outw(pCir->PIOReg, 0x8031); /* enable autostart */
+	pCir->chip.alp->waitMsk = 0x10;
+	pCir->chip.alp->autoStart = TRUE;
+    } else {
+        pCir->chip.alp->waitMsk = 0x1;
+	pCir->chip.alp->autoStart = FALSE;
+    }
+}
+
+Bool
+AlpEXAInit(ScreenPtr pScreen)
+{
+    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+    CirPtr pCir = CIRPTR(pScrn);
+
+    AlpAccelEngineInit(pScreen);
+
+    pCir->ExaDriver->exa_major = EXA_VERSION_MAJOR;
+    pCir->ExaDriver->exa_minor = EXA_VERSION_MINOR;
+
+    pCir->ExaDriver->memoryBase = (char *)pCir->FbBase + pScrn->fbOffset;
+    pCir->ExaDriver->flags = EXA_OFFSCREEN_PIXMAPS | EXA_OFFSCREEN_ALIGN_POT;
+
+#if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3)
+    pCir->ExaDriver->maxPitchBytes = 16320;
+#endif
+    /* Pitch alignment is in sets of 8 pixels, and we need to cover 32bpp, so it's 32 bytes */
+    pCir->ExaDriver->pixmapPitchAlign = 32;
+    pCir->ExaDriver->pixmapOffsetAlign = 32;
+    pCir->ExaDriver->maxX = 2048;
+    pCir->ExaDriver->maxY = 2048;
+    
+    pCir->ExaDriver->PrepareSolid = AlpPrepareSolid;
+    pCir->ExaDriver->Solid = AlpSolid;
+    pCir->ExaDriver->DoneSolid =AlpDone;
+    
+    pCir->ExaDriver->PrepareCopy = AlpPrepareCopy;
+    pCir->ExaDriver->Copy = AlpCopy;
+    pCir->ExaDriver->DoneCopy = AlpDone;
+
+    pCir->ExaDriver->WaitMarker = AlpSync;
+
+    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	       "Initializing EXA driver...\n");
+    if (!exaDriverInit(pScreen, pCir->ExaDriver)) {
+	free(pCir->ExaDriver);
+	return FALSE;
+    }
+    return TRUE;
+}
+
+    
diff --git src/cir.h src/cir.h
index 0a5d403..78c1301 100644
--- src/cir.h
+++ src/cir.h
@@ -7,6 +7,9 @@
 #ifdef HAVE_XAA_H
 #include "xaa.h"
 #endif
+#ifdef USE_EXA
+#include "exa.h"
+#endif
 #include "xf86i2c.h"
 #include <string.h>
 #include <stdlib.h>
@@ -46,9 +49,13 @@ typedef struct {
 	Bool			NoAccel;
 	Bool			HWCursor;
 	Bool			UseMMIO;
+	Bool			UseEXA;
 #ifdef HAVE_XAA_H
 	XAAInfoRecPtr		AccelInfoRec;
 #endif
+#ifdef USE_EXA
+	ExaDriverPtr		ExaDriver;
+#endif
 	xf86CursorInfoPtr	CursorInfoRec;
 	int			DGAnumModes;
 	DGAModePtr		DGAModes;
-- 
1.8.3



More information about the xorg-devel mailing list