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