[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