summaryrefslogtreecommitdiff
path: root/src/i830_exa.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/i830_exa.c')
-rw-r--r--src/i830_exa.c418
1 files changed, 418 insertions, 0 deletions
diff --git a/src/i830_exa.c b/src/i830_exa.c
new file mode 100644
index 00000000..a6aa6a79
--- /dev/null
+++ b/src/i830_exa.c
@@ -0,0 +1,418 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+All Rights Reserved.
+Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
+ Based on code from i830_xaa.c.
+
+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, sub license, 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 NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS 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_ansic.h"
+#include "xf86.h"
+#include "xaarop.h"
+#include "i830.h"
+#include "i810_reg.h"
+
+int I830CopyROP[16] =
+{
+ ROP_0, /* GXclear */
+ ROP_DSa, /* GXand */
+ ROP_SDna, /* GXandReverse */
+ ROP_S, /* GXcopy */
+ ROP_DSna, /* GXandInverted */
+ ROP_D, /* GXnoop */
+ ROP_DSx, /* GXxor */
+ ROP_DSo, /* GXor */
+ ROP_DSon, /* GXnor */
+ ROP_DSxn, /* GXequiv */
+ ROP_Dn, /* GXinvert*/
+ ROP_SDno, /* GXorReverse */
+ ROP_Sn, /* GXcopyInverted */
+ ROP_DSno, /* GXorInverted */
+ ROP_DSan, /* GXnand */
+ ROP_1 /* GXset */
+};
+
+static int I830PatternROP[16] =
+{
+ ROP_0,
+ ROP_DPa,
+ ROP_PDna,
+ ROP_P,
+ ROP_DPna,
+ ROP_D,
+ ROP_DPx,
+ ROP_DPo,
+ ROP_DPon,
+ ROP_PDxn,
+ ROP_Dn,
+ ROP_PDno,
+ ROP_Pn,
+ ROP_DPno,
+ ROP_DPan,
+ ROP_1
+};
+
+void i830ScratchSave(ScreenPtr pScreen, ExaOffscreenArea *area);
+Bool i830UploadToScreen(PixmapPtr pDst, char *src, int src_pitch);
+Bool i830UploadToScratch(PixmapPtr pSrc, PixmapPtr pDst);
+Bool i830DownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
+ char *dst, int dst_pitch);
+
+/**
+ * I830EXASync - wait for a command to finish
+ * @pScreen: current screen
+ * @marker: marker command to wait for
+ *
+ * Wait for the command specified by @marker to finish, then return.
+ */
+static void
+I830EXASync(ScreenPtr pScreen, int marker)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+#ifdef XF86DRI
+ /* VT switching tries to do this. */
+ if (!pI830->LockHeld && pI830->directRenderingEnabled)
+ return;
+#endif
+
+ if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning)
+ return;
+
+ /* Send a flush instruction and then wait till the ring is empty.
+ * This is stronger than waiting for the blitter to finish as it also
+ * flushes the internal graphics caches.
+ */
+ {
+ BEGIN_LP_RING(2);
+ OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
+ OUT_RING(MI_NOOP); /* pad to quadword */
+ ADVANCE_LP_RING();
+ }
+
+ I830WaitLpRing(pScrn, pI830->LpRing->mem.Size - 8, 0);
+
+ pI830->LpRing->space = pI830->LpRing->mem.Size - 8;
+ pI830->nextColorExpandBuf = 0;
+}
+
+/**
+ * I830EXAPrepareSolid - prepare for a Solid operation, if possible
+ *
+ * TODO:
+ * - support planemask using FILL_MONO_SRC_BLT_CMD?
+ */
+static Bool
+I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (planemask != (Pixel)~0)
+ return FALSE;
+
+ pI830->BR[13] = exaGetPixmapPitch(pPixmap);
+ pI830->BR[13] |= I830PatternROP[alu] << 16;
+
+ pI830->BR[16] = fg;
+
+ /*
+ * Depth: 00 - 8 bit, 01 - 16 bit, 10 - 24 bit, 11 - 32 bit
+ */
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ pI830->BR[13] |= ((0 << 25) | (0 << 24));
+ break;
+ case 16:
+ pI830->BR[13] |= ((0 << 25) | (1 << 24));
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+ return TRUE;
+}
+
+static void
+I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int h, w;
+ unsigned int offset;
+
+ offset = exaGetPixmapOffset(pPixmap) + y1 * exaGetPixmapPitch(pPixmap) +
+ x1 * (pPixmap->drawable.bitsPerPixel / 8);
+
+ h = y2 - y1;
+ w = x2 - x1;
+
+ {
+ BEGIN_LP_RING(6);
+
+ if (pScrn->bitsPerPixel == 32)
+ OUT_RING(COLOR_BLT_CMD | COLOR_BLT_WRITE_ALPHA |
+ COLOR_BLT_WRITE_RGB);
+ else
+ OUT_RING(COLOR_BLT_CMD);
+
+ OUT_RING(pI830->BR[13]);
+ OUT_RING((h << 16) | (w * (pPixmap->drawable.bitsPerPixel/8)));
+ OUT_RING(offset);
+ OUT_RING(pI830->BR[16]);
+ OUT_RING(0);
+
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I830EXADoneSolid(PixmapPtr pPixmap)
+{
+ return;
+}
+
+/**
+ * TODO:
+ * - support planemask using FULL_BLT_CMD?
+ */
+static Bool
+I830EXAPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir,
+ int ydir, int alu, Pixel planemask)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (planemask != (Pixel)~0)
+ return FALSE;
+
+ pI830->copy_src_pitch = exaGetPixmapPitch(pSrcPixmap);
+ pI830->copy_src_off = exaGetPixmapOffset(pSrcPixmap);
+
+ pI830->BR[13] = exaGetPixmapPitch(pDstPixmap);
+ pI830->BR[13] |= I830CopyROP[alu] << 16;
+
+ switch (pScrn->bitsPerPixel) {
+ case 8:
+ break;
+ case 16:
+ pI830->BR[13] |= (1 << 24);
+ break;
+ case 32:
+ pI830->BR[13] |= ((1 << 25) | (1 << 24));
+ break;
+ }
+ return TRUE;
+}
+
+static void
+I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
+ int dst_y1, int w, int h)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDstPixmap->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ int dst_x2, dst_y2;
+ unsigned int src_off, dst_off;
+
+ dst_x2 = dst_x1 + w;
+ dst_y2 = dst_y1 + h;
+
+ src_off = pI830->copy_src_off;
+ dst_off = exaGetPixmapOffset(pDstPixmap);
+
+ {
+ BEGIN_LP_RING(8);
+
+ if (pScrn->bitsPerPixel == 32)
+ OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ else
+ OUT_RING(XY_SRC_COPY_BLT_CMD);
+
+ OUT_RING(pI830->BR[13]);
+ OUT_RING((dst_y1 << 16) | (dst_x1 & 0xffff));
+ OUT_RING((dst_y2 << 16) | (dst_x2 & 0xffff));
+ OUT_RING(dst_off);
+ OUT_RING((src_y1 << 16) | (src_x1 & 0xffff));
+ OUT_RING(pI830->copy_src_pitch);
+ OUT_RING(src_off);
+
+ ADVANCE_LP_RING();
+ }
+}
+
+static void
+I830EXADoneCopy(PixmapPtr pDstPixmap)
+{
+ return;
+}
+
+#if 0 /* Not done (or even started for that matter) */
+static Bool
+I830EXAUploadToScreen(PixmapPtr pDst, char *src, int src_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned char *dst = pDst->devPrivate.ptr;
+ int dst_pitch = exaGetPixmapPitch(pDst);
+ int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+ int h = pDst->drawable.height;
+
+ I830Sync(pScrn);
+
+ while(h--) {
+ i830MemCopyToVideoRam(pI830, dst, (unsigned char *)src, size);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830EXADownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, int h,
+ char *dst, int dst_pitch)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pSrc->drawable.pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+ unsigned char *src = pSrc->devPrivate.ptr;
+ int src_pitch = exaGetPixmapPitch(pSrc);
+ int size = src_pitch < dst_pitch ? src_pitch : dst_pitch;
+
+ I830Sync(pScrn);
+
+ while(h--) {
+ i830MemCopyFromVideoRam(pI830, (unsigned char *)dst, src, size);
+ src += src_pitch;
+ dst += dst_pitch;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830EXACheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture,
+ PicturePtr pDstPicture)
+{
+ return FALSE; /* no Composite yet */
+}
+
+static Bool
+I830EXAPrepareComposite(int op, PicturePtr pSrcPicture,
+ PicturePtr pMaskPicture, PicturePtr pDstPicture,
+ PixmapPtr pSrc, PixmapPtr pMask, PixmapPtr pDst)
+{
+ return FALSE; /* no Composite yet */
+}
+
+static void
+I830EXAComposite(PixmapPtr pDst, int srcX, int srcY, int maskX, int maskY,
+ int dstX, int dstY, int width, int height)
+{
+ return; /* no Composite yet */
+}
+
+static void
+I830EXADoneComposite(PixmapPtr pDst)
+{
+ return; /* no Composite yet */
+}
+#endif
+
+/*
+ * TODO:
+ * - Dual head?
+ * - Upload/Download
+ * - Composite
+ */
+Bool
+I830EXAInit(ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if(pI830->useEXA) {
+ if(!(pI830->EXADriverPtr = xnfcalloc(sizeof(ExaDriverRec), 1))) {
+ pI830->noAccel = TRUE;
+ return FALSE;
+ }
+ }
+
+ pI830->bufferOffset = 0;
+ pI830->EXADriverPtr->card.memoryBase = pI830->FbBase;
+ pI830->EXADriverPtr->card.offScreenBase = pI830->Offscreen.Start;
+ pI830->EXADriverPtr->card.memorySize = pI830->Offscreen.Size;
+
+ if(pI830->EXADriverPtr->card.memorySize >
+ pI830->EXADriverPtr->card.offScreenBase)
+ pI830->EXADriverPtr->card.flags = EXA_OFFSCREEN_PIXMAPS;
+ else {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video RAM for "
+ "offscreen memory manager. Xv disabled\n");
+ /* disable Xv here... */
+ }
+
+ pI830->EXADriverPtr->card.pixmapOffsetAlign = 256;
+ pI830->EXADriverPtr->card.pixmapPitchAlign = 64;
+ pI830->EXADriverPtr->card.maxX = 4095;
+ pI830->EXADriverPtr->card.maxY = 4095;
+
+ /* Sync */
+ pI830->EXADriverPtr->accel.WaitMarker = I830EXASync;
+
+ /* Solid fill */
+ pI830->EXADriverPtr->accel.PrepareSolid = I830EXAPrepareSolid;
+ pI830->EXADriverPtr->accel.Solid = I830EXASolid;
+ pI830->EXADriverPtr->accel.DoneSolid = I830EXADoneSolid;
+
+ /* Copy */
+ pI830->EXADriverPtr->accel.PrepareCopy = I830EXAPrepareCopy;
+ pI830->EXADriverPtr->accel.Copy = I830EXACopy;
+ pI830->EXADriverPtr->accel.DoneCopy = I830EXADoneCopy;
+#if 0
+ /* Upload, download to/from Screen */
+ pI830->EXADriverPtr->accel.UploadToScreen = I830EXAUploadToScreen;
+ pI830->EXADriverPtr->accel.DownloadFromScreen = I830EXADownloadFromScreen;
+
+ /* Composite */
+ pI830->EXADriverPtr->accel.CheckComposite = I830EXACheckComposite;
+ pI830->EXADriverPtr->accel.PrepareComposite = I830EXAPrepareComposite;
+ pI830->EXADriverPtr->accel.Composite = I830EXAComposite;
+ pI830->EXADriverPtr->accel.DoneComposite = I830EXADoneComposite;
+#endif
+
+ if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+ pI830->noAccel = TRUE;
+ return FALSE;
+ }
+
+ I830SelectBuffer(pScrn, I830_SELECT_FRONT);
+
+ return TRUE;
+}