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