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