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