neo_cursor.c revision 692f60a7
1692f60a7Smrg/**********************************************************************
2692f60a7SmrgCopyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas.
3692f60a7Smrg
4692f60a7Smrg                        All Rights Reserved
5692f60a7Smrg
6692f60a7SmrgPermission to use, copy, modify, distribute, and sell this software and
7692f60a7Smrgits documentation for any purpose is hereby granted without fee,
8692f60a7Smrgprovided that the above copyright notice appear in all copies and that
9692f60a7Smrgboth that copyright notice and this permission notice appear in
10692f60a7Smrgsupporting documentation, and that the name of Precision Insight not be
11692f60a7Smrgused in advertising or publicity pertaining to distribution of the
12692f60a7Smrgsoftware without specific, written prior permission.  Precision Insight
13692f60a7Smrgand its suppliers make no representations about the suitability of this
14692f60a7Smrgsoftware for any purpose.  It is provided "as is" without express or
15692f60a7Smrgimplied warranty.
16692f60a7Smrg
17692f60a7SmrgPRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18692f60a7SmrgINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19692f60a7SmrgEVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
20692f60a7SmrgSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21692f60a7SmrgRESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
22692f60a7SmrgCONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23692f60a7SmrgCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24692f60a7Smrg**********************************************************************/
25692f60a7Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/neomagic/neo_cursor.c,v 1.8 2001/10/28 03:33:42 tsi Exp $ */
26692f60a7Smrg
27692f60a7Smrg/*
28692f60a7Smrg * The original Precision Insight driver for
29692f60a7Smrg * XFree86 v.3.3 has been sponsored by Red Hat.
30692f60a7Smrg *
31692f60a7Smrg * Authors:
32692f60a7Smrg *   Jens Owen (jens@tungstengraphics.com)
33692f60a7Smrg *   Kevin E. Martin (kevin@precisioninsight.com)
34692f60a7Smrg *
35692f60a7Smrg * Port to Xfree86 v.4.0
36692f60a7Smrg *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
37692f60a7Smrg */
38692f60a7Smrg
39692f60a7Smrg#ifdef HAVE_CONFIG_H
40692f60a7Smrg#include "config.h"
41692f60a7Smrg#endif
42692f60a7Smrg
43692f60a7Smrg/* All drivers should typically include these */
44692f60a7Smrg#include "xf86.h"
45692f60a7Smrg#include "xf86_OSproc.h"
46692f60a7Smrg#include "vgaHW.h"
47692f60a7Smrg
48692f60a7Smrg#include "xf86Cursor.h"
49692f60a7Smrg#include "cursorstr.h"
50692f60a7Smrg/* Driver specific headers */
51692f60a7Smrg#include "neo.h"
52692f60a7Smrg
53692f60a7Smrgstatic void _neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src,
54692f60a7Smrg				int xoff, int yoff);
55692f60a7Smrg
56692f60a7Smrgvoid
57692f60a7SmrgNeoShowCursor(ScrnInfoPtr pScrn)
58692f60a7Smrg{
59692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
60692f60a7Smrg
61692f60a7Smrg    /* turn cursor on */
62692f60a7Smrg    OUTREG(NEOREG_CURSCNTL, NEO_CURS_ENABLE);
63692f60a7Smrg    nPtr->NeoHWCursorShown = TRUE;
64692f60a7Smrg}
65692f60a7Smrg
66692f60a7Smrgvoid
67692f60a7SmrgNeoHideCursor(ScrnInfoPtr pScrn)
68692f60a7Smrg{
69692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
70692f60a7Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
71692f60a7Smrg
72692f60a7Smrg    /*
73692f60a7Smrg     * turn cursor off
74692f60a7Smrg     *
75692f60a7Smrg     * Sometimes we loose the I/O map, so directly use I/O here
76692f60a7Smrg     */
77692f60a7Smrg
78692f60a7Smrg    VGAwGR(0x82,0x00);
79692f60a7Smrg
80692f60a7Smrg    nPtr->NeoHWCursorShown = FALSE;
81692f60a7Smrg}
82692f60a7Smrg
83692f60a7Smrg#define MAX_CURS 64
84692f60a7Smrg
85692f60a7Smrg#define REVBITS_32(__b) { \
86692f60a7Smrg  ((unsigned char *)&__b)[0] = byte_reversed[((unsigned char *)&__b)[0]]; \
87692f60a7Smrg  ((unsigned char *)&__b)[1] = byte_reversed[((unsigned char *)&__b)[1]]; \
88692f60a7Smrg  ((unsigned char *)&__b)[2] = byte_reversed[((unsigned char *)&__b)[2]]; \
89692f60a7Smrg  ((unsigned char *)&__b)[3] = byte_reversed[((unsigned char *)&__b)[3]]; \
90692f60a7Smrg}
91692f60a7Smrg
92692f60a7Smrgstatic void
93692f60a7SmrgneoSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
94692f60a7Smrg{
95692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
96692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
97692f60a7Smrg    int i;
98692f60a7Smrg    CARD32 bits, bits2;
99692f60a7Smrg    unsigned char *_dest = ((unsigned char *)nPtr->NeoFbBase +
100692f60a7Smrg			    nAcl->CursorAddress);
101692f60a7Smrg    unsigned char *src = nPtr->NeoCursorImage;
102692f60a7Smrg    int xoff = 0, yoff = 0;
103692f60a7Smrg
104692f60a7Smrg    if ((y < 0) && (y > (-MAX_CURS))) {
105692f60a7Smrg	yoff = -y;
106692f60a7Smrg	y = 0;
107692f60a7Smrg    }
108692f60a7Smrg    if ((x < 0) && (x > (-MAX_CURS))) {
109692f60a7Smrg	xoff = -x;
110692f60a7Smrg	x = 0;
111692f60a7Smrg    }
112692f60a7Smrg    if (yoff != nPtr->NeoCursorPrevY || xoff !=nPtr->NeoCursorPrevX) {
113692f60a7Smrg	nPtr->NeoCursorPrevY = yoff;
114692f60a7Smrg	nPtr->NeoCursorPrevX = xoff;
115692f60a7Smrg
116692f60a7Smrg        /* This is for sprites that move off the top of the display.
117692f60a7Smrg	 * this code simply updates the pointer used for loading the sprite.
118692f60a7Smrg	 * Note, in our driver's RealizeCursor, the allocated buffer size
119692f60a7Smrg	 * is twice as large as needed, and we initialize the upper half to all
120692f60a7Smrg	 * zeros, so we can use this pointer trick here.
121692f60a7Smrg	 */
122692f60a7Smrg
123692f60a7Smrg         if (yoff) {
124692f60a7Smrg	    src += (yoff * 16);
125692f60a7Smrg	 }
126692f60a7Smrg
127692f60a7Smrg	 /* This is for sprites that move off the left edge of the display.
128692f60a7Smrg	  * this code has to do some ugly bit swizzling to generate new cursor
129692f60a7Smrg	  * masks that give the impression the cursor is moving off the screen.
130692f60a7Smrg	  * WARNING: PLATFORM SPECIFIC!  This is 32-bit little endian code!
131692f60a7Smrg	  */
132692f60a7Smrg          if (xoff)
133692f60a7Smrg	    {
134692f60a7Smrg	       if (xoff < 32) { /* offset 1-31 */
135692f60a7Smrg		  for (i=0; i<256; i+=2) {
136692f60a7Smrg		     bits = ((CARD32 *)src)[i];
137692f60a7Smrg		     bits2 = ((CARD32 *)src)[i+1];
138692f60a7Smrg
139692f60a7Smrg		     REVBITS_32(bits);
140692f60a7Smrg		     REVBITS_32(bits2);
141692f60a7Smrg
142692f60a7Smrg		     bits = ((bits >> xoff) | (bits2 << (32-xoff)));
143692f60a7Smrg		     bits2 >>= xoff;
144692f60a7Smrg
145692f60a7Smrg		     REVBITS_32(bits);
146692f60a7Smrg		     REVBITS_32(bits2);
147692f60a7Smrg
148692f60a7Smrg		     ((CARD32 *) nAcl->CursTemp)[i] = bits;
149692f60a7Smrg		     ((CARD32 *) nAcl->CursTemp)[i+1] = bits2;
150692f60a7Smrg		  }
151692f60a7Smrg	       }
152692f60a7Smrg	       else { /* offset 32-63 */
153692f60a7Smrg		  for (i=0; i<256; i+=2) {
154692f60a7Smrg		     bits = ((CARD32 *)src)[i];
155692f60a7Smrg		     bits2 = ((CARD32 *)src)[i+1];
156692f60a7Smrg
157692f60a7Smrg		     REVBITS_32(bits2);
158692f60a7Smrg
159692f60a7Smrg		     bits = (bits2 >> (xoff-32));
160692f60a7Smrg		     bits2 = 0;
161692f60a7Smrg
162692f60a7Smrg		     REVBITS_32(bits);
163692f60a7Smrg
164692f60a7Smrg		     ((CARD32 *)nAcl->CursTemp)[i] = bits;
165692f60a7Smrg		     ((CARD32 *)nAcl->CursTemp)[i+1] = bits2;
166692f60a7Smrg		  }
167692f60a7Smrg	       }
168692f60a7Smrg	       src = nAcl->CursTemp;
169692f60a7Smrg	    }
170692f60a7Smrg       memcpy(_dest, src, 1024);
171692f60a7Smrg       OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8) |
172692f60a7Smrg	      ((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4));
173692f60a7Smrg
174692f60a7Smrg
175692f60a7Smrg    }
176692f60a7Smrg
177692f60a7Smrg    /* Move the cursor */
178692f60a7Smrg    OUTREG(NEOREG_CURSX, x);
179692f60a7Smrg    OUTREG(NEOREG_CURSY, y);
180692f60a7Smrg}
181692f60a7Smrg
182692f60a7Smrgstatic void
183692f60a7SmrgneoSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
184692f60a7Smrg{
185692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
186692f60a7Smrg
187692f60a7Smrg    /* swap blue and red */
188692f60a7Smrg    fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
189692f60a7Smrg    bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
190692f60a7Smrg
191692f60a7Smrg    /* load colors */
192692f60a7Smrg    OUTREG(NEOREG_CURSFGCOLOR, fg);
193692f60a7Smrg    OUTREG(NEOREG_CURSBGCOLOR, bg);
194692f60a7Smrg}
195692f60a7Smrg
196692f60a7Smrgstatic void
197692f60a7Smrg_neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src, int xoff, int yoff)
198692f60a7Smrg{
199692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
200692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(pScrn);
201692f60a7Smrg    int i;
202692f60a7Smrg    unsigned char *_dest, *_src;
203692f60a7Smrg    int _width, _fill;
204692f60a7Smrg
205692f60a7Smrg    for (i = 0; i< nPtr->CursorInfo->MaxHeight - yoff; i++) {
206692f60a7Smrg      _dest = ((unsigned char *)nPtr->NeoFbBase
207692f60a7Smrg	       + nAcl->CursorAddress
208692f60a7Smrg	       + ((nPtr->CursorInfo->MaxWidth >> 2) * i));
209692f60a7Smrg      _width = (nPtr->CursorInfo->MaxWidth
210692f60a7Smrg		- (xoff & 0x38)) >> 3;
211692f60a7Smrg      _src = (src + ((nPtr->CursorInfo->MaxWidth >> 2) * i));
212692f60a7Smrg      _fill = (xoff & 0x38) >> 3;
213692f60a7Smrg
214692f60a7Smrg      memcpy(_dest,_src,_width);
215692f60a7Smrg      memset(_dest + _width, 0, _fill);
216692f60a7Smrg
217692f60a7Smrg      _dest += (nPtr->CursorInfo->MaxWidth >> 3);
218692f60a7Smrg      _src += (nPtr->CursorInfo->MaxWidth >> 3);
219692f60a7Smrg      memcpy(_dest,_src,_width);
220692f60a7Smrg      memset(_dest + _width, 0, _fill);
221692f60a7Smrg    }
222692f60a7Smrg    memset(nPtr->NeoFbBase + nAcl->CursorAddress
223692f60a7Smrg	   + ((nPtr->CursorInfo->MaxWidth >> 2) * i),
224692f60a7Smrg	   0, (nPtr->CursorInfo->MaxHeight - i)
225692f60a7Smrg	   * (nPtr->CursorInfo->MaxWidth >> 2));
226692f60a7Smrg    /* set cursor address here or we loose the cursor on video mode change */
227692f60a7Smrg    /* Load storage location.  */
228692f60a7Smrg    OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8)  |
229692f60a7Smrg	   ((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4));
230692f60a7Smrg}
231692f60a7Smrg
232692f60a7Smrgstatic void
233692f60a7SmrgneoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
234692f60a7Smrg{
235692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
236692f60a7Smrg    nPtr->NeoCursorImage = src;  /* store src address for later use */
237692f60a7Smrg
238692f60a7Smrg    /* Reset these because we have a new cursor image */
239692f60a7Smrg    nPtr->NeoCursorPrevY = nPtr->NeoCursorPrevX = 0;
240692f60a7Smrg
241692f60a7Smrg    _neoLoadCursorImage(pScrn,src,0,0);
242692f60a7Smrg}
243692f60a7Smrg
244692f60a7Smrgstatic Bool
245692f60a7SmrgneoUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
246692f60a7Smrg{
247692f60a7Smrg    NEOACLPtr nAcl = NEOACLPTR(xf86Screens[pScr->myNum]);
248692f60a7Smrg
249692f60a7Smrg    return(nAcl->UseHWCursor && !nAcl->NoCursorMode);
250692f60a7Smrg}
251692f60a7Smrg
252692f60a7Smrgstatic unsigned char*
253692f60a7SmrgneoRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
254692f60a7Smrg{
255692f60a7Smrg    CARD32 *SrcS, *SrcM, *DstS, *DstM;
256692f60a7Smrg    CARD32 *pSrc, *pMsk;
257692f60a7Smrg    unsigned char *mem;
258692f60a7Smrg    int SrcPitch, DstPitch, y, x, z;
259692f60a7Smrg
260692f60a7Smrg    mem = (unsigned char*)xnfcalloc(4096,1);
261692f60a7Smrg    SrcPitch = (pCurs->bits->width + 31) >> 5;
262692f60a7Smrg    DstPitch = infoPtr->MaxWidth >> 4;
263692f60a7Smrg    SrcS = (CARD32*)pCurs->bits->source;
264692f60a7Smrg    SrcM = (CARD32*)pCurs->bits->mask;
265692f60a7Smrg    DstS = (CARD32*)mem;
266692f60a7Smrg    DstM = DstS + (DstPitch >> 1);
267692f60a7Smrg
268692f60a7Smrg    for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
269692f60a7Smrg	y--;
270692f60a7Smrg	pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
271692f60a7Smrg	for(x = 0; x < SrcPitch; x++) {
272692f60a7Smrg	    pSrc[x] = ~SrcS[x] & SrcM[x];
273692f60a7Smrg	    pMsk[x] = SrcM[x];
274692f60a7Smrg	    for (z = 0; z < 4; z++) {
275692f60a7Smrg		((char *)pSrc)[x*4+z] =
276692f60a7Smrg		    byte_reversed[((char *)pSrc)[x*4+z] & 0xFF];
277692f60a7Smrg		((char *)pMsk)[x*4+z] =
278692f60a7Smrg		    byte_reversed[((char *)pMsk)[x*4+z] & 0xFF];
279692f60a7Smrg	    }
280692f60a7Smrg	}
281692f60a7Smrg#if 0
282692f60a7Smrg	for (;x < DstPitch; x++) {
283692f60a7Smrg	    pSrc[x] = 0;
284692f60a7Smrg	    pMsk[x] = 0;
285692f60a7Smrg	}
286692f60a7Smrg#endif
287692f60a7Smrg    }
288692f60a7Smrg
289692f60a7Smrg    return (unsigned char *)mem;
290692f60a7Smrg}
291692f60a7Smrg
292692f60a7SmrgBool
293692f60a7SmrgNeoCursorInit(ScreenPtr pScreen)
294692f60a7Smrg{
295692f60a7Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
296692f60a7Smrg    NEOPtr nPtr = NEOPTR(pScrn);
297692f60a7Smrg    xf86CursorInfoPtr infoPtr;
298692f60a7Smrg    infoPtr = xf86CreateCursorInfoRec();
299692f60a7Smrg    if(!infoPtr) return FALSE;
300692f60a7Smrg
301692f60a7Smrg    nPtr->CursorInfo = infoPtr;
302692f60a7Smrg
303692f60a7Smrg    infoPtr->MaxHeight = 64;
304692f60a7Smrg    infoPtr->MaxWidth = 64;
305692f60a7Smrg    infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
306692f60a7Smrg
307692f60a7Smrg    infoPtr->SetCursorColors = neoSetCursorColors;
308692f60a7Smrg    infoPtr->SetCursorPosition = neoSetCursorPosition;
309692f60a7Smrg    infoPtr->LoadCursorImage = neoLoadCursorImage;
310692f60a7Smrg    infoPtr->HideCursor = NeoHideCursor;
311692f60a7Smrg    infoPtr->ShowCursor = NeoShowCursor;
312692f60a7Smrg    infoPtr->UseHWCursor = neoUseHWCursor;
313692f60a7Smrg    infoPtr->RealizeCursor = neoRealizeCursor;
314692f60a7Smrg
315692f60a7Smrg    return(xf86InitCursor(pScreen, infoPtr));
316692f60a7Smrg}
317692f60a7Smrg
318692f60a7Smrg
319692f60a7Smrg
320