summaryrefslogtreecommitdiff
path: root/src/newport_cursor.c
blob: 4d4cf417f4ccae6bc670de5d223b65812725c4b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/*
 * newport_cursor.c
 */
/* $XFree86$ */

#include "newport.h"
#include "cursorstr.h"

#include "servermd.h"

#define MAX_CURS 32

static void NewportShowCursor(ScrnInfoPtr pScrn);
static void NewportHideCursor(ScrnInfoPtr pScrn);
static void NewportSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
static void NewportSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
/* static void NewportLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits); */
static unsigned char* NewportRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs);

Bool
NewportHWCursorInit(ScreenPtr pScreen)
{
	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
	NewportPtr pNewport = NEWPORTPTR(pScrn);
	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
	xf86CursorInfoPtr infoPtr;
	CARD16 tmp;

	infoPtr = xf86CreateCursorInfoRec();
	if(!infoPtr)
		return FALSE;

	pNewport->CursorInfoRec = infoPtr;
	infoPtr->MaxWidth = MAX_CURS;
	infoPtr->MaxHeight = MAX_CURS;
	infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;

	infoPtr->SetCursorColors = NewportSetCursorColors;
	infoPtr->SetCursorPosition = NewportSetCursorPosition;
	infoPtr->LoadCursorImage = NewportLoadCursorImage;
	infoPtr->HideCursor = NewportHideCursor;
	infoPtr->ShowCursor = NewportShowCursor;
	infoPtr->RealizeCursor = NewportRealizeCursor;
	infoPtr->UseHWCursor = NULL;

	/* enable cursor funtion in shadow register */
	pNewport->vc2ctrl |= VC2_CTRL_ECURS;
	/* enable glyph cursor, maximum size is 32x32x2 */
	pNewport->vc2ctrl &= ~( VC2_CTRL_ECG64 | VC2_CTRL_ECCURS);
	/* setup hw cursors cmap base address  */
	NewportBfwait(pNewportRegs);
	pNewportRegs->set.dcbmode = (DCB_XMAP0 | R_DCB_XMAP9_PROTOCOL |
			XM9_CRS_CURS_CMAP_MSB | NPORT_DMODE_W1 );
	tmp = pNewportRegs->set.dcbdata0.bytes.b3;
#if 0
	/* The docs say we can change base address of the cursors
	 * cmap entries, but it doesn't work. */
	tmp++;
#endif
	pNewportRegs->set.dcbmode = (DCB_XMAP0 | W_DCB_XMAP9_PROTOCOL |
			XM9_CRS_CURS_CMAP_MSB | NPORT_DMODE_W1 );
	pNewportRegs->set.dcbdata0.bytes.b3 = tmp;
	pNewport->curs_cmap_base = (tmp << 5) & 0xffe0;

	return xf86InitCursor(pScreen, infoPtr);
}


static void NewportShowCursor(ScrnInfoPtr pScrn)
{
	NewportPtr pNewport = NEWPORTPTR(pScrn);
	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);

	pNewport->vc2ctrl |= VC2_CTRL_ECDISP;
	NewportVc2Set( pNewportRegs, VC2_IREG_CONTROL, pNewport->vc2ctrl);
}

static void NewportHideCursor(ScrnInfoPtr pScrn)
{
	NewportPtr pNewport = NEWPORTPTR(pScrn);
	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);

	pNewport->vc2ctrl &= ~VC2_CTRL_ECDISP;
	NewportVc2Set( pNewportRegs, VC2_IREG_CONTROL, pNewport->vc2ctrl);
}

static void NewportSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
	CARD16 x_off;
	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
	NewportPtr pNewport = NEWPORTPTR(pScrn);
		
	/* the docu says this should always be 31, but it isn't */
	x_off = 31;
	if ( pNewport->board_rev < 6 )
		x_off = 21;
	NewportVc2Set( pNewportRegs, VC2_IREG_CURSX, (CARD16) x + x_off);
	NewportVc2Set( pNewportRegs, VC2_IREG_CURSY, (CARD16) y + 31);
}

static void NewportSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
	NewportPtr pNewport = NEWPORTPTR(pScrn);
	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);
	LOCO color;

	color.blue = bg & 0xff;
	color.green = (bg & 0xff00) >> 8;
	color.red = (bg & 0xff0000) >> 16;
	NewportCmapSetRGB( pNewportRegs, pNewport->curs_cmap_base+2, color);

	color.blue = fg & 0xff;
	color.green = (fg & 0xff00) >> 8;
	color.red = (fg & 0xff0000) >> 16;
	NewportCmapSetRGB( pNewportRegs, pNewport->curs_cmap_base+1, color);
}

static unsigned char* NewportRealizeCursor(xf86CursorInfoPtr infoPtr, CursorPtr pCurs)
{
	int size = (infoPtr->MaxWidth * infoPtr->MaxHeight) >> 2;
	CARD32 *mem, *SrcS, *SrcM, *DstS;
	unsigned int i;

	if (!(mem = xcalloc(1, size)))
        	return NULL;

	SrcS = (CARD32*)pCurs->bits->source;
    	SrcM = (CARD32*)pCurs->bits->mask;
    	DstS = mem;
	/* first color: maximum is 32*4 Bytes */
	for(i=0; i < pCurs->bits->height; i++) {
		*DstS = *SrcS & *SrcM;
		DstS++, SrcS++, SrcM++;
	}
	/* second color is the lower of mem: again 32*4 Bytes at most */
	DstS = mem + MAX_CURS;
	SrcS = (CARD32*)pCurs->bits->source;
    	SrcM = (CARD32*)pCurs->bits->mask;
	for(i=0; i < pCurs->bits->height; i++) {
		*DstS = (~*SrcS) & *SrcM;
		DstS++, SrcS++, SrcM++;
	}
	return (unsigned char*) mem;
}

void NewportLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
{
	int i;
	CARD16 tmp;
	NewportRegsPtr pNewportRegs = NEWPORTREGSPTR(pScrn);

	/* address of cursor data in vc2's ram */
        tmp = NewportVc2Get( pNewportRegs, VC2_IREG_CENTRY);
 	/* this is where we want to write to: */
        NewportVc2Set( pNewportRegs, VC2_IREG_RADDR, tmp);
        pNewportRegs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM |
                               		NPORT_DMODE_W2 | VC2_PROTOCOL);
	/* write cursor data */
        for (i = 0; i < ((MAX_CURS * MAX_CURS) >> 3); i++) {
		NewportBfwait(pNewportRegs);
		pNewportRegs->set.dcbdata0.hwords.s1 = *(unsigned short*)bits;
		bits += sizeof(unsigned short);
        }
}