1/*
2 * Hardware cursor support for TCX
3 *
4 * Copyright 2000 by Jakub Jelinek <jakub@redhat.com>.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software
7 * and its documentation for any purpose is hereby granted without
8 * fee, provided that the above copyright notice appear in all copies
9 * and that both that copyright notice and this permission notice
10 * appear in supporting documentation, and that the name of Jakub
11 * Jelinek not be used in advertising or publicity pertaining to
12 * distribution of the software without specific, written prior
13 * permission.  Jakub Jelinek makes no representations about the
14 * suitability of this software for any purpose.  It is provided "as
15 * is" without express or implied warranty.
16 *
17 * JAKUB JELINEK DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
18 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
19 * FITNESS, IN NO EVENT SHALL JAKUB JELINEK BE LIABLE FOR ANY
20 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
21 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
22 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
23 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
24 * SOFTWARE.
25 */
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include "tcx.h"
32
33static void TCXLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src);
34static void TCXShowCursor(ScrnInfoPtr pScrn);
35static void TCXHideCursor(ScrnInfoPtr pScrn);
36static void TCXSetCursorPosition(ScrnInfoPtr pScrn, int x, int y);
37static void TCXSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg);
38
39static void
40TCXLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
41{
42    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
43    int i, x, y;
44    unsigned int *data = (unsigned int *)src;
45
46    pTcx->CursorData = src;
47    x = pTcx->CursorShiftX;
48    y = pTcx->CursorShiftY;
49    if (x >= 32 || y >= 32)
50	y = 32;
51    data += y;
52    for (i = 0; i < 32 - y; i++)
53	pTcx->thc->thc_cursmask[i] = *data++ << x;
54    for (; i < 32; i++)
55	pTcx->thc->thc_cursmask[i] = 0;
56    data += y;
57    for (i = 0; i < 32 - y; i++)
58	pTcx->thc->thc_cursbits[i] = *data++ << x;
59    for (; i < 32; i++)
60	pTcx->thc->thc_cursbits[i] = 0;
61}
62
63static void
64TCXShowCursor(ScrnInfoPtr pScrn)
65{
66    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
67
68    pTcx->thc->thc_cursxy = pTcx->CursorXY;
69    pTcx->CursorEnabled = TRUE;
70}
71
72static void
73TCXHideCursor(ScrnInfoPtr pScrn)
74{
75    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
76
77    pTcx->thc->thc_cursxy = ((65536 - 32) << 16) | (65536 - 32);
78    pTcx->CursorEnabled = FALSE;
79}
80
81static void
82TCXSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
83{
84    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
85    int CursorShiftX = 0, CursorShiftY = 0;
86
87    if (x < 0) {
88	CursorShiftX = -x;
89	x = 0;
90	if (CursorShiftX > 32)
91	    CursorShiftX = 32;
92    }
93    if (y < 0) {
94	CursorShiftY = -y;
95	y = 0;
96	if (CursorShiftY > 32)
97	    CursorShiftY = 32;
98    }
99    if ((CursorShiftX != pTcx->CursorShiftX ||
100	 CursorShiftY != pTcx->CursorShiftY) &&
101	 pTcx->CursorData != NULL) {
102	pTcx->CursorShiftX = CursorShiftX;
103	pTcx->CursorShiftY = CursorShiftY;
104	TCXLoadCursorImage(pScrn, pTcx->CursorData);
105    }
106
107    pTcx->CursorXY = ((x & 0xffff) << 16) | (y & 0xffff);
108    if (pTcx->CursorEnabled)
109	pTcx->thc->thc_cursxy = pTcx->CursorXY;
110}
111
112static void
113TCXSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
114{
115    TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn);
116
117    if (bg != pTcx->CursorBg || fg != pTcx->CursorFg) {
118	xf86SbusSetOsHwCursorCmap(pTcx->psdp, bg, fg);
119	pTcx->CursorBg = bg;
120	pTcx->CursorFg = fg;
121    }
122}
123
124Bool
125TCXHWCursorInit(ScreenPtr pScreen)
126{
127    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
128    TcxPtr pTcx;
129    xf86CursorInfoPtr infoPtr;
130
131    pTcx = GET_TCX_FROM_SCRN(pScrn);
132    pTcx->CursorXY = 0;
133    pTcx->CursorBg = pTcx->CursorFg = 0;
134    pTcx->CursorEnabled = FALSE;
135    pTcx->CursorShiftX = 0;
136    pTcx->CursorShiftY = 0;
137    pTcx->CursorData = NULL;
138
139    infoPtr = xf86CreateCursorInfoRec();
140    if(!infoPtr) return FALSE;
141
142    pTcx->CursorInfoRec = infoPtr;
143
144    infoPtr->MaxWidth = 32;
145    infoPtr->MaxHeight = 32;
146    infoPtr->Flags = HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
147	HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
148	HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED |
149	HARDWARE_CURSOR_TRUECOLOR_AT_8BPP;
150
151    infoPtr->SetCursorColors = TCXSetCursorColors;
152    infoPtr->SetCursorPosition = TCXSetCursorPosition;
153    infoPtr->LoadCursorImage = TCXLoadCursorImage;
154    infoPtr->HideCursor = TCXHideCursor;
155    infoPtr->ShowCursor = TCXShowCursor;
156    infoPtr->UseHWCursor = NULL;
157
158    return xf86InitCursor(pScreen, infoPtr);
159}
160