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 26692f60a7Smrg/* 27692f60a7Smrg * The original Precision Insight driver for 28692f60a7Smrg * XFree86 v.3.3 has been sponsored by Red Hat. 29692f60a7Smrg * 30692f60a7Smrg * Authors: 31692f60a7Smrg * Jens Owen (jens@tungstengraphics.com) 32692f60a7Smrg * Kevin E. Martin (kevin@precisioninsight.com) 33692f60a7Smrg * 34692f60a7Smrg * Port to Xfree86 v.4.0 35692f60a7Smrg * 1998, 1999 by Egbert Eich (Egbert.Eich@Physik.TU-Darmstadt.DE) 36692f60a7Smrg */ 37692f60a7Smrg 38692f60a7Smrg#ifdef HAVE_CONFIG_H 39692f60a7Smrg#include "config.h" 40692f60a7Smrg#endif 41692f60a7Smrg 42692f60a7Smrg/* All drivers should typically include these */ 43692f60a7Smrg#include "xf86.h" 44692f60a7Smrg#include "xf86_OSproc.h" 45692f60a7Smrg#include "vgaHW.h" 46692f60a7Smrg 47692f60a7Smrg#include "xf86Cursor.h" 48692f60a7Smrg#include "cursorstr.h" 49692f60a7Smrg/* Driver specific headers */ 50692f60a7Smrg#include "neo.h" 51692f60a7Smrg 52692f60a7Smrgstatic void _neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src, 53692f60a7Smrg int xoff, int yoff); 54692f60a7Smrg 55692f60a7Smrgvoid 56692f60a7SmrgNeoShowCursor(ScrnInfoPtr pScrn) 57692f60a7Smrg{ 58692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 59692f60a7Smrg 60692f60a7Smrg /* turn cursor on */ 61692f60a7Smrg OUTREG(NEOREG_CURSCNTL, NEO_CURS_ENABLE); 62692f60a7Smrg nPtr->NeoHWCursorShown = TRUE; 63692f60a7Smrg} 64692f60a7Smrg 65692f60a7Smrgvoid 66692f60a7SmrgNeoHideCursor(ScrnInfoPtr pScrn) 67692f60a7Smrg{ 68692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 69692f60a7Smrg vgaHWPtr hwp = VGAHWPTR(pScrn); 70692f60a7Smrg 71692f60a7Smrg /* 72692f60a7Smrg * turn cursor off 73692f60a7Smrg * 74692f60a7Smrg * Sometimes we loose the I/O map, so directly use I/O here 75692f60a7Smrg */ 76692f60a7Smrg 77692f60a7Smrg VGAwGR(0x82,0x00); 78692f60a7Smrg 79692f60a7Smrg nPtr->NeoHWCursorShown = FALSE; 80692f60a7Smrg} 81692f60a7Smrg 82692f60a7Smrg#define MAX_CURS 64 83692f60a7Smrg 84692f60a7Smrg#define REVBITS_32(__b) { \ 85692f60a7Smrg ((unsigned char *)&__b)[0] = byte_reversed[((unsigned char *)&__b)[0]]; \ 86692f60a7Smrg ((unsigned char *)&__b)[1] = byte_reversed[((unsigned char *)&__b)[1]]; \ 87692f60a7Smrg ((unsigned char *)&__b)[2] = byte_reversed[((unsigned char *)&__b)[2]]; \ 88692f60a7Smrg ((unsigned char *)&__b)[3] = byte_reversed[((unsigned char *)&__b)[3]]; \ 89692f60a7Smrg} 90692f60a7Smrg 91692f60a7Smrgstatic void 92692f60a7SmrgneoSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 93692f60a7Smrg{ 94692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 95692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 96692f60a7Smrg int i; 97692f60a7Smrg CARD32 bits, bits2; 98692f60a7Smrg unsigned char *_dest = ((unsigned char *)nPtr->NeoFbBase + 99692f60a7Smrg nAcl->CursorAddress); 100692f60a7Smrg unsigned char *src = nPtr->NeoCursorImage; 101692f60a7Smrg int xoff = 0, yoff = 0; 102692f60a7Smrg 103692f60a7Smrg if ((y < 0) && (y > (-MAX_CURS))) { 104692f60a7Smrg yoff = -y; 105692f60a7Smrg y = 0; 106692f60a7Smrg } 107692f60a7Smrg if ((x < 0) && (x > (-MAX_CURS))) { 108692f60a7Smrg xoff = -x; 109692f60a7Smrg x = 0; 110692f60a7Smrg } 111692f60a7Smrg if (yoff != nPtr->NeoCursorPrevY || xoff !=nPtr->NeoCursorPrevX) { 112692f60a7Smrg nPtr->NeoCursorPrevY = yoff; 113692f60a7Smrg nPtr->NeoCursorPrevX = xoff; 114692f60a7Smrg 115692f60a7Smrg /* This is for sprites that move off the top of the display. 116692f60a7Smrg * this code simply updates the pointer used for loading the sprite. 117692f60a7Smrg * Note, in our driver's RealizeCursor, the allocated buffer size 118692f60a7Smrg * is twice as large as needed, and we initialize the upper half to all 119692f60a7Smrg * zeros, so we can use this pointer trick here. 120692f60a7Smrg */ 121692f60a7Smrg 122692f60a7Smrg if (yoff) { 123692f60a7Smrg src += (yoff * 16); 124692f60a7Smrg } 125692f60a7Smrg 126692f60a7Smrg /* This is for sprites that move off the left edge of the display. 127692f60a7Smrg * this code has to do some ugly bit swizzling to generate new cursor 128692f60a7Smrg * masks that give the impression the cursor is moving off the screen. 129692f60a7Smrg * WARNING: PLATFORM SPECIFIC! This is 32-bit little endian code! 130692f60a7Smrg */ 131692f60a7Smrg if (xoff) 132692f60a7Smrg { 133692f60a7Smrg if (xoff < 32) { /* offset 1-31 */ 134692f60a7Smrg for (i=0; i<256; i+=2) { 135692f60a7Smrg bits = ((CARD32 *)src)[i]; 136692f60a7Smrg bits2 = ((CARD32 *)src)[i+1]; 137692f60a7Smrg 138692f60a7Smrg REVBITS_32(bits); 139692f60a7Smrg REVBITS_32(bits2); 140692f60a7Smrg 141692f60a7Smrg bits = ((bits >> xoff) | (bits2 << (32-xoff))); 142692f60a7Smrg bits2 >>= xoff; 143692f60a7Smrg 144692f60a7Smrg REVBITS_32(bits); 145692f60a7Smrg REVBITS_32(bits2); 146692f60a7Smrg 147692f60a7Smrg ((CARD32 *) nAcl->CursTemp)[i] = bits; 148692f60a7Smrg ((CARD32 *) nAcl->CursTemp)[i+1] = bits2; 149692f60a7Smrg } 150692f60a7Smrg } 151692f60a7Smrg else { /* offset 32-63 */ 152692f60a7Smrg for (i=0; i<256; i+=2) { 153692f60a7Smrg bits = ((CARD32 *)src)[i]; 154692f60a7Smrg bits2 = ((CARD32 *)src)[i+1]; 155692f60a7Smrg 156692f60a7Smrg REVBITS_32(bits2); 157692f60a7Smrg 158692f60a7Smrg bits = (bits2 >> (xoff-32)); 159692f60a7Smrg bits2 = 0; 160692f60a7Smrg 161692f60a7Smrg REVBITS_32(bits); 162692f60a7Smrg 163692f60a7Smrg ((CARD32 *)nAcl->CursTemp)[i] = bits; 164692f60a7Smrg ((CARD32 *)nAcl->CursTemp)[i+1] = bits2; 165692f60a7Smrg } 166692f60a7Smrg } 167692f60a7Smrg src = nAcl->CursTemp; 168692f60a7Smrg } 169692f60a7Smrg memcpy(_dest, src, 1024); 170692f60a7Smrg OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8) | 171692f60a7Smrg ((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4)); 172692f60a7Smrg 173692f60a7Smrg 174692f60a7Smrg } 175692f60a7Smrg 176692f60a7Smrg /* Move the cursor */ 177692f60a7Smrg OUTREG(NEOREG_CURSX, x); 178692f60a7Smrg OUTREG(NEOREG_CURSY, y); 179692f60a7Smrg} 180692f60a7Smrg 181692f60a7Smrgstatic void 182692f60a7SmrgneoSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 183692f60a7Smrg{ 184692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 185692f60a7Smrg 186692f60a7Smrg /* swap blue and red */ 187692f60a7Smrg fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00); 188692f60a7Smrg bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00); 189692f60a7Smrg 190692f60a7Smrg /* load colors */ 191692f60a7Smrg OUTREG(NEOREG_CURSFGCOLOR, fg); 192692f60a7Smrg OUTREG(NEOREG_CURSBGCOLOR, bg); 193692f60a7Smrg} 194692f60a7Smrg 195692f60a7Smrgstatic void 196692f60a7Smrg_neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src, int xoff, int yoff) 197692f60a7Smrg{ 198692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 199692f60a7Smrg NEOACLPtr nAcl = NEOACLPTR(pScrn); 200692f60a7Smrg int i; 201692f60a7Smrg unsigned char *_dest, *_src; 202692f60a7Smrg int _width, _fill; 203692f60a7Smrg 204692f60a7Smrg for (i = 0; i< nPtr->CursorInfo->MaxHeight - yoff; i++) { 205692f60a7Smrg _dest = ((unsigned char *)nPtr->NeoFbBase 206692f60a7Smrg + nAcl->CursorAddress 207692f60a7Smrg + ((nPtr->CursorInfo->MaxWidth >> 2) * i)); 208692f60a7Smrg _width = (nPtr->CursorInfo->MaxWidth 209692f60a7Smrg - (xoff & 0x38)) >> 3; 210692f60a7Smrg _src = (src + ((nPtr->CursorInfo->MaxWidth >> 2) * i)); 211692f60a7Smrg _fill = (xoff & 0x38) >> 3; 212692f60a7Smrg 213692f60a7Smrg memcpy(_dest,_src,_width); 214692f60a7Smrg memset(_dest + _width, 0, _fill); 215692f60a7Smrg 216692f60a7Smrg _dest += (nPtr->CursorInfo->MaxWidth >> 3); 217692f60a7Smrg _src += (nPtr->CursorInfo->MaxWidth >> 3); 218692f60a7Smrg memcpy(_dest,_src,_width); 219692f60a7Smrg memset(_dest + _width, 0, _fill); 220692f60a7Smrg } 221692f60a7Smrg memset(nPtr->NeoFbBase + nAcl->CursorAddress 222692f60a7Smrg + ((nPtr->CursorInfo->MaxWidth >> 2) * i), 223692f60a7Smrg 0, (nPtr->CursorInfo->MaxHeight - i) 224692f60a7Smrg * (nPtr->CursorInfo->MaxWidth >> 2)); 225692f60a7Smrg /* set cursor address here or we loose the cursor on video mode change */ 226692f60a7Smrg /* Load storage location. */ 227692f60a7Smrg OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8) | 228692f60a7Smrg ((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4)); 229692f60a7Smrg} 230692f60a7Smrg 231692f60a7Smrgstatic void 232692f60a7SmrgneoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 233692f60a7Smrg{ 234692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 235692f60a7Smrg nPtr->NeoCursorImage = src; /* store src address for later use */ 236692f60a7Smrg 237692f60a7Smrg /* Reset these because we have a new cursor image */ 238692f60a7Smrg nPtr->NeoCursorPrevY = nPtr->NeoCursorPrevX = 0; 239692f60a7Smrg 240692f60a7Smrg _neoLoadCursorImage(pScrn,src,0,0); 241692f60a7Smrg} 242692f60a7Smrg 243692f60a7Smrgstatic Bool 244692f60a7SmrgneoUseHWCursor(ScreenPtr pScr, CursorPtr pCurs) 245692f60a7Smrg{ 2463f6d0e1dSmrg NEOACLPtr nAcl = NEOACLPTR(xf86ScreenToScrn(pScr)); 247692f60a7Smrg 248692f60a7Smrg return(nAcl->UseHWCursor && !nAcl->NoCursorMode); 249692f60a7Smrg} 250692f60a7Smrg 251692f60a7Smrgstatic unsigned char* 252692f60a7SmrgneoRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs) 253692f60a7Smrg{ 254692f60a7Smrg CARD32 *SrcS, *SrcM, *DstS, *DstM; 255692f60a7Smrg CARD32 *pSrc, *pMsk; 256692f60a7Smrg unsigned char *mem; 257692f60a7Smrg int SrcPitch, DstPitch, y, x, z; 258692f60a7Smrg 259692f60a7Smrg mem = (unsigned char*)xnfcalloc(4096,1); 260692f60a7Smrg SrcPitch = (pCurs->bits->width + 31) >> 5; 261692f60a7Smrg DstPitch = infoPtr->MaxWidth >> 4; 262692f60a7Smrg SrcS = (CARD32*)pCurs->bits->source; 263692f60a7Smrg SrcM = (CARD32*)pCurs->bits->mask; 264692f60a7Smrg DstS = (CARD32*)mem; 265692f60a7Smrg DstM = DstS + (DstPitch >> 1); 266692f60a7Smrg 267692f60a7Smrg for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM; 268692f60a7Smrg y--; 269692f60a7Smrg pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) { 270692f60a7Smrg for(x = 0; x < SrcPitch; x++) { 271692f60a7Smrg pSrc[x] = ~SrcS[x] & SrcM[x]; 272692f60a7Smrg pMsk[x] = SrcM[x]; 273692f60a7Smrg for (z = 0; z < 4; z++) { 274692f60a7Smrg ((char *)pSrc)[x*4+z] = 275692f60a7Smrg byte_reversed[((char *)pSrc)[x*4+z] & 0xFF]; 276692f60a7Smrg ((char *)pMsk)[x*4+z] = 277692f60a7Smrg byte_reversed[((char *)pMsk)[x*4+z] & 0xFF]; 278692f60a7Smrg } 279692f60a7Smrg } 280692f60a7Smrg#if 0 281692f60a7Smrg for (;x < DstPitch; x++) { 282692f60a7Smrg pSrc[x] = 0; 283692f60a7Smrg pMsk[x] = 0; 284692f60a7Smrg } 285692f60a7Smrg#endif 286692f60a7Smrg } 287692f60a7Smrg 288692f60a7Smrg return (unsigned char *)mem; 289692f60a7Smrg} 290692f60a7Smrg 291692f60a7SmrgBool 292692f60a7SmrgNeoCursorInit(ScreenPtr pScreen) 293692f60a7Smrg{ 2943f6d0e1dSmrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 295692f60a7Smrg NEOPtr nPtr = NEOPTR(pScrn); 296692f60a7Smrg xf86CursorInfoPtr infoPtr; 297692f60a7Smrg infoPtr = xf86CreateCursorInfoRec(); 298692f60a7Smrg if(!infoPtr) return FALSE; 299692f60a7Smrg 300692f60a7Smrg nPtr->CursorInfo = infoPtr; 301692f60a7Smrg 302692f60a7Smrg infoPtr->MaxHeight = 64; 303692f60a7Smrg infoPtr->MaxWidth = 64; 304692f60a7Smrg infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP; 305692f60a7Smrg 306692f60a7Smrg infoPtr->SetCursorColors = neoSetCursorColors; 307692f60a7Smrg infoPtr->SetCursorPosition = neoSetCursorPosition; 308692f60a7Smrg infoPtr->LoadCursorImage = neoLoadCursorImage; 309692f60a7Smrg infoPtr->HideCursor = NeoHideCursor; 310692f60a7Smrg infoPtr->ShowCursor = NeoShowCursor; 311692f60a7Smrg infoPtr->UseHWCursor = neoUseHWCursor; 312692f60a7Smrg infoPtr->RealizeCursor = neoRealizeCursor; 313692f60a7Smrg 314692f60a7Smrg return(xf86InitCursor(pScreen, infoPtr)); 315692f60a7Smrg} 316692f60a7Smrg 317692f60a7Smrg 318692f60a7Smrg 319