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