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