apm_cursor.c revision 17a48c7c
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/apm/apm_cursor.c,v 1.14 2000/06/30 18:27:02 dawes Exp $ */
2
3#ifdef HAVE_CONFIG_H
4#include "config.h"
5#endif
6
7#include <X11/X.h>
8#include <X11/Xproto.h>
9#include "misc.h"
10#include "input.h"
11#include "cursorstr.h"
12#include "regionstr.h"
13#include "scrnintstr.h"
14#include "servermd.h"
15#include "windowstr.h"
16#include "mfb.h"
17#include "mipointer.h"
18
19#include "apm.h"
20
21#define CURSORWIDTH	64
22#define CURSORHEIGHT	64
23#define CURSORSIZE	(CURSORWIDTH * CURSORHEIGHT / 8)
24#define CURSORALIGN	((CURSORSIZE + 1023) & ~1023l)
25
26static void	ApmShowCursor(ScrnInfoPtr pScrn);
27static void	ApmHideCursor(ScrnInfoPtr pScrn);
28static void	ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
29static void	ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
30static void	ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data);
31static Bool	ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs);
32
33static u8 ConvertTable[256];
34
35/* Inline functions */
36static __inline__ void
37WaitForFifo(ApmPtr pApm, int slots)
38{
39  if (!pApm->UsePCIRetry) {
40    volatile int i;
41#define MAXLOOP 1000000
42
43    for(i = 0; i < MAXLOOP; i++) {
44      if ((STATUS() & STATUS_FIFO) >= slots)
45	break;
46    }
47    if (i == MAXLOOP) {
48      unsigned int status = STATUS();
49
50      WRXB(0x1FF, 0);
51      if (!xf86ServerIsExiting())
52	FatalError("Hung in WaitForFifo() (Status = 0x%08X)\n", status);
53    }
54  }
55}
56
57void ApmHWCursorReserveSpace(ApmPtr pApm)
58{
59  pApm->OffscreenReserved	+= 2 * CURSORALIGN;
60  pApm->DisplayedCursorAddress	= pApm->BaseCursorAddress =
61  pApm->CursorAddress	= 1024 * xf86Screens[pApm->pScreen->myNum]->videoRam -
62					pApm->OffscreenReserved;
63}
64
65
66int ApmHWCursorInit(ScreenPtr pScreen)
67{
68  ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
69  APMDECL(pScrn);
70  xf86CursorInfoPtr	infoPtr;
71  u32			i;
72
73  infoPtr = xf86CreateCursorInfoRec();
74  if (!infoPtr)
75      return FALSE;
76
77  pApm->CursorInfoRec		= infoPtr;
78
79  infoPtr->MaxWidth	= CURSORWIDTH;
80  infoPtr->MaxHeight	= CURSORHEIGHT;
81
82  infoPtr->Flags = HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1;
83  infoPtr->SetCursorColors	= ApmSetCursorColors;
84  infoPtr->SetCursorPosition	= ApmSetCursorPosition;
85  infoPtr->LoadCursorImage	= ApmLoadCursorImage;
86  infoPtr->HideCursor		= ApmHideCursor;
87  infoPtr->ShowCursor		= ApmShowCursor;
88  infoPtr->UseHWCursor		= ApmUseHWCursor;
89
90  /* Set up the convert table for the input cursor data */
91  for (i = 0; i < 256; i++)
92    ConvertTable[i] = ((~i) & 0xAA) | (i & (i >> 1) & 0x55);
93
94  return xf86InitCursor(pScreen, infoPtr);
95}
96
97
98static void
99ApmShowCursor(ScrnInfoPtr pScrn)
100{
101  APMDECL(pScrn);
102
103  WaitForFifo(pApm, 2);
104  WRXW(0x144, pApm->CursorAddress >> 10);
105  WRXB(0x140, 1);
106  pApm->DisplayedCursorAddress = pApm->CursorAddress;
107}
108
109
110static void
111ApmHideCursor(ScrnInfoPtr pScrn)
112{
113  APMDECL(pScrn);
114
115  WaitForFifo(pApm, 1);
116  WRXB(0x140, 0);
117}
118
119static Bool ApmUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
120{
121    return APMPTR(xf86Screens[pScreen->myNum])->CurrentLayout.bitsPerPixel >= 8;
122}
123
124static void
125ApmSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
126{
127  APMDECL(pScrn);
128  int	xoff, yoff;
129
130  if (x < -CURSORWIDTH || y < -CURSORHEIGHT) {
131      WaitForFifo(pApm, 1);
132      WRXB(0x140, 0);
133      return;
134  }
135
136  if (x < 0) {
137      xoff = -x;
138      x = 0;
139  }
140  else
141      xoff = 0;
142  if (y < 0) {
143      yoff = -y;
144      y = 0;
145  }
146  else
147      yoff = 0;
148
149  WaitForFifo(pApm, 2);
150  WRXW(0x14C, (yoff << 8) | (xoff & 0xFF));
151  WRXL(0x148, (y << 16) | (x & 0xFFFF));
152}
153
154
155static void
156ApmSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
157{
158  APMDECL(pScrn);
159  u16 packedcolfg, packedcolbg;
160
161  if (pApm->CurrentLayout.bitsPerPixel == 8)
162  {
163    WaitForFifo(pApm, 2);
164    WRXB(0x141, fg);
165    WRXB(0x142, bg);
166  }
167  else
168  {
169    packedcolfg =
170      ((fg & 0xE00000) >> 16) |
171      ((fg & 0x00E000) >> 11) |
172      ((fg & 0x0000C0) >> 6);
173    packedcolbg =
174      ((bg & 0xE00000) >> 16) |
175      ((bg & 0x00E000) >> 11) |
176      ((bg & 0x0000C0) >> 6);
177    WaitForFifo(pApm, 2);
178    WRXB(0x141, packedcolfg);
179    WRXB(0x142, packedcolbg);
180  }
181}
182
183
184static void
185ApmLoadCursorImage(ScrnInfoPtr pScrn, u8* data)
186{
187  APMDECL(pScrn);
188  u32 i;
189  u8 tmp[2 * CURSORSIZE];
190
191  /* Correct input data */
192  for (i = 0; i < sizeof tmp; i++)
193    tmp[i] = ConvertTable[data[i]];
194  /*
195   * To avoid flicker.
196   * Note: 2*pApm->BaseCursorAddress + CURSORALIGN (=1024) < 2^31 all the time.
197   */
198  pApm->CursorAddress = 2*pApm->BaseCursorAddress + CURSORALIGN - pApm->DisplayedCursorAddress;
199  memcpy((u8*)pApm->FbBase + pApm->CursorAddress, tmp, sizeof tmp);
200}
201