xserver-multidpi/hw/kdrive/mga/mgadraw.c

318 lines
8.1 KiB
C
Raw Normal View History

2003-09-18 22:47:43 +02:00
/*
* $Id$
*
* Copyright <EFBFBD> 2003-2004 Anders Carlsson
2003-09-18 22:47:43 +02:00
*
* 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.
*/
/* $Header$ */
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "mga.h"
#include "g400_common.h"
#include <unistd.h>
2003-09-18 22:47:43 +02:00
2003-09-22 23:14:59 +02:00
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;
2003-09-18 22:47:43 +02:00
int fifo_size;
int pitch, src_pitch;
2003-09-22 23:14:59 +02:00
int dir;
2003-09-18 22:47:43 +02:00
void
2003-09-18 22:47:43 +02:00
mgaWaitAvail (int n)
{
if (fifo_size < n) {
while ((fifo_size = MGA_IN32 (mmio, MGA_REG_FIFOSTATUS) & 0xff) < n)
;
}
fifo_size -= n;
}
void
2003-09-18 22:47:43 +02:00
mgaWaitIdle (void)
{
while (MGA_IN32 (mmio, MGA_REG_STATUS) & 0x10000);
}
Bool
mgaSetup (ScreenPtr pScreen, int dest_bpp, int wait)
2003-09-18 22:47:43 +02:00
{
KdScreenPriv (pScreen);
mgaScreenInfo (pScreenPriv);
mgaCardInfo (pScreenPriv);
fifo_size = 0;
mmio = mgac->reg_base;
2003-09-22 23:14:59 +02:00
pitch = mgas->pitch;
2003-09-18 22:47:43 +02:00
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;
}
2003-09-18 22:47:43 +02:00
MGA_OUT32 (mmio, MGA_REG_CXBNDRY, 0xffff0000);
MGA_OUT32 (mmio, MGA_REG_YTOP, 0x00000000);
MGA_OUT32 (mmio, MGA_REG_YBOT, 0x007fffff);
return TRUE;
2003-09-18 22:47:43 +02:00
}
2003-11-02 20:56:10 +01:00
static Bool
mgaPrepareSolid (PixmapPtr pPixmap, int alu, Pixel pm, Pixel fg)
2003-09-18 22:47:43 +02:00
{
KdScreenPriv(pPixmap->drawable.pScreen);
2003-09-18 22:47:43 +02:00
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;
}
2003-09-18 22:47:43 +02:00
cmd = MGA_OPCOD_TRAP | MGA_DWGCTL_SOLID | MGA_DWGCTL_ARZERO | MGA_DWGCTL_SGNZERO |
2003-09-22 23:14:59 +02:00
MGA_DWGCTL_SHIFTZERO | mgaRop[alu];
2003-09-18 22:47:43 +02:00
2003-10-15 07:34:54 +02:00
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));
2003-09-18 22:47:43 +02:00
MGA_OUT32 (mmio, MGA_REG_DWGCTL, cmd);
MGA_OUT32 (mmio, MGA_REG_FCOL, fg);
MGA_OUT32 (mmio, MGA_REG_PLNWT, pm);
2003-09-18 22:47:43 +02:00
return TRUE;
}
2003-11-02 20:56:10 +01:00
static void
2003-09-18 22:47:43 +02:00
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));
2003-09-18 22:47:43 +02:00
}
2003-11-02 20:56:10 +01:00
static void
2003-09-18 22:47:43 +02:00
mgaDoneSolid (void)
{
mgaWaitIdle();
2003-09-18 22:47:43 +02:00
}
2003-09-22 23:14:59 +02:00
#define BLIT_LEFT 1
#define BLIT_UP 4
2003-11-02 20:56:10 +01:00
static Bool
mgaPrepareCopy (PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap,
int dx, int dy, int alu, Pixel pm)
2003-09-18 22:47:43 +02:00
{
KdScreenPriv(pSrcPixmap->drawable.pScreen);
2003-09-22 23:14:59 +02:00
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);
2003-09-22 23:14:59 +02:00
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);
2003-09-22 23:14:59 +02:00
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) );
2003-09-22 23:14:59 +02:00
return TRUE;
2003-09-18 22:47:43 +02:00
}
2003-11-02 20:56:10 +01:00
static void
2003-09-18 22:47:43 +02:00
mgaCopy (int srcX, int srcY, int dstX, int dstY, int w, int h)
{
2003-09-22 23:14:59 +02:00
int start, end;
2003-09-22 23:14:59 +02:00
if (dir & BLIT_UP)
{
srcY += h - 1;
dstY += h - 1;
}
w--;
start = end = srcY * src_pitch + srcX;
2003-09-22 23:14:59 +02:00
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);
2003-09-18 22:47:43 +02:00
}
2003-11-02 20:56:10 +01:00
static void
2003-09-18 22:47:43 +02:00
mgaDoneCopy (void)
{
mgaWaitIdle();
}
static Bool
mgaUploadToScreen(PixmapPtr pDst, char *src, int src_pitch) {
/* fprintf(stderr,"Upload to Screen %p [%d]\n",src,src_pitch); */
return TRUE;
2003-09-18 22:47:43 +02:00
}
KaaScreenInfoRec mgaKaa = {
2003-09-18 22:47:43 +02:00
mgaPrepareSolid,
mgaSolid,
mgaDoneSolid,
mgaPrepareCopy,
mgaCopy,
mgaDoneCopy,
192, /* 192 Offscreen byte alignment */
128, /* Pitch alignment is in sets of 32 pixels, and we need to
cover 32bpp, so 128 bytes */
KAA_OFFSCREEN_PIXMAPS /* Flags */
2003-09-18 22:47:43 +02:00
};
Bool
mgaDrawInit (ScreenPtr pScreen)
{
KdScreenPriv(pScreen);
KdCardInfo *card = pScreenPriv->card;
if (card->attr.deviceID == MGA_G4XX_DEVICE_ID) {
mgaKaa.PrepareBlend=mgaPrepareBlend;
mgaKaa.Blend=mgaBlend;
mgaKaa.DoneBlend=mgaDoneBlend;
mgaKaa.PrepareComposite=mgaPrepareComposite;
mgaKaa.Composite=mgaComposite;
mgaKaa.DoneComposite=mgaDoneComposite;
}
/*mgaKaa.UploadToScreen=mgaUploadToScreen;*/
2003-09-18 22:47:43 +02:00
if (!kaaDrawInit (pScreen, &mgaKaa))
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;
2003-09-18 22:47:43 +02:00
break;
default:
FatalError ("unsupported pixel format");
}
KdMarkSync (pScreen);
}
void
mgaDrawDisable (ScreenPtr pScreen)
{
}
void
mgaDrawFini (ScreenPtr pScreen)
{
}
void
mgaDrawSync (ScreenPtr pScreen)
{
KdScreenPriv (pScreen);
mgaCardInfo (pScreenPriv);
mmio = mgac->reg_base;
mgaWaitIdle ();
}