1/* 2 * Copyright (c) 2003 NVIDIA, Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the 6 * "Software"), to deal in the Software without restriction, including 7 * without limitation the rights to use, copy, modify, merge, publish, 8 * distribute, sublicense, and/or sell copies of the Software, and to 9 * permit persons to whom the Software is furnished to do so, subject to 10 * the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include "nv_include.h" 29 30#include "cursorstr.h" 31 32/****************************************************************************\ 33* * 34* HW Cursor Entrypoints * 35* * 36\****************************************************************************/ 37 38#define TRANSPARENT_PIXEL 0 39 40#define ConvertToRGB555(c) \ 41(((c & 0xf80000) >> 9 ) | ((c & 0xf800) >> 6 ) | ((c & 0xf8) >> 3 ) | 0x8000) 42 43#define ConvertToRGB888(c) (c | 0xff000000) 44 45#define BYTE_SWAP_32(c) ((c & 0xff000000) >> 24) | \ 46 ((c & 0xff0000) >> 8) | \ 47 ((c & 0xff00) << 8) | \ 48 ((c & 0xff) << 24) 49 50 51static void 52ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst) 53{ 54 CARD32 b, m; 55 int i, j; 56 57 for ( i = 0; i < 32; i++ ) { 58 b = *src++; 59 m = *src++; 60 for ( j = 0; j < 32; j++ ) { 61#if X_BYTE_ORDER == X_BIG_ENDIAN 62 if ( m & 0x80000000) 63 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg; 64 else 65 *dst = TRANSPARENT_PIXEL; 66 b <<= 1; 67 m <<= 1; 68#else 69 if ( m & 1 ) 70 *dst = ( b & 1) ? pNv->curFg : pNv->curBg; 71 else 72 *dst = TRANSPARENT_PIXEL; 73 b >>= 1; 74 m >>= 1; 75#endif 76 dst++; 77 } 78 } 79} 80 81 82static void 83ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst) 84{ 85 CARD32 b, m; 86 int i, j; 87 88 for ( i = 0; i < 128; i++ ) { 89 b = *src++; 90 m = *src++; 91 for ( j = 0; j < 32; j++ ) { 92#if X_BYTE_ORDER == X_BIG_ENDIAN 93 if ( m & 0x80000000) 94 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg; 95 else 96 *dst = TRANSPARENT_PIXEL; 97 b <<= 1; 98 m <<= 1; 99#else 100 if ( m & 1 ) 101 *dst = ( b & 1) ? pNv->curFg : pNv->curBg; 102 else 103 *dst = TRANSPARENT_PIXEL; 104 b >>= 1; 105 m >>= 1; 106#endif 107 dst++; 108 } 109 } 110} 111 112 113static void 114TransformCursor (NVPtr pNv) 115{ 116 CARD32 *tmp; 117 int i, dwords; 118 119 /* convert to color cursor */ 120 if(pNv->alphaCursor) { 121 dwords = 64 * 64; 122 if(!(tmp = calloc(1, dwords * 4))) return; 123 ConvertCursor8888(pNv, pNv->curImage, tmp); 124 } else { 125 dwords = (32 * 32) >> 1; 126 if(!(tmp = calloc(1, dwords * 4))) return; 127 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp); 128 } 129 130 for(i = 0; i < dwords; i++) 131 pNv->CURSOR[i] = tmp[i]; 132 133 free(tmp); 134} 135 136static void 137NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src ) 138{ 139 NVPtr pNv = NVPTR(pScrn); 140 141 /* save copy of image for color changes */ 142 memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256); 143 144 TransformCursor(pNv); 145} 146 147static void 148NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 149{ 150 NVPtr pNv = NVPTR(pScrn); 151 152 pNv->PRAMDAC[0x0000300/4] = (x & 0xFFFF) | (y << 16); 153} 154 155static void 156NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 157{ 158 NVPtr pNv = NVPTR(pScrn); 159 CARD32 fore, back; 160 161 if(pNv->alphaCursor) { 162 fore = ConvertToRGB888(fg); 163 back = ConvertToRGB888(bg); 164#if X_BYTE_ORDER == X_BIG_ENDIAN 165 if((pNv->Chipset & 0x0ff0) == 0x0110) { 166 fore = BYTE_SWAP_32(fore); 167 back = BYTE_SWAP_32(back); 168 } 169#endif 170 } else { 171 fore = ConvertToRGB555(fg); 172 back = ConvertToRGB555(bg); 173#if X_BYTE_ORDER == X_BIG_ENDIAN 174 if((pNv->Chipset & 0x0ff0) == 0x0110) { 175 fore = ((fore & 0xff) << 8) | (fore >> 8); 176 back = ((back & 0xff) << 8) | (back >> 8); 177 } 178#endif 179 } 180 181 if ((pNv->curFg != fore) || (pNv->curBg != back)) { 182 pNv->curFg = fore; 183 pNv->curBg = back; 184 185 TransformCursor(pNv); 186 } 187} 188 189 190static void 191NVShowCursor(ScrnInfoPtr pScrn) 192{ 193 NVPtr pNv = NVPTR(pScrn); 194 /* Enable cursor - X-Windows mode */ 195 NVShowHideCursor(pNv, 1); 196} 197 198static void 199NVHideCursor(ScrnInfoPtr pScrn) 200{ 201 NVPtr pNv = NVPTR(pScrn); 202 /* Disable cursor */ 203 NVShowHideCursor(pNv, 0); 204} 205 206static Bool 207NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 208{ 209 return TRUE; 210} 211 212#ifdef ARGB_CURSOR 213static Bool 214NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs) 215{ 216 if((pCurs->bits->width <= 64) && (pCurs->bits->height <= 64)) 217 return TRUE; 218 219 return FALSE; 220} 221 222static void 223NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs) 224{ 225 NVPtr pNv = NVPTR(pScrn); 226 CARD32 *image = pCurs->bits->argb; 227 CARD32 *dst = (CARD32*)pNv->CURSOR; 228 CARD32 alpha, tmp; 229 int x, y, w, h; 230 231 w = pCurs->bits->width; 232 h = pCurs->bits->height; 233 234 if((pNv->Chipset & 0x0ff0) == 0x0110) { /* premultiply */ 235 for(y = 0; y < h; y++) { 236 for(x = 0; x < w; x++) { 237 alpha = *image >> 24; 238 if(alpha == 0xff) 239 tmp = *image; 240 else { 241 tmp = (alpha << 24) | 242 (((*image & 0xff) * alpha) / 255) | 243 ((((*image & 0xff00) * alpha) / 255) & 0xff00) | 244 ((((*image & 0xff0000) * alpha) / 255) & 0xff0000); 245 } 246 image++; 247#if X_BYTE_ORDER == X_BIG_ENDIAN 248 *dst++ = BYTE_SWAP_32(tmp); 249#else 250 *dst++ = tmp; 251#endif 252 } 253 for(; x < 64; x++) 254 *dst++ = 0; 255 } 256 } else { 257 for(y = 0; y < h; y++) { 258 for(x = 0; x < w; x++) 259 *dst++ = *image++; 260 for(; x < 64; x++) 261 *dst++ = 0; 262 } 263 } 264 265 if(y < 64) 266 memset(dst, 0, 64 * (64 - y) * 4); 267} 268#endif 269 270Bool 271NVCursorInit(ScreenPtr pScreen) 272{ 273 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 274 NVPtr pNv = NVPTR(pScrn); 275 xf86CursorInfoPtr infoPtr; 276 277 infoPtr = xf86CreateCursorInfoRec(); 278 if(!infoPtr) return FALSE; 279 280 pNv->CursorInfoRec = infoPtr; 281 282 if(pNv->alphaCursor) 283 infoPtr->MaxWidth = infoPtr->MaxHeight = 64; 284 else 285 infoPtr->MaxWidth = infoPtr->MaxHeight = 32; 286 287 infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 288 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32; 289 infoPtr->SetCursorColors = NVSetCursorColors; 290 infoPtr->SetCursorPosition = NVSetCursorPosition; 291 infoPtr->LoadCursorImage = NVLoadCursorImage; 292 infoPtr->HideCursor = NVHideCursor; 293 infoPtr->ShowCursor = NVShowCursor; 294 infoPtr->UseHWCursor = NVUseHWCursor; 295 296#ifdef ARGB_CURSOR 297 if(pNv->alphaCursor) { 298 infoPtr->UseHWCursorARGB = NVUseHWCursorARGB; 299 infoPtr->LoadCursorARGB = NVLoadCursorARGB; 300 } 301#endif 302 303 return(xf86InitCursor(pScreen, infoPtr)); 304} 305