1/********************************************************************** 2Copyright 1998, 1999 by Precision Insight, Inc., Cedar Park, Texas. 3 4 All Rights Reserved 5 6Permission to use, copy, modify, distribute, and sell this software and 7its documentation for any purpose is hereby granted without fee, 8provided that the above copyright notice appear in all copies and that 9both that copyright notice and this permission notice appear in 10supporting documentation, and that the name of Precision Insight not be 11used in advertising or publicity pertaining to distribution of the 12software without specific, written prior permission. Precision Insight 13and its suppliers make no representations about the suitability of this 14software for any purpose. It is provided "as is" without express or 15implied warranty. 16 17PRECISION INSIGHT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY 20SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER 21RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF 22CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 23CONNECTION 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 52static void _neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src, 53 int xoff, int yoff); 54 55void 56NeoShowCursor(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 65void 66NeoHideCursor(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 91static void 92neoSetCursorPosition(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 181static void 182neoSetCursorColors(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 195static void 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 231static void 232neoLoadCursorImage(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 243static Bool 244neoUseHWCursor(ScreenPtr pScr, CursorPtr pCurs) 245{ 246 NEOACLPtr nAcl = NEOACLPTR(xf86ScreenToScrn(pScr)); 247 248 return(nAcl->UseHWCursor && !nAcl->NoCursorMode); 249} 250 251static unsigned char* 252neoRealizeCursor(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 291Bool 292NeoCursorInit(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