2 * Copyright 2003 NVIDIA, Corporation
3 * Copyright 2007 Maarten Maathuis
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include "nv_include.h"
26 #include "cursorstr.h"
28 /****************************************************************************\
30 * HW Cursor Entrypoints *
32 \****************************************************************************/
34 #define CURSOR_X_SHIFT 0
35 #define CURSOR_Y_SHIFT 16
36 #define CURSOR_POS_MASK 0xffff
38 #define TRANSPARENT_PIXEL 0
40 #define ConvertToRGB555(c) (((c & 0xf80000) >> 9 ) | /* Blue */ \
41 ((c & 0xf800) >> 6 ) | /* Green */ \
42 ((c & 0xf8) >> 3 ) | /* Red */ \
43 0x8000) /* Set upper bit, else we get complete transparency. */
45 #define ConvertToRGB888(c) (c | 0xff000000)
47 #define BYTE_SWAP_32(c) ((c & 0xff000000) >> 24) | \
48 ((c & 0xff0000) >> 8) | \
49 ((c & 0xff00) << 8) | \
52 /* Limit non-alpha cursors to 32x32 (x2 bytes) */
53 #define MAX_CURSOR_SIZE 32
55 /* Limit alpha cursors to 64x64 (x4 bytes) */
56 #define MAX_CURSOR_SIZE_ALPHA (MAX_CURSOR_SIZE * 2)
59 ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst)
63 int sz=pNv->NVArch==0x10?MAX_CURSOR_SIZE_ALPHA:MAX_CURSOR_SIZE;
65 for ( i = 0; i < sz; i++ ) {
68 for ( j = 0; j < sz; j++ ) {
69 #if X_BYTE_ORDER == X_BIG_ENDIAN
71 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
73 *dst = TRANSPARENT_PIXEL;
78 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
80 *dst = TRANSPARENT_PIXEL;
91 ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst)
96 /* Iterate over each byte in the cursor. */
97 for ( i = 0; i < MAX_CURSOR_SIZE * 4; i++ ) {
100 for ( j = 0; j < MAX_CURSOR_SIZE; j++ ) {
101 #if X_BYTE_ORDER == X_BIG_ENDIAN
103 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
105 *dst = TRANSPARENT_PIXEL;
110 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
112 *dst = TRANSPARENT_PIXEL;
122 TransformCursor (NVPtr pNv)
127 /* convert to color cursor */
128 if(pNv->NVArch==0x10) {
129 dwords = (MAX_CURSOR_SIZE_ALPHA * MAX_CURSOR_SIZE_ALPHA) >> 1;
130 if(!(tmp = xalloc(dwords * 4))) return;
131 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
132 } else if(pNv->alphaCursor) {
133 dwords = MAX_CURSOR_SIZE_ALPHA * MAX_CURSOR_SIZE_ALPHA;
134 if(!(tmp = xalloc(dwords * 4))) return;
135 ConvertCursor8888(pNv, pNv->curImage, tmp);
137 dwords = (MAX_CURSOR_SIZE * MAX_CURSOR_SIZE) >> 1;
138 if(!(tmp = xalloc(dwords * 4))) return;
139 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
142 for(i = 0; i < dwords; i++)
143 pNv->CURSOR[i] = tmp[i];
149 NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src )
151 NVPtr pNv = NVPTR(pScrn);
153 /* save copy of image for color changes */
154 memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256);
156 TransformCursor(pNv);
160 NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
162 NVPtr pNv = NVPTR(pScrn);
163 nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, (x & 0xFFFF) | (y << 16));
167 NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
169 NVPtr pNv = NVPTR(pScrn);
172 if(pNv->alphaCursor) {
173 fore = ConvertToRGB888(fg);
174 back = ConvertToRGB888(bg);
175 #if X_BYTE_ORDER == X_BIG_ENDIAN
176 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
177 fore = BYTE_SWAP_32(fore);
178 back = BYTE_SWAP_32(back);
182 fore = ConvertToRGB555(fg);
183 back = ConvertToRGB555(bg);
184 #if X_BYTE_ORDER == X_BIG_ENDIAN
185 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
186 fore = ((fore & 0xff) << 8) | (fore >> 8);
187 back = ((back & 0xff) << 8) | (back >> 8);
192 if ((pNv->curFg != fore) || (pNv->curBg != back)) {
196 TransformCursor(pNv);
202 NVShowCursor(ScrnInfoPtr pScrn)
204 /* Enable cursor - X-Windows mode */
205 NVShowHideCursor(pScrn, 1);
209 NVHideCursor(ScrnInfoPtr pScrn)
212 NVShowHideCursor(pScrn, 0);
216 NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
223 NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
225 if((pCurs->bits->width <= MAX_CURSOR_SIZE_ALPHA) && (pCurs->bits->height <= MAX_CURSOR_SIZE_ALPHA))
232 NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
234 NVPtr pNv = NVPTR(pScrn);
235 CARD32 *image = pCurs->bits->argb;
236 CARD32 *dst = (CARD32*)pNv->CURSOR;
240 w = pCurs->bits->width;
241 h = pCurs->bits->height;
243 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) { /* premultiply */
244 for(y = 0; y < h; y++) {
245 for(x = 0; x < w; x++) {
246 alpha = *image >> 24;
250 tmp = (alpha << 24) |
251 (((*image & 0xff) * alpha) / 255) |
252 ((((*image & 0xff00) * alpha) / 255) & 0xff00) |
253 ((((*image & 0xff0000) * alpha) / 255) & 0xff0000);
256 #if X_BYTE_ORDER == X_BIG_ENDIAN
257 *dst++ = BYTE_SWAP_32(tmp);
262 for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
266 for(y = 0; y < h; y++) {
267 for(x = 0; x < w; x++)
269 for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
274 if(y < MAX_CURSOR_SIZE_ALPHA)
275 memset(dst, 0, MAX_CURSOR_SIZE_ALPHA * (MAX_CURSOR_SIZE_ALPHA - y) * 4);
280 NVCursorInit(ScreenPtr pScreen)
282 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
283 NVPtr pNv = NVPTR(pScrn);
284 xf86CursorInfoPtr infoPtr;
286 infoPtr = xf86CreateCursorInfoRec();
287 if(!infoPtr) return FALSE;
289 pNv->CursorInfoRec = infoPtr;
292 infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE_ALPHA;
294 infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE;
296 infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
297 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
298 infoPtr->SetCursorColors = NVSetCursorColors;
299 infoPtr->SetCursorPosition = NVSetCursorPosition;
300 infoPtr->LoadCursorImage = NVLoadCursorImage;
301 infoPtr->HideCursor = NVHideCursor;
302 infoPtr->ShowCursor = NVShowCursor;
303 infoPtr->UseHWCursor = NVUseHWCursor;
306 if(pNv->alphaCursor) {
307 infoPtr->UseHWCursorARGB = NVUseHWCursorARGB;
308 infoPtr->LoadCursorARGB = NVLoadCursorARGB;
312 return(xf86InitCursor(pScreen, infoPtr));
315 #define CURSOR_PTR ((CARD32*)pNv->Cursor->map)
317 Bool NVCursorInitRandr12(ScreenPtr pScreen)
319 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
320 NVPtr pNv = NVPTR(pScrn);
321 int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
322 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
324 if (pNv->alphaCursor) { /* >= NV11 */
325 cursor_size = MAX_CURSOR_SIZE_ALPHA;
326 flags |= HARDWARE_CURSOR_ARGB;
328 cursor_size = MAX_CURSOR_SIZE;
330 return xf86_cursors_init(pScreen, cursor_size, cursor_size, flags);
333 void nv_crtc_show_cursor(xf86CrtcPtr crtc)
335 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
337 nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, true);
340 void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
342 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
344 nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, false);
347 void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
349 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
350 ScrnInfoPtr pScrn = crtc->scrn;
351 NVPtr pNv = NVPTR(pScrn);
353 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | (y << CURSOR_Y_SHIFT));
356 void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
358 ScrnInfoPtr pScrn = crtc->scrn;
359 NVPtr pNv = NVPTR(pScrn);
362 fore = ConvertToRGB555(fg);
363 back = ConvertToRGB555(bg);
364 #if X_BYTE_ORDER == X_BIG_ENDIAN
365 if(pNv->NVArch == 0x11) {
366 fore = ((fore & 0xff) << 8) | (fore >> 8);
367 back = ((back & 0xff) << 8) | (back >> 8);
371 /* Eventually this must be replaced as well */
372 if ((pNv->curFg != fore) || (pNv->curBg != back)) {
375 TransformCursor(pNv);
380 void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
382 ScrnInfoPtr pScrn = crtc->scrn;
383 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
384 NVPtr pNv = NVPTR(pScrn);
386 /* save copy of image for color changes */
387 memcpy(pNv->curImage, image, 256);
389 if (pNv->Architecture >= NV_ARCH_10) {
390 /* Due to legacy code */
391 if (nv_crtc->head == 1)
392 pNv->CURSOR = (CARD32 *) pNv->Cursor2->map;
394 pNv->CURSOR = (CARD32 *) pNv->Cursor->map;
397 /* Eventually this has to be replaced as well */
398 TransformCursor(pNv);
401 void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
403 ScrnInfoPtr pScrn = crtc->scrn;
404 struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
405 NVPtr pNv = NVPTR(pScrn);
406 uint32_t *dst = NULL;
407 uint32_t *src = (uint32_t *)image;
409 if (nv_crtc->head == 1) {
410 dst = (uint32_t *) pNv->Cursor2->map;
412 dst = (uint32_t *) pNv->Cursor->map;
415 /* It seems we get premultiplied alpha and the hardware takes non-premultiplied? */
416 /* This is needed, because without bit28 of cursorControl, we use what ever ROP is set currently */
417 /* This causes artifacts (on nv4x at least) */
419 uint32_t alpha, value;
421 if (pNv->NVArch == 0x11) { /* NV11 takes premultiplied cursors i think. */
422 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
423 for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
424 /* I suspect NV11 is the only card needing cursor byteswapping. */
425 #if X_BYTE_ORDER == X_BIG_ENDIAN
426 *dst++ = BYTE_SWAP_32(*src++);
433 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
434 for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
436 if (alpha == 0x0 || alpha == 0xff) {
439 value = ((((*src & 0xff) * 0xff) / alpha) & 0x000000ff) |
440 ((((*src & 0xff00) * 0xff) / alpha) & 0x0000ff00) |
441 ((((*src & 0xff0000) * 0xff) / alpha) & 0x00ff0000) |
442 ((alpha << 24) & 0xff000000);