1 /**********************************************************************
2 Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas.
3 
4                         All Rights Reserved
5 
6 Permission to use, copy, modify, distribute, and sell this software and
7 its documentation for any purpose is hereby granted without fee,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of Precision Insight not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.  Precision Insight
13 and its suppliers make no representations about the suitability of this
14 software for any purpose.  It is provided "as is" without express or
15 implied warranty.
16 
17 PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
20 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
21 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
22 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
23 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 **********************************************************************/
25 
26 /*
27  * The original Precision Insight driver for
28  * XFree86 v.3.3 has been sponsored by Red Hat.
29  *
30  * Authors:
31  *   Jens Owen (jens@tungstengraphics.com)
32  *   Kevin E. Martin (kevin@precisioninsight.com)
33  *
34  * Port to Xfree86 v.4.0
35  *   1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE)
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #include "config.h"
40 #endif
41 
42 /* All drivers should typically include these */
43 #include "xf86.h"
44 #include "xf86_OSproc.h"
45 #include "vgaHW.h"
46 
47 #include "xf86Cursor.h"
48 #include "cursorstr.h"
49 /* Driver specific headers */
50 #include "neo.h"
51 
52 static void _neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src,
53 				int xoff, int yoff);
54 
55 void
NeoShowCursor(ScrnInfoPtr pScrn)56 NeoShowCursor(ScrnInfoPtr pScrn)
57 {
58     NEOPtr nPtr = NEOPTR(pScrn);
59 
60     /* turn cursor on */
61     OUTREG(NEOREG_CURSCNTL, NEO_CURS_ENABLE);
62     nPtr->NeoHWCursorShown = TRUE;
63 }
64 
65 void
NeoHideCursor(ScrnInfoPtr pScrn)66 NeoHideCursor(ScrnInfoPtr pScrn)
67 {
68     NEOPtr nPtr = NEOPTR(pScrn);
69     vgaHWPtr hwp = VGAHWPTR(pScrn);
70 
71     /*
72      * turn cursor off
73      *
74      * Sometimes we loose the I/O map, so directly use I/O here
75      */
76 
77     VGAwGR(0x82,0x00);
78 
79     nPtr->NeoHWCursorShown = FALSE;
80 }
81 
82 #define MAX_CURS 64
83 
84 #define REVBITS_32(__b) { \
85   ((unsigned char *)&__b)[0] = byte_reversed[((unsigned char *)&__b)[0]]; \
86   ((unsigned char *)&__b)[1] = byte_reversed[((unsigned char *)&__b)[1]]; \
87   ((unsigned char *)&__b)[2] = byte_reversed[((unsigned char *)&__b)[2]]; \
88   ((unsigned char *)&__b)[3] = byte_reversed[((unsigned char *)&__b)[3]]; \
89 }
90 
91 static void
neoSetCursorPosition(ScrnInfoPtr pScrn,int x,int y)92 neoSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
93 {
94     NEOPtr nPtr = NEOPTR(pScrn);
95     NEOACLPtr nAcl = NEOACLPTR(pScrn);
96     int i;
97     CARD32 bits, bits2;
98     unsigned char *_dest = ((unsigned char *)nPtr->NeoFbBase +
99 			    nAcl->CursorAddress);
100     unsigned char *src = nPtr->NeoCursorImage;
101     int xoff = 0, yoff = 0;
102 
103     if ((y < 0) && (y > (-MAX_CURS))) {
104 	yoff = -y;
105 	y = 0;
106     }
107     if ((x < 0) && (x > (-MAX_CURS))) {
108 	xoff = -x;
109 	x = 0;
110     }
111     if (yoff != nPtr->NeoCursorPrevY || xoff !=nPtr->NeoCursorPrevX) {
112 	nPtr->NeoCursorPrevY = yoff;
113 	nPtr->NeoCursorPrevX = xoff;
114 
115         /* This is for sprites that move off the top of the display.
116 	 * this code simply updates the pointer used for loading the sprite.
117 	 * Note, in our driver's RealizeCursor, the allocated buffer size
118 	 * is twice as large as needed, and we initialize the upper half to all
119 	 * zeros, so we can use this pointer trick here.
120 	 */
121 
122          if (yoff) {
123 	    src += (yoff * 16);
124 	 }
125 
126 	 /* This is for sprites that move off the left edge of the display.
127 	  * this code has to do some ugly bit swizzling to generate new cursor
128 	  * masks that give the impression the cursor is moving off the screen.
129 	  * WARNING: PLATFORM SPECIFIC!  This is 32-bit little endian code!
130 	  */
131           if (xoff)
132 	    {
133 	       if (xoff < 32) { /* offset 1-31 */
134 		  for (i=0; i<256; i+=2) {
135 		     bits = ((CARD32 *)src)[i];
136 		     bits2 = ((CARD32 *)src)[i+1];
137 
138 		     REVBITS_32(bits);
139 		     REVBITS_32(bits2);
140 
141 		     bits = ((bits >> xoff) | (bits2 << (32-xoff)));
142 		     bits2 >>= xoff;
143 
144 		     REVBITS_32(bits);
145 		     REVBITS_32(bits2);
146 
147 		     ((CARD32 *) nAcl->CursTemp)[i] = bits;
148 		     ((CARD32 *) nAcl->CursTemp)[i+1] = bits2;
149 		  }
150 	       }
151 	       else { /* offset 32-63 */
152 		  for (i=0; i<256; i+=2) {
153 		     bits = ((CARD32 *)src)[i];
154 		     bits2 = ((CARD32 *)src)[i+1];
155 
156 		     REVBITS_32(bits2);
157 
158 		     bits = (bits2 >> (xoff-32));
159 		     bits2 = 0;
160 
161 		     REVBITS_32(bits);
162 
163 		     ((CARD32 *)nAcl->CursTemp)[i] = bits;
164 		     ((CARD32 *)nAcl->CursTemp)[i+1] = bits2;
165 		  }
166 	       }
167 	       src = nAcl->CursTemp;
168 	    }
169        memcpy(_dest, src, 1024);
170        OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8) |
171 	      ((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4));
172 
173 
174     }
175 
176     /* Move the cursor */
177     OUTREG(NEOREG_CURSX, x);
178     OUTREG(NEOREG_CURSY, y);
179 }
180 
181 static void
neoSetCursorColors(ScrnInfoPtr pScrn,int bg,int fg)182 neoSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
183 {
184     NEOPtr nPtr = NEOPTR(pScrn);
185 
186     /* swap blue and red */
187     fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
188     bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
189 
190     /* load colors */
191     OUTREG(NEOREG_CURSFGCOLOR, fg);
192     OUTREG(NEOREG_CURSBGCOLOR, bg);
193 }
194 
195 static void
_neoLoadCursorImage(ScrnInfoPtr pScrn,unsigned char * src,int xoff,int yoff)196 _neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src, int xoff, int yoff)
197 {
198     NEOPtr nPtr = NEOPTR(pScrn);
199     NEOACLPtr nAcl = NEOACLPTR(pScrn);
200     int i;
201     unsigned char *_dest, *_src;
202     int _width, _fill;
203 
204     for (i = 0; i< nPtr->CursorInfo->MaxHeight - yoff; i++) {
205       _dest = ((unsigned char *)nPtr->NeoFbBase
206 	       + nAcl->CursorAddress
207 	       + ((nPtr->CursorInfo->MaxWidth >> 2) * i));
208       _width = (nPtr->CursorInfo->MaxWidth
209 		- (xoff & 0x38)) >> 3;
210       _src = (src + ((nPtr->CursorInfo->MaxWidth >> 2) * i));
211       _fill = (xoff & 0x38) >> 3;
212 
213       memcpy(_dest,_src,_width);
214       memset(_dest + _width, 0, _fill);
215 
216       _dest += (nPtr->CursorInfo->MaxWidth >> 3);
217       _src += (nPtr->CursorInfo->MaxWidth >> 3);
218       memcpy(_dest,_src,_width);
219       memset(_dest + _width, 0, _fill);
220     }
221     memset(nPtr->NeoFbBase + nAcl->CursorAddress
222 	   + ((nPtr->CursorInfo->MaxWidth >> 2) * i),
223 	   0, (nPtr->CursorInfo->MaxHeight - i)
224 	   * (nPtr->CursorInfo->MaxWidth >> 2));
225     /* set cursor address here or we loose the cursor on video mode change */
226     /* Load storage location.  */
227     OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8)  |
228 	   ((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4));
229 }
230 
231 static void
neoLoadCursorImage(ScrnInfoPtr pScrn,unsigned char * src)232 neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
233 {
234     NEOPtr nPtr = NEOPTR(pScrn);
235     nPtr->NeoCursorImage = src;  /* store src address for later use */
236 
237     /* Reset these because we have a new cursor image */
238     nPtr->NeoCursorPrevY = nPtr->NeoCursorPrevX = 0;
239 
240     _neoLoadCursorImage(pScrn,src,0,0);
241 }
242 
243 static Bool
neoUseHWCursor(ScreenPtr pScr,CursorPtr pCurs)244 neoUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
245 {
246     NEOACLPtr nAcl = NEOACLPTR(xf86ScreenToScrn(pScr));
247 
248     return(nAcl->UseHWCursor && !nAcl->NoCursorMode);
249 }
250 
251 static unsigned char*
neoRealizeCursor(xf86CursorInfoPtr infoPtr,CursorPtr pCurs)252 neoRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
253 {
254     CARD32 *SrcS, *SrcM, *DstS, *DstM;
255     CARD32 *pSrc, *pMsk;
256     unsigned char *mem;
257     int SrcPitch, DstPitch, y, x, z;
258 
259     mem = (unsigned char*)xnfcalloc(4096,1);
260     SrcPitch = (pCurs->bits->width + 31) >> 5;
261     DstPitch = infoPtr->MaxWidth >> 4;
262     SrcS = (CARD32*)pCurs->bits->source;
263     SrcM = (CARD32*)pCurs->bits->mask;
264     DstS = (CARD32*)mem;
265     DstM = DstS + (DstPitch >> 1);
266 
267     for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
268 	y--;
269 	pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
270 	for(x = 0; x < SrcPitch; x++) {
271 	    pSrc[x] = ~SrcS[x] & SrcM[x];
272 	    pMsk[x] = SrcM[x];
273 	    for (z = 0; z < 4; z++) {
274 		((char *)pSrc)[x*4+z] =
275 		    byte_reversed[((char *)pSrc)[x*4+z] & 0xFF];
276 		((char *)pMsk)[x*4+z] =
277 		    byte_reversed[((char *)pMsk)[x*4+z] & 0xFF];
278 	    }
279 	}
280 #if 0
281 	for (;x < DstPitch; x++) {
282 	    pSrc[x] = 0;
283 	    pMsk[x] = 0;
284 	}
285 #endif
286     }
287 
288     return (unsigned char *)mem;
289 }
290 
291 Bool
NeoCursorInit(ScreenPtr pScreen)292 NeoCursorInit(ScreenPtr pScreen)
293 {
294     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
295     NEOPtr nPtr = NEOPTR(pScrn);
296     xf86CursorInfoPtr infoPtr;
297     infoPtr = xf86CreateCursorInfoRec();
298     if(!infoPtr) return FALSE;
299 
300     nPtr->CursorInfo = infoPtr;
301 
302     infoPtr->MaxHeight = 64;
303     infoPtr->MaxWidth = 64;
304     infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
305 
306     infoPtr->SetCursorColors = neoSetCursorColors;
307     infoPtr->SetCursorPosition = neoSetCursorPosition;
308     infoPtr->LoadCursorImage = neoLoadCursorImage;
309     infoPtr->HideCursor = NeoHideCursor;
310     infoPtr->ShowCursor = NeoShowCursor;
311     infoPtr->UseHWCursor = neoUseHWCursor;
312     infoPtr->RealizeCursor = neoRealizeCursor;
313 
314     return(xf86InitCursor(pScreen, infoPtr));
315 }
316 
317 
318 
319