apm_cursor.c revision 17a48c7c
117a48c7cSmrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_cursor.c,v 1.14 2000/06/30 18:27:02 dawes Exp $ */
217a48c7cSmrg
317a48c7cSmrg#ifdef HAVE_CONFIG_H
417a48c7cSmrg#include "config.h"
517a48c7cSmrg#endif
617a48c7cSmrg
717a48c7cSmrg#include <X11/X.h>
817a48c7cSmrg#include <X11/Xproto.h>
917a48c7cSmrg#include "misc.h"
1017a48c7cSmrg#include "input.h"
1117a48c7cSmrg#include "cursorstr.h"
1217a48c7cSmrg#include "regionstr.h"
1317a48c7cSmrg#include "scrnintstr.h"
1417a48c7cSmrg#include "servermd.h"
1517a48c7cSmrg#include "windowstr.h"
1617a48c7cSmrg#include "mfb.h"
1717a48c7cSmrg#include "mipointer.h"
1817a48c7cSmrg
1917a48c7cSmrg#include "apm.h"
2017a48c7cSmrg
2117a48c7cSmrg#define CURSORWIDTH	64
2217a48c7cSmrg#define CURSORHEIGHT	64
2317a48c7cSmrg#define CURSORSIZE	(CURSORWIDTH * CURSORHEIGHT / 8)
2417a48c7cSmrg#define CURSORALIGN	((CURSORSIZE + 1023) & ~1023l)
2517a48c7cSmrg
2617a48c7cSmrgstatic void	ApmShowCursor(ScrnInfoPtr pScrn);
2717a48c7cSmrgstatic void	ApmHideCursor(ScrnInfoPtr pScrn);
2817a48c7cSmrgstatic void	ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
2917a48c7cSmrgstatic void	ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
3017a48c7cSmrgstatic void	ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data);
3117a48c7cSmrgstatic Bool	ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
3217a48c7cSmrg
3317a48c7cSmrgstatic u8 ConvertTable[256];
3417a48c7cSmrg
3517a48c7cSmrg/* Inline functions */
3617a48c7cSmrgstatic __inline__ void
3717a48c7cSmrgWaitForFifo(ApmPtr pApm, int slots)
3817a48c7cSmrg{
3917a48c7cSmrg  if (!pApm->UsePCIRetry) {
4017a48c7cSmrg    volatile int i;
4117a48c7cSmrg#define MAXLOOP 1000000
4217a48c7cSmrg
4317a48c7cSmrg    for(i = 0; i < MAXLOOP; i++) {
4417a48c7cSmrg      if ((STATUS() & STATUS_FIFO) >= slots)
4517a48c7cSmrg	break;
4617a48c7cSmrg    }
4717a48c7cSmrg    if (i == MAXLOOP) {
4817a48c7cSmrg      unsigned int status = STATUS();
4917a48c7cSmrg
5017a48c7cSmrg      WRXB(0x1FF, 0);
5117a48c7cSmrg      if (!xf86ServerIsExiting())
5217a48c7cSmrg	FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
5317a48c7cSmrg    }
5417a48c7cSmrg  }
5517a48c7cSmrg}
5617a48c7cSmrg
5717a48c7cSmrgvoid ApmHWCursorReserveSpace(ApmPtr pApm)
5817a48c7cSmrg{
5917a48c7cSmrg  pApm->OffscreenReserved	+= 2 * CURSORALIGN;
6017a48c7cSmrg  pApm->DisplayedCursorAddress	= pApm->BaseCursorAddress =
6117a48c7cSmrg  pApm->CursorAddress	= 1024 * xf86Screens[pApm->pScreen->myNum]->videoRam -
6217a48c7cSmrg					pApm->OffscreenReserved;
6317a48c7cSmrg}
6417a48c7cSmrg
6517a48c7cSmrg
6617a48c7cSmrgint ApmHWCursorInit(ScreenPtr pScreen)
6717a48c7cSmrg{
6817a48c7cSmrg  ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
6917a48c7cSmrg  APMDECL(pScrn);
7017a48c7cSmrg  xf86CursorInfoPtr	infoPtr;
7117a48c7cSmrg  u32			i;
7217a48c7cSmrg
7317a48c7cSmrg  infoPtr = xf86CreateCursorInfoRec();
7417a48c7cSmrg  if (!infoPtr)
7517a48c7cSmrg      return FALSE;
7617a48c7cSmrg
7717a48c7cSmrg  pApm->CursorInfoRec		= infoPtr;
7817a48c7cSmrg
7917a48c7cSmrg  infoPtr->MaxWidth	= CURSORWIDTH;
8017a48c7cSmrg  infoPtr->MaxHeight	= CURSORHEIGHT;
8117a48c7cSmrg
8217a48c7cSmrg  infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
8317a48c7cSmrg  infoPtr->SetCursorColors	= ApmSetCursorColors;
8417a48c7cSmrg  infoPtr->SetCursorPosition	= ApmSetCursorPosition;
8517a48c7cSmrg  infoPtr->LoadCursorImage	= ApmLoadCursorImage;
8617a48c7cSmrg  infoPtr->HideCursor		= ApmHideCursor;
8717a48c7cSmrg  infoPtr->ShowCursor		= ApmShowCursor;
8817a48c7cSmrg  infoPtr->UseHWCursor		= ApmUseHWCursor;
8917a48c7cSmrg
9017a48c7cSmrg  /* Set up the convert table for the input cursor data */
9117a48c7cSmrg  for (i = 0; i < 256; i++)
9217a48c7cSmrg    ConvertTable[i] = ((~i) & 0xAA) | (i & (i >> 1) & 0x55);
9317a48c7cSmrg
9417a48c7cSmrg  return xf86InitCursor(pScreen, infoPtr);
9517a48c7cSmrg}
9617a48c7cSmrg
9717a48c7cSmrg
9817a48c7cSmrgstatic void
9917a48c7cSmrgApmShowCursor(ScrnInfoPtr pScrn)
10017a48c7cSmrg{
10117a48c7cSmrg  APMDECL(pScrn);
10217a48c7cSmrg
10317a48c7cSmrg  WaitForFifo(pApm, 2);
10417a48c7cSmrg  WRXW(0x144, pApm->CursorAddress >> 10);
10517a48c7cSmrg  WRXB(0x140, 1);
10617a48c7cSmrg  pApm->DisplayedCursorAddress = pApm->CursorAddress;
10717a48c7cSmrg}
10817a48c7cSmrg
10917a48c7cSmrg
11017a48c7cSmrgstatic void
11117a48c7cSmrgApmHideCursor(ScrnInfoPtr pScrn)
11217a48c7cSmrg{
11317a48c7cSmrg  APMDECL(pScrn);
11417a48c7cSmrg
11517a48c7cSmrg  WaitForFifo(pApm, 1);
11617a48c7cSmrg  WRXB(0x140, 0);
11717a48c7cSmrg}
11817a48c7cSmrg
11917a48c7cSmrgstatic Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
12017a48c7cSmrg{
12117a48c7cSmrg    return APMPTR(xf86Screens[pScreen->myNum])->CurrentLayout.bitsPerPixel >= 8;
12217a48c7cSmrg}
12317a48c7cSmrg
12417a48c7cSmrgstatic void
12517a48c7cSmrgApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
12617a48c7cSmrg{
12717a48c7cSmrg  APMDECL(pScrn);
12817a48c7cSmrg  int	xoff, yoff;
12917a48c7cSmrg
13017a48c7cSmrg  if (x < -CURSORWIDTH || y < -CURSORHEIGHT) {
13117a48c7cSmrg      WaitForFifo(pApm, 1);
13217a48c7cSmrg      WRXB(0x140, 0);
13317a48c7cSmrg      return;
13417a48c7cSmrg  }
13517a48c7cSmrg
13617a48c7cSmrg  if (x < 0) {
13717a48c7cSmrg      xoff = -x;
13817a48c7cSmrg      x = 0;
13917a48c7cSmrg  }
14017a48c7cSmrg  else
14117a48c7cSmrg      xoff = 0;
14217a48c7cSmrg  if (y < 0) {
14317a48c7cSmrg      yoff = -y;
14417a48c7cSmrg      y = 0;
14517a48c7cSmrg  }
14617a48c7cSmrg  else
14717a48c7cSmrg      yoff = 0;
14817a48c7cSmrg
14917a48c7cSmrg  WaitForFifo(pApm, 2);
15017a48c7cSmrg  WRXW(0x14C, (yoff << 8) | (xoff & 0xFF));
15117a48c7cSmrg  WRXL(0x148, (y << 16) | (x & 0xFFFF));
15217a48c7cSmrg}
15317a48c7cSmrg
15417a48c7cSmrg
15517a48c7cSmrgstatic void
15617a48c7cSmrgApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
15717a48c7cSmrg{
15817a48c7cSmrg  APMDECL(pScrn);
15917a48c7cSmrg  u16 packedcolfg, packedcolbg;
16017a48c7cSmrg
16117a48c7cSmrg  if (pApm->CurrentLayout.bitsPerPixel == 8)
16217a48c7cSmrg  {
16317a48c7cSmrg    WaitForFifo(pApm, 2);
16417a48c7cSmrg    WRXB(0x141, fg);
16517a48c7cSmrg    WRXB(0x142, bg);
16617a48c7cSmrg  }
16717a48c7cSmrg  else
16817a48c7cSmrg  {
16917a48c7cSmrg    packedcolfg =
17017a48c7cSmrg      ((fg & 0xE00000) >> 16) |
17117a48c7cSmrg      ((fg & 0x00E000) >> 11) |
17217a48c7cSmrg      ((fg & 0x0000C0) >> 6);
17317a48c7cSmrg    packedcolbg =
17417a48c7cSmrg      ((bg & 0xE00000) >> 16) |
17517a48c7cSmrg      ((bg & 0x00E000) >> 11) |
17617a48c7cSmrg      ((bg & 0x0000C0) >> 6);
17717a48c7cSmrg    WaitForFifo(pApm, 2);
17817a48c7cSmrg    WRXB(0x141, packedcolfg);
17917a48c7cSmrg    WRXB(0x142, packedcolbg);
18017a48c7cSmrg  }
18117a48c7cSmrg}
18217a48c7cSmrg
18317a48c7cSmrg
18417a48c7cSmrgstatic void
18517a48c7cSmrgApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data)
18617a48c7cSmrg{
18717a48c7cSmrg  APMDECL(pScrn);
18817a48c7cSmrg  u32 i;
18917a48c7cSmrg  u8 tmp[2 * CURSORSIZE];
19017a48c7cSmrg
19117a48c7cSmrg  /* Correct input data */
19217a48c7cSmrg  for (i = 0; i < sizeof tmp; i++)
19317a48c7cSmrg    tmp[i] = ConvertTable[data[i]];
19417a48c7cSmrg  /*
19517a48c7cSmrg   * To avoid flicker.
19617a48c7cSmrg   * Note: 2*pApm->BaseCursorAddress + CURSORALIGN (=1024) < 2^31 all the time.
19717a48c7cSmrg   */
19817a48c7cSmrg  pApm->CursorAddress = 2*pApm->BaseCursorAddress + CURSORALIGN - pApm->DisplayedCursorAddress;
19917a48c7cSmrg  memcpy((u8*)pApm->FbBase + pApm->CursorAddress, tmp, sizeof tmp);
20017a48c7cSmrg}
201