#include "xf86.h"
#include "xf86_OSproc.h"
#include "xf86_ansic.h"
#include "vgaHW.h"
#include "xf86Cursor.h"
#include "cursorstr.h"
#include "neo.h"
static void _neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src,
int xoff, int yoff);
void
NeoShowCursor(ScrnInfoPtr pScrn)
{
NEOPtr nPtr = NEOPTR(pScrn);
OUTREG(NEOREG_CURSCNTL, NEO_CURS_ENABLE);
nPtr->NeoHWCursorShown = TRUE;
}
void
NeoHideCursor(ScrnInfoPtr pScrn)
{
NEOPtr nPtr = NEOPTR(pScrn);
vgaHWPtr hwp = VGAHWPTR(pScrn);
VGAwGR(0x82,0x00);
nPtr->NeoHWCursorShown = FALSE;
}
#define MAX_CURS 64
#define REVBITS_32(__b) { \
((unsigned char *)&__b)[0] = byte_reversed[((unsigned char *)&__b)[0]]; \
((unsigned char *)&__b)[1] = byte_reversed[((unsigned char *)&__b)[1]]; \
((unsigned char *)&__b)[2] = byte_reversed[((unsigned char *)&__b)[2]]; \
((unsigned char *)&__b)[3] = byte_reversed[((unsigned char *)&__b)[3]]; \
}
static void
neoSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
int i;
CARD32 bits, bits2;
unsigned char *_dest = ((unsigned char *)nPtr->NeoFbBase +
nAcl->CursorAddress);
unsigned char *src = nPtr->NeoCursorImage;
int xoff = 0, yoff = 0;
if ((y < 0) && (y > (-MAX_CURS))) {
yoff = -y;
y = 0;
}
if ((x < 0) && (x > (-MAX_CURS))) {
xoff = -x;
x = 0;
}
if (yoff != nPtr->NeoCursorPrevY || xoff !=nPtr->NeoCursorPrevX) {
nPtr->NeoCursorPrevY = yoff;
nPtr->NeoCursorPrevX = xoff;
if (yoff) {
src += (yoff * 16);
}
if (xoff)
{
if (xoff < 32) {
for (i=0; i<256; i+=2) {
bits = ((CARD32 *)src)[i];
bits2 = ((CARD32 *)src)[i+1];
REVBITS_32(bits);
REVBITS_32(bits2);
bits = ((bits >> xoff) | (bits2 << (32-xoff)));
bits2 >>= xoff;
REVBITS_32(bits);
REVBITS_32(bits2);
((CARD32 *) nAcl->CursTemp)[i] = bits;
((CARD32 *) nAcl->CursTemp)[i+1] = bits2;
}
}
else {
for (i=0; i<256; i+=2) {
bits = ((CARD32 *)src)[i];
bits2 = ((CARD32 *)src)[i+1];
REVBITS_32(bits2);
bits = (bits2 >> (xoff-32));
bits2 = 0;
REVBITS_32(bits);
((CARD32 *)nAcl->CursTemp)[i] = bits;
((CARD32 *)nAcl->CursTemp)[i+1] = bits2;
}
}
src = nAcl->CursTemp;
}
memcpy(_dest, src, 1024);
OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8) |
((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4));
}
OUTREG(NEOREG_CURSX, x);
OUTREG(NEOREG_CURSY, y);
}
static void
neoSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
NEOPtr nPtr = NEOPTR(pScrn);
fg = ((fg & 0xff0000) >> 16) | ((fg & 0xff) << 16) | (fg & 0xff00);
bg = ((bg & 0xff0000) >> 16) | ((bg & 0xff) << 16) | (bg & 0xff00);
OUTREG(NEOREG_CURSFGCOLOR, fg);
OUTREG(NEOREG_CURSBGCOLOR, bg);
}
static void
_neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src, int xoff, int yoff)
{
NEOPtr nPtr = NEOPTR(pScrn);
NEOACLPtr nAcl = NEOACLPTR(pScrn);
int i;
unsigned char *_dest, *_src;
int _width, _fill;
for (i = 0; i< nPtr->CursorInfo->MaxHeight - yoff; i++) {
_dest = ((unsigned char *)nPtr->NeoFbBase
+ nAcl->CursorAddress
+ ((nPtr->CursorInfo->MaxWidth >> 2) * i));
_width = (nPtr->CursorInfo->MaxWidth
- (xoff & 0x38)) >> 3;
_src = (src + ((nPtr->CursorInfo->MaxWidth >> 2) * i));
_fill = (xoff & 0x38) >> 3;
memcpy(_dest,_src,_width);
memset(_dest + _width, 0, _fill);
_dest += (nPtr->CursorInfo->MaxWidth >> 3);
_src += (nPtr->CursorInfo->MaxWidth >> 3);
memcpy(_dest,_src,_width);
memset(_dest + _width, 0, _fill);
}
memset(nPtr->NeoFbBase + nAcl->CursorAddress
+ ((nPtr->CursorInfo->MaxWidth >> 2) * i),
0, (nPtr->CursorInfo->MaxHeight - i)
* (nPtr->CursorInfo->MaxWidth >> 2));
OUTREG(NEOREG_CURSMEMPOS, ((0x000f & (nAcl->CursorAddress >> 10)) << 8) |
((0x0ff0 & (nAcl->CursorAddress >> 10)) >> 4));
}
static void
neoLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
{
NEOPtr nPtr = NEOPTR(pScrn);
nPtr->NeoCursorImage = src;
nPtr->NeoCursorPrevY = nPtr->NeoCursorPrevX = 0;
_neoLoadCursorImage(pScrn,src,0,0);
}
static Bool
neoUseHWCursor(ScreenPtr pScr, CursorPtr pCurs)
{
NEOACLPtr nAcl = NEOACLPTR(xf86Screens[pScr->myNum]);
return(nAcl->UseHWCursor && !nAcl->NoCursorMode);
}
static unsigned char*
neoRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
{
CARD32 *SrcS, *SrcM, *DstS, *DstM;
CARD32 *pSrc, *pMsk;
unsigned char *mem;
int SrcPitch, DstPitch, y, x, z;
mem = (unsigned char*)xnfcalloc(4096,1);
SrcPitch = (pCurs->bits->width + 31) >> 5;
DstPitch = infoPtr->MaxWidth >> 4;
SrcS = (CARD32*)pCurs->bits->source;
SrcM = (CARD32*)pCurs->bits->mask;
DstS = (CARD32*)mem;
DstM = DstS + (DstPitch >> 1);
for(y = pCurs->bits->height, pSrc = DstS, pMsk = DstM;
y--;
pSrc+=DstPitch, pMsk+=DstPitch, SrcS+=SrcPitch, SrcM+=SrcPitch) {
for(x = 0; x < SrcPitch; x++) {
pSrc[x] = ~SrcS[x] & SrcM[x];
pMsk[x] = SrcM[x];
for (z = 0; z < 4; z++) {
((char *)pSrc)[x*4+z] =
byte_reversed[((char *)pSrc)[x*4+z] & 0xFF];
((char *)pMsk)[x*4+z] =
byte_reversed[((char *)pMsk)[x*4+z] & 0xFF];
}
}
#if 0
for (;x < DstPitch; x++) {
pSrc[x] = 0;
pMsk[x] = 0;
}
#endif
}
return (unsigned char *)mem;
}
Bool
NeoCursorInit(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
NEOPtr nPtr = NEOPTR(pScrn);
xf86CursorInfoPtr infoPtr;
infoPtr = xf86CreateCursorInfoRec();
if(!infoPtr) return FALSE;
nPtr->CursorInfo = infoPtr;
infoPtr->MaxHeight = 64;
infoPtr->MaxWidth = 64;
infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
infoPtr->SetCursorColors = neoSetCursorColors;
infoPtr->SetCursorPosition = neoSetCursorPosition;
infoPtr->LoadCursorImage = neoLoadCursorImage;
infoPtr->HideCursor = NeoHideCursor;
infoPtr->ShowCursor = NeoShowCursor;
infoPtr->UseHWCursor = neoUseHWCursor;
infoPtr->RealizeCursor = neoRealizeCursor;
return(xf86InitCursor(pScreen, infoPtr));
}