aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/hw/kdrive/mga/mgadraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/hw/kdrive/mga/mgadraw.c')
-rw-r--r--xorg-server/hw/kdrive/mga/mgadraw.c324
1 files changed, 324 insertions, 0 deletions
diff --git a/xorg-server/hw/kdrive/mga/mgadraw.c b/xorg-server/hw/kdrive/mga/mgadraw.c
new file mode 100644
index 000000000..d27e8c9cc
--- /dev/null
+++ b/xorg-server/hw/kdrive/mga/mgadraw.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright © 2003-2004 Anders Carlsson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Anders Carlsson not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Anders Carlsson makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * ANDERS CARLSSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ANDERS CARLSSON BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+#ifdef HAVE_CONFIG_H
+#include <kdrive-config.h>
+#endif
+#include "mga.h"
+#include "g400_common.h"
+#include "kaa.h"
+#include <unistd.h>
+
+CARD32 mgaRop[16] = {
+ /* GXclear */ MGA_ATYPE_RPL | 0x00000000, /* 0 */
+ /* GXand */ MGA_ATYPE_RSTR | 0x00080000, /* src AND dst */
+ /* GXandReverse */ MGA_ATYPE_RSTR | 0x00040000, /* src AND NOT dst */
+ /* GXcopy */ MGA_ATYPE_RSTR | 0x000c0000, /* src */
+ /* GXandInverted */ MGA_ATYPE_RSTR | 0x00020000, /* NOT src AND dst */
+ /* GXnoop */ MGA_ATYPE_RSTR | 0x000a0000, /* dst */
+ /* GXxor */ MGA_ATYPE_RSTR | 0x00060000, /* src XOR dst */
+ /* GXor */ MGA_ATYPE_RSTR | 0x000e0000, /* src OR dst */
+ /* GXnor */ MGA_ATYPE_RSTR | 0x00010000, /* NOT src AND NOT dst */
+ /* GXequiv */ MGA_ATYPE_RSTR | 0x00090000, /* NOT src XOR dst */
+ /* GXinvert */ MGA_ATYPE_RSTR | 0x00050000, /* NOT dst */
+ /* GXorReverse */ MGA_ATYPE_RSTR | 0x000d0000, /* src OR NOT dst */
+ /* GXcopyInverted */ MGA_ATYPE_RPL | 0x00030000, /* NOT src */
+ /* GXorInverted */ MGA_ATYPE_RSTR | 0x000b0000, /* NOT src OR dst */
+ /* GXnand */ MGA_ATYPE_RSTR | 0x00070000, /* NOT src OR NOT dst */
+ /* GXset */ MGA_ATYPE_RPL | 0x000f0000 /* 1 */
+};
+
+VOL8 *mmio;
+int fifo_size;
+int pitch, src_pitch;
+int dir;
+
+void
+mgaWaitAvail (int n)
+{
+ if (fifo_size < n) {
+ while ((fifo_size = MGA_IN32 (mmio, MGA_REG_FIFOSTATUS) & 0xff) < n)
+ ;
+ }
+
+ fifo_size -= n;
+}
+
+#define MGA_OUT8(mmio, a, v) (*(VOL8 *) ((mmio) + (a)) = (v))
+#define MGA_REG_CRTC_INDEX (0x1fd4)
+
+void
+mgaWaitIdle (void)
+{
+
+ mgaWaitAvail (2);
+ MGA_OUT32(mmio, MGA_REG_CACHEFLUSH, 0);
+ /* MGA_OUT8 (mmio, MGA_REG_CRTC_INDEX, 0); */
+ while (MGA_IN32 (mmio, MGA_REG_STATUS) & 0x10000)
+ ;
+}
+
+static void
+mgaWaitMarker (ScreenPtr pScreen, int marker)
+{
+ KdScreenPriv (pScreen);
+ mgaCardInfo (pScreenPriv);
+
+ mmio = mgac->reg_base;
+
+ mgaWaitIdle ();
+}
+
+Bool
+mgaSetup (ScreenPtr pScreen, int dest_bpp, int wait)
+{
+ KdScreenPriv (pScreen);
+ mgaScreenInfo (pScreenPriv);
+ mgaCardInfo (pScreenPriv);
+
+ fifo_size = 0;
+ mmio = mgac->reg_base;
+ pitch = mgas->pitch;
+
+ if (!mmio)
+ return FALSE;
+
+ mgaWaitAvail (wait + 4);
+ /* Set the format of the destination pixmap */
+ switch (dest_bpp) {
+ case 8:
+ MGA_OUT32 (mmio, MGA_REG_MACCESS, MGA_PW8);
+ break;
+ case 16:
+ MGA_OUT32 (mmio, MGA_REG_MACCESS, MGA_PW16);
+ break;
+ case 24:
+ case 32:
+ MGA_OUT32 (mmio, MGA_REG_MACCESS, MGA_PW24);
+ break;
+ }
+ MGA_OUT32 (mmio, MGA_REG_CXBNDRY, 0xffff0000);
+ MGA_OUT32 (mmio, MGA_REG_YTOP, 0x00000000);
+ MGA_OUT32 (mmio, MGA_REG_YBOT, 0x007fffff);
+
+ return TRUE;
+}
+
+static Bool
+mgaPrepareSolid (PixmapPtr pPixmap, int alu, Pixel pm, Pixel fg)
+{
+
+ KdScreenPriv(pPixmap->drawable.pScreen);
+ int cmd;
+ int dst_org;
+ /* We must pad pm and fg depending on the format of the
+ * destination pixmap
+ */
+ switch (pPixmap->drawable.bitsPerPixel) {
+ case 16:
+ fg |= fg << 16;
+ pm |= pm << 16;
+ break;
+ case 8:
+ fg |= (fg << 8) | (fg << 16) | (fg << 24);
+ pm |= (pm << 8) | (pm << 16) | (pm << 24);
+ break;
+ }
+
+ cmd = MGA_OPCOD_TRAP | MGA_DWGCTL_SOLID | MGA_DWGCTL_ARZERO | MGA_DWGCTL_SGNZERO |
+ MGA_DWGCTL_SHIFTZERO | mgaRop[alu];
+
+ dst_org = (int)pPixmap->devPrivate.ptr - (int)pScreenPriv->screen->memory_base;
+
+ mgaSetup (pPixmap->drawable.pScreen, pPixmap->drawable.bitsPerPixel, 5);
+ MGA_OUT32 (mmio, MGA_REG_DSTORG, dst_org);
+ MGA_OUT32 (mmio, MGA_REG_PITCH, pPixmap->devKind / (pPixmap->drawable.bitsPerPixel >> 3));
+ MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd);
+ MGA_OUT32 (mmio, MGA_REG_FCOL, fg);
+ MGA_OUT32 (mmio, MGA_REG_PLNWT, pm);
+
+ return TRUE;
+}
+
+static void
+mgaSolid (int x1, int y1, int x2, int y2)
+{
+ mgaWaitAvail (2);
+ MGA_OUT32 (mmio, MGA_REG_FXBNDRY, (x2 << 16) | (x1 & 0xffff));
+ MGA_OUT32 (mmio, MGA_REG_YDSTLEN | MGA_REG_EXEC, (y1 << 16) | (y2 - y1));
+}
+
+static void
+mgaDoneSolid (void)
+{
+}
+
+#define BLIT_LEFT 1
+#define BLIT_UP 4
+
+static Bool
+mgaPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
+ int dx, int dy, int alu, Pixel pm)
+{
+ KdScreenPriv(pSrcPixmap->drawable.pScreen);
+ int cmd;
+
+ cmd = MGA_OPCOD_BITBLT | MGA_DWGCTL_BFCOL | MGA_DWGCTL_SHIFTZERO | mgaRop[alu];
+
+ dir = 0;
+
+ if (dy < 0)
+ dir |= BLIT_UP;
+ if (dx < 0)
+ dir |= BLIT_LEFT;
+
+ mgaSetup (pSrcPixmap->drawable.pScreen,
+ pDstPixmap->drawable.bitsPerPixel, 7);
+
+ MGA_OUT32 (mmio, MGA_REG_SRCORG, ((int)pSrcPixmap->devPrivate.ptr -
+ (int)pScreenPriv->screen->memory_base));
+ MGA_OUT32 (mmio, MGA_REG_DSTORG, ((int)pDstPixmap->devPrivate.ptr -
+ (int)pScreenPriv->screen->memory_base));
+ MGA_OUT32 (mmio, MGA_REG_PITCH, (pDstPixmap->devKind /
+ (pDstPixmap->drawable.bitsPerPixel >> 3)));
+ src_pitch = pSrcPixmap->devKind / (pSrcPixmap->drawable.bitsPerPixel >> 3);
+
+ MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd);
+ MGA_OUT32 (mmio, MGA_REG_SGN, dir);
+ MGA_OUT32 (mmio, MGA_REG_PLNWT, pm);
+ MGA_OUT32 (mmio, MGA_REG_AR5, src_pitch * (dy < 0 ? -1 : 1) );
+
+ return TRUE;
+}
+
+static void
+mgaCopy (int srcX, int srcY, int dstX, int dstY, int w, int h)
+{
+ int start, end;
+ if (dir & BLIT_UP)
+ {
+ srcY += h - 1;
+ dstY += h - 1;
+ }
+
+ w--;
+ start = end = srcY * src_pitch + srcX;
+
+ if (dir & BLIT_LEFT)
+ start += w;
+ else
+ end += w;
+
+ mgaWaitAvail (4);
+ MGA_OUT32 (mmio, MGA_REG_AR0, end);
+ MGA_OUT32 (mmio, MGA_REG_AR3, start);
+ MGA_OUT32 (mmio, MGA_REG_FXBNDRY, ((dstX + w) << 16) | (dstX & 0xffff));
+ MGA_OUT32 (mmio, MGA_REG_YDSTLEN | MGA_REG_EXEC, (dstY << 16) | h);
+}
+
+static void
+mgaDoneCopy (void)
+{
+}
+
+#if 0
+static Bool
+mgaUploadToScreen(PixmapPtr pDst, char *src, int src_pitch) {
+ /*fprintf(stderr,"Upload to Screen %p [%d]\n",src,src_pitch);*/
+ return TRUE;
+}
+#endif
+
+Bool
+mgaDrawInit (ScreenPtr pScreen)
+{
+ KdScreenPriv(pScreen);
+ mgaScreenInfo (pScreenPriv);
+ KdCardInfo *card = pScreenPriv->card;
+
+ memset(&mgas->kaa, 0, sizeof(KaaScreenInfoRec));
+ mgas->kaa.waitMarker = mgaWaitMarker;
+ mgas->kaa.PrepareSolid = mgaPrepareSolid;
+ mgas->kaa.Solid = mgaSolid;
+ mgas->kaa.DoneSolid = mgaDoneSolid;
+ mgas->kaa.PrepareCopy = mgaPrepareCopy;
+ mgas->kaa.Copy = mgaCopy;
+ mgas->kaa.DoneCopy = mgaDoneCopy;
+ /* In PW24 mode, we need to align to "3 64-bytes" */
+ mgas->kaa.offsetAlign = 192;
+ /* Pitch alignment is in sets of 32 pixels, and we need to cover 32bpp, so
+ * 128 bytes
+ */
+ mgas->kaa.pitchAlign = 128;
+ mgas->kaa.flags = KAA_OFFSCREEN_PIXMAPS;
+
+ if (card->attr.deviceID == MGA_G4XX_DEVICE_ID) {
+ mgas->kaa.CheckComposite = mgaCheckComposite;
+ mgas->kaa.PrepareComposite = mgaPrepareComposite;
+ mgas->kaa.Composite = mgaComposite;
+ mgas->kaa.DoneComposite = mgaDoneComposite;
+ }
+
+ /*mgas->kaa.UploadToScreen=mgaUploadToScreen;*/
+
+ if (!kaaDrawInit (pScreen, &mgas->kaa))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+mgaDrawEnable (ScreenPtr pScreen)
+{
+ KdScreenPriv (pScreen);
+ mgaScreenInfo (pScreenPriv);
+
+ mgas->pitch = pScreenPriv->screen->width;
+
+ switch (pScreenPriv->screen->fb[0].depth) {
+ case 8:
+ mgas->pw = MGA_PW8;
+ break;
+ case 16:
+ mgas->pw = MGA_PW16;
+ break;
+ case 24:
+ case 32:
+ mgas->pw = MGA_PW24;
+ break;
+ default:
+ FatalError ("unsupported pixel format");
+ }
+
+ kaaMarkSync (pScreen);
+}
+
+void
+mgaDrawDisable (ScreenPtr pScreen)
+{
+ kaaWaitSync(pScreen);
+}
+
+void
+mgaDrawFini (ScreenPtr pScreen)
+{
+}
+