1/* $Xorg: sunCursor.c,v 1.4 2001/02/09 02:04:43 xorgcvs Exp $ */
2/*
3
4Copyright 1988  Sun Microsystems, Inc.
5Copyright 1993, 1998  The Open Group
6
7Permission to use, copy, modify, distribute, and sell this software and its
8documentation for any purpose is hereby granted without fee, provided that
9the above copyright notice appear in all copies and that both that
10copyright notice and this permission notice appear in supporting
11documentation.
12
13The above copyright notice and this permission notice shall be included
14in all copies or substantial portions of the Software.
15
16THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
20OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22OTHER DEALINGS IN THE SOFTWARE.
23
24Except as contained in this notice, the name of The Open Group shall
25not be used in advertising or otherwise to promote the sale, use or
26other dealings in this Software without prior written authorization
27from The Open Group.
28
29*/
30/* $XFree86: xc/programs/Xserver/hw/sun/sunCursor.c,v 3.6 2003/11/17 22:20:36 dawes Exp $ */
31
32/*-
33 * sunCursor.c --
34 *	Functions for maintaining the Sun software cursor...
35 *
36 */
37
38#define NEED_EVENTS
39#include    "sun.h"
40#include    "fb.h"
41
42#ifdef FBIOGCURMAX  /* has hardware cursor kernel support */
43
44#define sunGetCursorPrivate(pScreen) \
45    (&(sunGetScreenPrivate(pScreen)->hardwareCursor))
46
47static Bool sunRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
48static Bool sunUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr);
49static void sunCursorRepad (ScreenPtr, CursorBitsPtr, unsigned char *, unsigned char *, DDXPointPtr, int, int);
50static void sunLoadCursor(ScreenPtr, CursorPtr, int, int);
51static void sunSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int);
52static void sunMoveCursor(DeviceIntPtr, ScreenPtr, int, int);
53static void sunQueryBestSize(int, unsigned short *, unsigned short *, ScreenPtr);
54
55static Bool
56sunRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
57{
58    sunCursorPtr pCurPriv = sunGetCursorPrivate(pScreen);
59    int	    x, y;
60
61    /* miRecolorCursor does this */
62    if (pCurPriv->pCursor == pCursor)
63    {
64	miPointerGetPosition (pDev, &x, &y);
65	sunLoadCursor (pScreen, pCursor, x, y);
66    }
67    return TRUE;
68}
69
70static Bool
71sunUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
72{
73    return TRUE;
74}
75
76static void
77sunCursorRepad(ScreenPtr pScreen, CursorBitsPtr bits, unsigned char *src_bits, unsigned char *dst_bits, DDXPointPtr ptSrc, int w, int h)
78{
79    PixmapPtr	src, dst;
80    BoxRec	box;
81    RegionRec	rgnDst;
82
83    if (!(src = GetScratchPixmapHeader(pScreen, bits->width, bits->height,
84				       /*bpp*/ 1, /*depth*/ 1,
85				      PixmapBytePad(bits->width,1), src_bits)))
86	return;
87    if (!(dst = GetScratchPixmapHeader(pScreen, w, h, /*bpp*/ 1, /*depth*/ 1,
88				       PixmapBytePad(w,1), dst_bits)))
89    {
90	FreeScratchPixmapHeader(src);
91	return;
92    }
93    box.x1 = 0;
94    box.y1 = 0;
95    box.x2 = w;
96    box.y2 = h;
97    REGION_INIT(pScreen, &rgnDst, &box, 1);
98#ifndef LOWMEMFTPT
99    mfbDoBitblt(&src->drawable, &dst->drawable, GXcopy, &rgnDst, ptSrc);
100#else
101    cfbDoBitblt(&src->drawable, &dst->drawable, GXcopy, &rgnDst, ptSrc,
102	0xFFFFFFFF);
103#endif /* ifndef LOWMEMFTPT */
104    REGION_UNINIT(pScreen, &rgnDst);
105    FreeScratchPixmapHeader(src);
106    FreeScratchPixmapHeader(dst);
107}
108
109static void
110sunLoadCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
111{
112    sunCursorPtr pCurPriv = sunGetCursorPrivate(pScreen);
113    struct fbcursor fbcursor;
114    int	w, h;
115    unsigned char   r[2], g[2], b[2];
116    DDXPointRec	ptSrc;
117    unsigned char   source_temp[1024], mask_temp[1024];
118#ifdef INTERNAL_VS_EXTERNAL_PADDING
119    long                widthBytesLine, length;
120    long                widthBytesLineProto, lengthProto;
121    int			linesDone;
122#endif
123
124
125    fbcursor.set = FB_CUR_SETALL;
126    fbcursor.enable = 1;
127    fbcursor.pos.x = x;
128    fbcursor.pos.y = y;
129    fbcursor.hot.x = pCursor->bits->xhot;
130    fbcursor.hot.y = pCursor->bits->yhot;
131    r[0] = pCursor->backRed >> 8;
132    g[0] = pCursor->backGreen >> 8;
133    b[0] = pCursor->backBlue >> 8;
134    r[1] = pCursor->foreRed >> 8;
135    g[1] = pCursor->foreGreen >> 8;
136    b[1] = pCursor->foreBlue >> 8;
137    fbcursor.cmap.index = 0;
138    fbcursor.cmap.count = 2;
139    fbcursor.cmap.red = r;
140    fbcursor.cmap.green = g;
141    fbcursor.cmap.blue = b;
142    fbcursor.image = (char *) pCursor->bits->source;
143    fbcursor.mask = (char *) pCursor->bits->mask;
144    w = pCursor->bits->width;
145    h = pCursor->bits->height;
146    if (w > pCurPriv->width || h > pCurPriv->height) {
147	ptSrc.x = 0;
148	ptSrc.y = 0;
149	if (w > pCurPriv->width)
150	    w = pCurPriv->width;
151	if (h > pCurPriv->height)
152	    h = pCurPriv->height;
153	sunCursorRepad (pScreen, pCursor->bits, pCursor->bits->source,
154			source_temp, &ptSrc, w, h);
155	sunCursorRepad (pScreen, pCursor->bits, pCursor->bits->mask,
156			mask_temp, &ptSrc, w, h);
157	fbcursor.image = (char *) source_temp;
158	fbcursor.mask = (char *) mask_temp;
159    }
160#ifdef INTERNAL_VS_EXTERNAL_PADDING
161    widthBytesLine = BitmapBytePad(w);
162    length = widthBytesLine * h;
163    widthBytesLineProto = BitmapBytePadProto(w);
164    lengthProto = widthBytesLineProto * h;
165
166    /* for 64-bit server, convert image to pad to 32 bits */
167    if ( widthBytesLine != widthBytesLineProto ) {
168	if (widthBytesLine - widthBytesLineProto  == 4) {
169		register int * sprotoPtr, * mprotoPtr;
170		register int * sbufPtr, * mbufPtr;
171		register int i, j;
172
173		sbufPtr = (int *)fbcursor.image;
174		mbufPtr = (int *)fbcursor.mask;
175		sprotoPtr = (int *)source_temp;
176		mprotoPtr = (int *)mask_temp;
177		for (i=0; i<h; i++) {
178			for (j=0; j<widthBytesLineProto; j+=4) {
179				*sprotoPtr++ = *sbufPtr++;
180				*mprotoPtr++ = *mbufPtr++;
181			}
182			sbufPtr++;
183			mbufPtr++;
184		}
185	} else {
186        register char * sbufPtr, * sprotoPtr;
187        register char * mbufPtr, * mprotoPtr;
188        register int i;
189
190        for (i = 0,
191             sbufPtr = fbcursor.image,
192             sprotoPtr = source_temp,
193             mbufPtr = fbcursor.mask,
194             mprotoPtr = mask_temp;
195             i < h;
196             sbufPtr += widthBytesLine,
197             sprotoPtr += widthBytesLineProto,
198             mbufPtr += widthBytesLine,
199             mprotoPtr += widthBytesLineProto,
200             i++) {
201	    if (sprotoPtr != sbufPtr)
202            	memmove(sprotoPtr, sbufPtr, widthBytesLineProto);
203	    if (mprotoPtr != mbufPtr)
204            	memmove(mprotoPtr, mbufPtr, widthBytesLineProto);
205	}
206} /* else */
207	fbcursor.image = (char *) source_temp;
208	fbcursor.mask = (char *) mask_temp;
209    }
210#endif
211    fbcursor.size.x = w;
212    fbcursor.size.y = h;
213#ifndef Lynx
214    (void) ioctl (sunFbs[pScreen->myNum].fd, FBIOSCURSOR, &fbcursor);
215#else
216    (void) sunIoctl (&sunFbs[pScreen->myNum], FBIOSCURSOR, &fbcursor);
217#endif
218}
219
220static void
221sunSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y)
222{
223    sunCursorPtr pCurPriv = sunGetCursorPrivate(pScreen);
224
225    if (pCursor)
226    	sunLoadCursor (pScreen, pCursor, x, y);
227    else
228	sunDisableCursor (pScreen);
229    pCurPriv->pCursor = pCursor;
230}
231
232static void
233sunMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
234{
235    struct fbcurpos pos;
236
237    pos.x = x;
238    pos.y = y;
239#ifndef Lynx
240    ioctl (sunFbs[pScreen->myNum].fd, FBIOSCURPOS, &pos);
241#else
242    sunIoctl (&sunFbs[pScreen->myNum], FBIOSCURPOS, &pos);
243#endif
244}
245
246miPointerSpriteFuncRec sunPointerSpriteFuncs = {
247    sunRealizeCursor,
248    sunUnrealizeCursor,
249    sunSetCursor,
250    sunMoveCursor,
251};
252
253static void
254sunQueryBestSize(int class, unsigned short *pwidth, unsigned short *pheight, ScreenPtr pScreen)
255{
256    sunCursorPtr pCurPriv = sunGetCursorPrivate(pScreen);
257
258    switch (class)
259    {
260    case CursorShape:
261	if (*pwidth > pCurPriv->width)
262	    *pwidth = pCurPriv->width;
263	if (*pheight > pCurPriv->height)
264	    *pheight = pCurPriv->height;
265	if (*pwidth > pScreen->width)
266	    *pwidth = pScreen->width;
267	if (*pheight > pScreen->height)
268	    *pheight = pScreen->height;
269	break;
270    default:
271	fbQueryBestSize (class, pwidth, pheight, pScreen);
272	break;
273    }
274}
275
276#endif
277
278Bool
279sunCursorInitialize(ScreenPtr pScreen)
280{
281#ifdef FBIOGCURMAX
282    sunCursorPtr pCurPriv = sunGetCursorPrivate(pScreen);
283    struct fbcurpos maxsize;
284
285    pCurPriv->has_cursor = FALSE;
286#ifndef Lynx
287    if (ioctl (sunFbs[pScreen->myNum].fd, FBIOGCURMAX, &maxsize) == -1)
288#else
289    if (sunIoctl (&sunFbs[pScreen->myNum], FBIOGCURMAX, &maxsize) == -1)
290#endif
291	return FALSE;
292    pCurPriv->width = maxsize.x;
293    pCurPriv->height= maxsize.y;
294    pScreen->QueryBestSize = sunQueryBestSize;
295    miPointerInitialize (pScreen,
296			 &sunPointerSpriteFuncs,
297			 &sunPointerScreenFuncs,
298			 FALSE);
299    pCurPriv->has_cursor = TRUE;
300    pCurPriv->pCursor = NULL;
301    return TRUE;
302#else
303    return FALSE;
304#endif
305}
306
307void
308sunDisableCursor (ScreenPtr pScreen)
309{
310#ifdef FBIOGCURMAX
311    sunCursorPtr pCurPriv = sunGetCursorPrivate(pScreen);
312    struct fbcursor fbcursor;
313
314    if (pCurPriv->has_cursor)
315    {
316    	fbcursor.set = FB_CUR_SETCUR;
317    	fbcursor.enable = 0;
318#ifndef Lynx
319    	(void) ioctl (sunFbs[pScreen->myNum].fd, FBIOSCURSOR, &fbcursor);
320#else
321    	(void) sunIoctl (&sunFbs[pScreen->myNum], FBIOSCURSOR, &fbcursor);
322#endif
323	pCurPriv->pCursor = NULL;
324    }
325#endif
326}
327