alp_hwcurs.c revision 76888252
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/cirrus/alp_hwcurs.c,v 1.4 2000/12/06 15:35:15 eich Exp $ */
2
3#ifdef HAVE_CONFIG_H
4#include "config.h"
5#endif
6
7/* (c) Itai Nahshon */
8
9#include "xf86.h"
10#include "xf86_OSproc.h"
11#include "compiler.h"
12
13#include "xf86Pci.h"
14#include "xf86PciInfo.h"
15
16#include "vgaHW.h"
17
18#include "cir.h"
19#define _ALP_PRIVATE_
20#include "alp.h"
21
22#define CURSORWIDTH	pAlp->CursorWidth
23#define CURSORHEIGHT	pAlp->CursorHeight
24#define CURSORSIZE      (CURSORWIDTH*CURSORHEIGHT/8)
25#define MAXCURSORSIZE   (64*64>>3)
26
27static void
28AlpSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
29{
30    const AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
31	vgaHWPtr hwp = VGAHWPTR(pScrn);
32#ifdef ALP_DEBUG
33	ErrorF("AlpSetCursorColors\n");
34#endif
35	hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]|0x02);
36	hwp->writeDacWriteAddr(hwp, 0x00);
37	hwp->writeDacData(hwp, 0x3f & (bg >> 18));
38	hwp->writeDacData(hwp, 0x3f & (bg >> 10));
39	hwp->writeDacData(hwp, 0x3f & (bg >>  2));
40	hwp->writeDacWriteAddr(hwp, 0x0F);
41	hwp->writeDacData(hwp, 0x3F & (fg >> 18));
42	hwp->writeDacData(hwp, 0x3F & (fg >> 10));
43	hwp->writeDacData(hwp, 0x3F & (fg >>  2));
44	hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
45}
46
47static void
48AlpLoadSkewedCursor(CirPtr pCir, int x, int y) {
49
50    const AlpPtr pAlp = ALPPTR(pCir);
51
52    unsigned char *memx = pAlp->HWCursorBits;
53        unsigned char *CursorBits = pAlp->CursorBits;
54
55        unsigned char mem[2*MAXCURSORSIZE];
56	unsigned char *p1, *p2;
57	int i, j, m, a, b;
58	Bool cur64 = (CURSORWIDTH == 64);
59	int shift = (cur64? 1 : 0);
60
61	if (x > 0) x = 0; else x = -x;
62	if (y > 0) y = 0; else y = -y;
63
64
65	a = ((y*CURSORWIDTH<<shift)+x)>>3;
66	b = x & 7;
67
68	/* Copy the skewed mask bits */
69	p1 = mem;
70	p2 = CursorBits + a;
71	for (i = 0; i < (CURSORSIZE << shift)-a-1; i++) {
72		*p1++ = (p2[0] << b) | (p2[1] >> (8-b));
73		p2++;
74	}
75	/* last mask byte */
76	*p1++ = (p2[0] << b);
77
78	/* Clear to end (bottom) of mask. */
79	for (i = i+1; i < (CURSORSIZE << shift); i++)
80		*p1++ = 0;
81
82	if (!cur64) {
83	    /* Now copy the cursor bits */
84	    /* p1 is already right */
85	    p2 = CursorBits+CURSORSIZE+a;
86	    for (i = 0; i < CURSORSIZE-a-1; i++) {
87		*p1++ = (p2[0] << b) | (p2[1] >> (8-b));
88		p2++;
89	    }
90	    /* last cursor  byte */
91	    *p1++ = (p2[0] << b);
92	}
93
94	/* Clear to end (bottom) of cursor. */
95	for (i = i+1; i < CURSORSIZE; i++)
96		*p1++ = 0;
97
98	/* Clear the right unused area of the mask
99	and cyrsor bits.  */
100	p2 = mem + CURSORWIDTH/8 - (x>>3) - 1;
101	for (i = 0; i < 2*CURSORHEIGHT; i++) {
102		m = (-1)<<(x&7);
103		p1 = p2;
104		p2 += CURSORWIDTH/8;
105		for (j = x>>3; j >= 0; j--) {
106			*p1 &= m;
107			m = 0;
108			p1++;
109		}
110	}
111	memcpy(memx, mem, 2*CURSORSIZE);
112}
113
114
115static void
116AlpSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
117{
118	const CirPtr pCir = CIRPTR(pScrn);
119	const AlpPtr pAlp = ALPPTR(pCir);
120	vgaHWPtr hwp = VGAHWPTR(pScrn);
121
122#if 0
123#ifdef ALP_DEBUG
124	ErrorF("AlpSetCursorPosition %d %d\n", x, y);
125#endif
126#endif
127
128	if (x < 0 || y < 0) {
129		if (x+CURSORWIDTH <= 0 || y+CURSORHEIGHT <= 0) {
130			hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12] & ~0x01);
131			return;
132		}
133		AlpLoadSkewedCursor(pCir, x, y);
134		pCir->CursorIsSkewed = TRUE;
135		if (x < 0) x = 0;
136		if (y < 0) y = 0;
137	} else if (pCir->CursorIsSkewed) {
138		memcpy(pAlp->HWCursorBits, pAlp->CursorBits, 2*CURSORSIZE);
139		pCir->CursorIsSkewed = FALSE;
140	}
141	hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
142	hwp->writeSeq(hwp, ((x << 5)|0x10)&0xff, x >> 3);
143	hwp->writeSeq(hwp, ((y << 5)|0x11)&0xff, y >> 3);
144}
145
146static void
147AlpLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
148{
149	const AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
150	vgaHWPtr hwp = VGAHWPTR(pScrn);
151
152#ifdef ALP_DEBUG
153	ErrorF("AlpLoadCursorImage\n");
154#endif
155
156	pAlp->CursorBits = bits;
157	memcpy(pAlp->HWCursorBits, bits, 2*CURSORSIZE);
158	/* this should work for both 64 and 32 bit cursors */
159	pAlp->ModeReg.ExtVga[SR13] = 0x3f;
160	hwp->writeSeq(hwp, 0x13, pAlp->ModeReg.ExtVga[SR13]);
161}
162
163static void
164AlpHideCursor(ScrnInfoPtr pScrn)
165{
166	AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
167	vgaHWPtr hwp = VGAHWPTR(pScrn);
168
169#ifdef ALP_DEBUG
170	ErrorF("AlpHideCursor\n");
171#endif
172	pAlp->ModeReg.ExtVga[SR12] &= ~0x01;
173	hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
174}
175
176static void
177AlpShowCursor(ScrnInfoPtr pScrn)
178{
179	AlpPtr pAlp = ALPPTR(CIRPTR(pScrn));
180	vgaHWPtr hwp = VGAHWPTR(pScrn);
181
182#ifdef ALP_DEBUG
183	ErrorF("AlpShowCursor\n");
184#endif
185	pAlp->ModeReg.ExtVga[SR12] |= 0x01;
186	hwp->writeSeq(hwp, 0x12, pAlp->ModeReg.ExtVga[SR12]);
187}
188
189static Bool
190AlpUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
191{
192	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
193#ifdef ALP_DEBUG
194	ErrorF("AlpUseHWCursor\n");
195#endif
196	if (pScrn->bitsPerPixel < 8)
197		return FALSE;
198
199	return TRUE;
200}
201
202Bool
203AlpHWCursorInit(ScreenPtr pScreen, int size)
204{
205	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
206	const CirPtr pCir = CIRPTR(pScrn);
207	const AlpPtr pAlp = ALPPTR(pCir);
208
209	xf86CursorInfoPtr infoPtr;
210
211#ifdef ALP_DEBUG
212	ErrorF("AlpHWCursorInit\n");
213#endif
214	if (!size) return FALSE;
215
216	infoPtr = xf86CreateCursorInfoRec();
217	if (!infoPtr) return FALSE;
218
219	pCir->CursorInfoRec = infoPtr;
220	pCir->CursorIsSkewed = FALSE;
221	pAlp->CursorBits = NULL;
222
223	if (size == 64)
224	    CURSORWIDTH = CURSORHEIGHT = 64;
225	else
226	    CURSORWIDTH = CURSORHEIGHT = 32;
227
228	pAlp->HWCursorBits = pCir->FbBase + 1024*pScrn->videoRam - 2*CURSORSIZE;
229
230	infoPtr->MaxWidth = CURSORWIDTH;
231	infoPtr->MaxHeight = CURSORHEIGHT;
232	if (CURSORWIDTH == 64)
233	    infoPtr->Flags =
234#if X_BYTE_ORDER == X_LITTLE_ENDIAN
235		    HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
236#endif
237		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 |
238		    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
239	else
240		infoPtr->Flags =
241#if X_BYTE_ORDER == X_LITTLE_ENDIAN
242		    HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
243#endif
244		    HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
245
246	infoPtr->SetCursorColors = AlpSetCursorColors;
247	infoPtr->SetCursorPosition = AlpSetCursorPosition;
248	infoPtr->LoadCursorImage = AlpLoadCursorImage;
249	infoPtr->HideCursor = AlpHideCursor;
250	infoPtr->ShowCursor = AlpShowCursor;
251	infoPtr->UseHWCursor = AlpUseHWCursor;
252
253#ifdef ALP_DEBUG
254	ErrorF("AlpHWCursorInit before xf86InitCursor\n");
255#endif
256	xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Hardware cursor: %ix%i\n",
257		   CURSORWIDTH,CURSORHEIGHT);
258	return(xf86InitCursor(pScreen, infoPtr));
259}
260
261
262