1 /***************************************************************************\
3 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
5 |* NOTICE TO USER: The source code is copyrighted under U.S. and *|
6 |* international laws. Users and possessors of this source code are *|
7 |* hereby granted a nonexclusive, royalty-free copyright license to *|
8 |* use this code in individual and commercial software. *|
10 |* Any use of this source code must include, in the user documenta- *|
11 |* tion and internal comments to the code, notices to the end user *|
14 |* Copyright 2003 NVIDIA, Corporation. All rights reserved. *|
16 |* NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY *|
17 |* OF THIS SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" *|
18 |* WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND. NVIDIA, CORPOR- *|
19 |* ATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOURCE CODE, *|
20 |* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE- *|
21 |* MENT, AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL *|
22 |* NVIDIA, CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT, INCI- *|
23 |* DENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RE- *|
24 |* SULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION *|
25 |* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *|
26 |* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. *|
28 |* U.S. Government End Users. This source code is a "commercial *|
29 |* item," as that term is defined at 48 C.F.R. 2.101 (OCT 1995), *|
30 |* consisting of "commercial computer software" and "commercial *|
31 |* computer software documentation," as such terms are used in *|
32 |* 48 C.F.R. 12.212 (SEPT 1995) and is provided to the U.S. Govern- *|
33 |* ment only as a commercial end item. Consistent with 48 C.F.R. *|
34 |* 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (JUNE 1995), *|
35 |* all U.S. Government End Users acquire the source code with only *|
36 |* those rights set forth herein. *|
38 \***************************************************************************/
40 /* Copyright 2007 Maarten Maathuis */
42 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_cursor.c,v 1.13 2004/03/13 22:07:05 mvojkovi Exp $ */
44 #include "nv_include.h"
46 #include "cursorstr.h"
48 /****************************************************************************\
50 * HW Cursor Entrypoints *
52 \****************************************************************************/
54 #define CURSOR_X_SHIFT 0
55 #define CURSOR_Y_SHIFT 16
56 #define CURSOR_POS_MASK 0xffff
58 #define TRANSPARENT_PIXEL 0
60 #define ConvertToRGB555(c) (((c & 0xf80000) >> 9 ) | /* Blue */ \
61 ((c & 0xf800) >> 6 ) | /* Green */ \
62 ((c & 0xf8) >> 3 ) | /* Red */ \
63 0x8000) /* Set upper bit, else we get complete transparency. */
65 #define ConvertToRGB888(c) (c | 0xff000000)
67 #define BYTE_SWAP_32(c) ((c & 0xff000000) >> 24) | \
68 ((c & 0xff0000) >> 8) | \
69 ((c & 0xff00) << 8) | \
72 /* Limit non-alpha cursors to 32x32 (x2 bytes) */
73 #define MAX_CURSOR_SIZE 32
75 /* Limit alpha cursors to 64x64 (x4 bytes) */
76 #define MAX_CURSOR_SIZE_ALPHA (MAX_CURSOR_SIZE * 2)
79 ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst)
83 int sz=pNv->NVArch==0x10?MAX_CURSOR_SIZE_ALPHA:MAX_CURSOR_SIZE;
85 for ( i = 0; i < sz; i++ ) {
88 for ( j = 0; j < sz; j++ ) {
89 #if X_BYTE_ORDER == X_BIG_ENDIAN
91 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
93 *dst = TRANSPARENT_PIXEL;
98 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
100 *dst = TRANSPARENT_PIXEL;
111 ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst)
116 /* Iterate over each byte in the cursor. */
117 for ( i = 0; i < MAX_CURSOR_SIZE * 4; i++ ) {
120 for ( j = 0; j < MAX_CURSOR_SIZE; j++ ) {
121 #if X_BYTE_ORDER == X_BIG_ENDIAN
123 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
125 *dst = TRANSPARENT_PIXEL;
130 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
132 *dst = TRANSPARENT_PIXEL;
142 TransformCursor (NVPtr pNv)
147 /* convert to color cursor */
148 if(pNv->NVArch==0x10) {
149 dwords = (MAX_CURSOR_SIZE_ALPHA * MAX_CURSOR_SIZE_ALPHA) >> 1;
150 if(!(tmp = xalloc(dwords * 4))) return;
151 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
152 } else if(pNv->alphaCursor) {
153 dwords = MAX_CURSOR_SIZE_ALPHA * MAX_CURSOR_SIZE_ALPHA;
154 if(!(tmp = xalloc(dwords * 4))) return;
155 ConvertCursor8888(pNv, pNv->curImage, tmp);
157 dwords = (MAX_CURSOR_SIZE * MAX_CURSOR_SIZE) >> 1;
158 if(!(tmp = xalloc(dwords * 4))) return;
159 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
162 for(i = 0; i < dwords; i++)
163 pNv->CURSOR[i] = tmp[i];
169 NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src )
171 NVPtr pNv = NVPTR(pScrn);
173 /* save copy of image for color changes */
174 memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256);
176 TransformCursor(pNv);
180 NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
182 NVPtr pNv = NVPTR(pScrn);
183 nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, (x & 0xFFFF) | (y << 16));
187 NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
189 NVPtr pNv = NVPTR(pScrn);
192 if(pNv->alphaCursor) {
193 fore = ConvertToRGB888(fg);
194 back = ConvertToRGB888(bg);
195 #if X_BYTE_ORDER == X_BIG_ENDIAN
196 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
197 fore = BYTE_SWAP_32(fore);
198 back = BYTE_SWAP_32(back);
202 fore = ConvertToRGB555(fg);
203 back = ConvertToRGB555(bg);
204 #if X_BYTE_ORDER == X_BIG_ENDIAN
205 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
206 fore = ((fore & 0xff) << 8) | (fore >> 8);
207 back = ((back & 0xff) << 8) | (back >> 8);
212 if ((pNv->curFg != fore) || (pNv->curBg != back)) {
216 TransformCursor(pNv);
222 NVShowCursor(ScrnInfoPtr pScrn)
224 /* Enable cursor - X-Windows mode */
225 NVShowHideCursor(pScrn, 1);
229 NVHideCursor(ScrnInfoPtr pScrn)
232 NVShowHideCursor(pScrn, 0);
236 NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
243 NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
245 if((pCurs->bits->width <= MAX_CURSOR_SIZE_ALPHA) && (pCurs->bits->height <= MAX_CURSOR_SIZE_ALPHA))
252 NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
254 NVPtr pNv = NVPTR(pScrn);
255 CARD32 *image = pCurs->bits->argb;
256 CARD32 *dst = (CARD32*)pNv->CURSOR;
260 w = pCurs->bits->width;
261 h = pCurs->bits->height;
263 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) { /* premultiply */
264 for(y = 0; y < h; y++) {
265 for(x = 0; x < w; x++) {
266 alpha = *image >> 24;
270 tmp = (alpha << 24) |
271 (((*image & 0xff) * alpha) / 255) |
272 ((((*image & 0xff00) * alpha) / 255) & 0xff00) |
273 ((((*image & 0xff0000) * alpha) / 255) & 0xff0000);
276 #if X_BYTE_ORDER == X_BIG_ENDIAN
277 *dst++ = BYTE_SWAP_32(tmp);
282 for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
286 for(y = 0; y < h; y++) {
287 for(x = 0; x < w; x++)
289 for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
294 if(y < MAX_CURSOR_SIZE_ALPHA)
295 memset(dst, 0, MAX_CURSOR_SIZE_ALPHA * (MAX_CURSOR_SIZE_ALPHA - y) * 4);
300 NVCursorInit(ScreenPtr pScreen)
302 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
303 NVPtr pNv = NVPTR(pScrn);
304 xf86CursorInfoPtr infoPtr;
306 infoPtr = xf86CreateCursorInfoRec();
307 if(!infoPtr) return FALSE;
309 pNv->CursorInfoRec = infoPtr;
312 infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE_ALPHA;
314 infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE;
316 infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
317 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
318 infoPtr->SetCursorColors = NVSetCursorColors;
319 infoPtr->SetCursorPosition = NVSetCursorPosition;
320 infoPtr->LoadCursorImage = NVLoadCursorImage;
321 infoPtr->HideCursor = NVHideCursor;
322 infoPtr->ShowCursor = NVShowCursor;
323 infoPtr->UseHWCursor = NVUseHWCursor;
326 if(pNv->alphaCursor) {
327 infoPtr->UseHWCursorARGB = NVUseHWCursorARGB;
328 infoPtr->LoadCursorARGB = NVLoadCursorARGB;
332 return(xf86InitCursor(pScreen, infoPtr));
335 #define CURSOR_PTR ((CARD32*)pNv->Cursor->map)
337 Bool NVCursorInitRandr12(ScreenPtr pScreen)
339 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
340 NVPtr pNv = NVPTR(pScrn);
341 int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
342 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
344 if (pNv->alphaCursor) { /* >= NV11 */
345 cursor_size = MAX_CURSOR_SIZE_ALPHA;
346 flags |= HARDWARE_CURSOR_ARGB;
348 cursor_size = MAX_CURSOR_SIZE;
350 return xf86_cursors_init(pScreen, cursor_size, cursor_size, flags);
353 void nv_crtc_fix_nv40_hw_cursor(ScrnInfoPtr pScrn, uint8_t head)
355 NVPtr pNv = NVPTR(pScrn);
356 volatile uint32_t curpos = NVReadRAMDAC(pNv, head, NV_RAMDAC_CURSOR_POS);
357 NVWriteRAMDAC(pNv, head, NV_RAMDAC_CURSOR_POS, curpos);
360 void nv_crtc_show_hide_cursor(ScrnInfoPtr pScrn, uint8_t head, Bool show)
362 NVPtr pNv = NVPTR(pScrn);
363 int curctl1 = NVReadVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1);
366 NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1, curctl1 | 1);
368 NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1, curctl1 & ~1);
370 if (pNv->Architecture == NV_ARCH_40) /* HW bug */
371 nv_crtc_fix_nv40_hw_cursor(pScrn, head);
374 void nv_crtc_show_cursor(xf86CrtcPtr crtc)
376 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
377 ScrnInfoPtr pScrn = crtc->scrn;
379 nv_crtc->cursorVisible = TRUE;
381 nv_crtc_show_hide_cursor(pScrn, nv_crtc->head, TRUE);
384 void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
386 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
387 ScrnInfoPtr pScrn = crtc->scrn;
389 nv_crtc->cursorVisible = FALSE;
391 nv_crtc_show_hide_cursor(pScrn, nv_crtc->head, FALSE);
394 void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
396 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
397 ScrnInfoPtr pScrn = crtc->scrn;
398 NVPtr pNv = NVPTR(pScrn);
400 NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | (y << CURSOR_Y_SHIFT));
403 void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
405 ScrnInfoPtr pScrn = crtc->scrn;
406 NVPtr pNv = NVPTR(pScrn);
409 fore = ConvertToRGB555(fg);
410 back = ConvertToRGB555(bg);
411 #if X_BYTE_ORDER == X_BIG_ENDIAN
412 if(pNv->NVArch == 0x11) {
413 fore = ((fore & 0xff) << 8) | (fore >> 8);
414 back = ((back & 0xff) << 8) | (back >> 8);
418 /* Eventually this must be replaced as well */
419 if ((pNv->curFg != fore) || (pNv->curBg != back)) {
422 TransformCursor(pNv);
427 void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
429 ScrnInfoPtr pScrn = crtc->scrn;
430 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
431 NVPtr pNv = NVPTR(pScrn);
433 /* save copy of image for color changes */
434 memcpy(pNv->curImage, image, 256);
436 if (pNv->Architecture >= NV_ARCH_10) {
437 /* Due to legacy code */
438 if (nv_crtc->head == 1)
439 pNv->CURSOR = (CARD32 *) pNv->Cursor2->map;
441 pNv->CURSOR = (CARD32 *) pNv->Cursor->map;
444 /* Eventually this has to be replaced as well */
445 TransformCursor(pNv);
448 void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
450 ScrnInfoPtr pScrn = crtc->scrn;
451 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
452 NVPtr pNv = NVPTR(pScrn);
453 uint32_t *dst = NULL;
454 uint32_t *src = (uint32_t *)image;
456 if (nv_crtc->head == 1) {
457 dst = (uint32_t *) pNv->Cursor2->map;
459 dst = (uint32_t *) pNv->Cursor->map;
462 /* It seems we get premultiplied alpha and the hardware takes non-premultiplied? */
463 /* This is needed, because without bit28 of cursorControl, we use what ever ROP is set currently */
464 /* This causes artifacts (on nv4x at least) */
466 uint32_t alpha, value;
468 if (pNv->NVArch == 0x11) { /* NV11 takes premultiplied cursors i think. */
469 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
470 for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
471 /* I suspect NV11 is the only card needing cursor byteswapping. */
472 #if X_BYTE_ORDER == X_BIG_ENDIAN
473 *dst++ = BYTE_SWAP_32(*src++);
480 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
481 for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
483 if (alpha == 0x0 || alpha == 0xff) {
486 value = ((((*src & 0xff) * 0xff) / alpha) & 0x000000ff) |
487 ((((*src & 0xff00) * 0xff) / alpha) & 0x0000ff00) |
488 ((((*src & 0xff0000) * 0xff) / alpha) & 0x00ff0000) |
489 ((alpha << 24) & 0xff000000);