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