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 NV_CURSOR_X 64
55 #define NV_CURSOR_Y 64
57 #define CURSOR_X_SHIFT 0
58 #define CURSOR_Y_SHIFT 16
59 #define CURSOR_POS_MASK 0xffff
61 #define TRANSPARENT_PIXEL 0
63 #define ConvertToRGB555(c) (((c & 0xf80000) >> 9 ) | /* Blue */ \
64 ((c & 0xf800) >> 6 ) | /* Green */ \
65 ((c & 0xf8) >> 3 ) | /* Red */ \
66 0x8000) /* Set upper bit, else we get complete transparency. */
68 #define ConvertToRGB888(c) (c | 0xff000000)
70 #define BYTE_SWAP_32(c) ((c & 0xff000000) >> 24) | \
71 ((c & 0xff0000) >> 8) | \
72 ((c & 0xff00) << 8) | \
75 /* Limit non-alpha cursors to 32x32 (x2 bytes) */
76 #define MAX_CURSOR_SIZE 32
78 /* Limit alpha cursors to 64x64 (x4 bytes) */
79 #define MAX_CURSOR_SIZE_ALPHA (MAX_CURSOR_SIZE * 2)
82 ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst)
87 for ( i = 0; i < MAX_CURSOR_SIZE; i++ ) {
90 for ( j = 0; j < MAX_CURSOR_SIZE; j++ ) {
91 #if X_BYTE_ORDER == X_BIG_ENDIAN
93 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
95 *dst = TRANSPARENT_PIXEL;
100 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
102 *dst = TRANSPARENT_PIXEL;
113 ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst)
118 /* Iterate over each byte in the cursor. */
119 for ( i = 0; i < MAX_CURSOR_SIZE * 4; i++ ) {
122 for ( j = 0; j < MAX_CURSOR_SIZE; j++ ) {
123 #if X_BYTE_ORDER == X_BIG_ENDIAN
125 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
127 *dst = TRANSPARENT_PIXEL;
132 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
134 *dst = TRANSPARENT_PIXEL;
145 TransformCursor (NVPtr pNv)
150 /* convert to color cursor */
151 if(pNv->alphaCursor) {
152 dwords = MAX_CURSOR_SIZE_ALPHA * MAX_CURSOR_SIZE_ALPHA;
153 if(!(tmp = xalloc(dwords * 4))) return;
154 ConvertCursor8888(pNv, pNv->curImage, tmp);
156 dwords = (MAX_CURSOR_SIZE * MAX_CURSOR_SIZE) >> 1;
157 if(!(tmp = xalloc(dwords * 4))) return;
158 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
161 for(i = 0; i < dwords; i++)
162 pNv->CURSOR[i] = tmp[i];
168 NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src )
170 NVPtr pNv = NVPTR(pScrn);
172 /* save copy of image for color changes */
173 memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256);
175 TransformCursor(pNv);
179 NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
181 NVPtr pNv = NVPTR(pScrn);
182 nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, (x & 0xFFFF) | (y << 16));
186 NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
188 NVPtr pNv = NVPTR(pScrn);
191 if(pNv->alphaCursor) {
192 fore = ConvertToRGB888(fg);
193 back = ConvertToRGB888(bg);
194 #if X_BYTE_ORDER == X_BIG_ENDIAN
195 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
196 fore = BYTE_SWAP_32(fore);
197 back = BYTE_SWAP_32(back);
201 fore = ConvertToRGB555(fg);
202 back = ConvertToRGB555(bg);
203 #if X_BYTE_ORDER == X_BIG_ENDIAN
204 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
205 fore = ((fore & 0xff) << 8) | (fore >> 8);
206 back = ((back & 0xff) << 8) | (back >> 8);
211 if ((pNv->curFg != fore) || (pNv->curBg != back)) {
215 TransformCursor(pNv);
221 NVShowCursor(ScrnInfoPtr pScrn)
223 NVPtr pNv = NVPTR(pScrn);
224 /* Enable cursor - X-Windows mode */
225 NVShowHideCursor(pNv, 1);
229 NVHideCursor(ScrnInfoPtr pScrn)
231 NVPtr pNv = NVPTR(pScrn);
233 NVShowHideCursor(pNv, 0);
237 NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
244 NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
246 if((pCurs->bits->width <= MAX_CURSOR_SIZE_ALPHA) && (pCurs->bits->height <= MAX_CURSOR_SIZE_ALPHA))
253 NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
255 NVPtr pNv = NVPTR(pScrn);
256 CARD32 *image = pCurs->bits->argb;
257 CARD32 *dst = (CARD32*)pNv->CURSOR;
261 w = pCurs->bits->width;
262 h = pCurs->bits->height;
264 if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) { /* premultiply */
265 for(y = 0; y < h; y++) {
266 for(x = 0; x < w; x++) {
267 alpha = *image >> 24;
271 tmp = (alpha << 24) |
272 (((*image & 0xff) * alpha) / 255) |
273 ((((*image & 0xff00) * alpha) / 255) & 0xff00) |
274 ((((*image & 0xff0000) * alpha) / 255) & 0xff0000);
277 #if X_BYTE_ORDER == X_BIG_ENDIAN
278 *dst++ = BYTE_SWAP_32(tmp);
283 for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
287 for(y = 0; y < h; y++) {
288 for(x = 0; x < w; x++)
290 for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
295 if(y < MAX_CURSOR_SIZE_ALPHA)
296 memset(dst, 0, MAX_CURSOR_SIZE_ALPHA * (MAX_CURSOR_SIZE_ALPHA - y) * 4);
301 NVCursorInit(ScreenPtr pScreen)
303 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
304 NVPtr pNv = NVPTR(pScrn);
305 xf86CursorInfoPtr infoPtr;
307 infoPtr = xf86CreateCursorInfoRec();
308 if(!infoPtr) return FALSE;
310 pNv->CursorInfoRec = infoPtr;
313 infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE_ALPHA;
315 infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE;
317 infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
318 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
319 infoPtr->SetCursorColors = NVSetCursorColors;
320 infoPtr->SetCursorPosition = NVSetCursorPosition;
321 infoPtr->LoadCursorImage = NVLoadCursorImage;
322 infoPtr->HideCursor = NVHideCursor;
323 infoPtr->ShowCursor = NVShowCursor;
324 infoPtr->UseHWCursor = NVUseHWCursor;
327 if(pNv->alphaCursor) {
328 infoPtr->UseHWCursorARGB = NVUseHWCursorARGB;
329 infoPtr->LoadCursorARGB = NVLoadCursorARGB;
333 return(xf86InitCursor(pScreen, infoPtr));
336 #define CURSOR_PTR ((CARD32*)pNv->Cursor->map)
338 Bool NVCursorInitRandr12(ScreenPtr pScreen)
340 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
341 NVPtr pNv = NVPTR(pScrn);
342 int flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
343 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32;
345 if (pNv->alphaCursor) { /* >= NV11 */
346 cursor_size = MAX_CURSOR_SIZE_ALPHA;
347 flags |= HARDWARE_CURSOR_ARGB;
349 cursor_size = MAX_CURSOR_SIZE;
351 return xf86_cursors_init(pScreen, cursor_size, cursor_size, flags);
354 void nv_crtc_show_cursor(xf86CrtcPtr crtc)
356 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
357 ScrnInfoPtr pScrn = crtc->scrn;
358 NVPtr pNv = NVPTR(pScrn);
359 int current = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1);
361 /* Enable on this crtc */
362 NVWriteVGA(pNv, nv_crtc->head, NV_VGA_CRTCX_CURCTL1, current | 1);
364 if (pNv->Architecture == NV_ARCH_40) { /* HW bug */
365 volatile CARD32 curpos = nvReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS);
366 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, curpos);
370 void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
372 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
373 ScrnInfoPtr pScrn = crtc->scrn;
374 NVPtr pNv = NVPTR(pScrn);
375 int current = NVReadVgaCrtc(crtc, NV_VGA_CRTCX_CURCTL1);
377 /* Disable on this crtc */
378 NVWriteVGA(pNv, nv_crtc->head, NV_VGA_CRTCX_CURCTL1, current & ~1);
380 if (pNv->Architecture == NV_ARCH_40) { /* HW bug */
381 volatile CARD32 curpos = nvReadRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS);
382 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, curpos);
386 void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
388 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
389 ScrnInfoPtr pScrn = crtc->scrn;
390 NVPtr pNv = NVPTR(pScrn);
392 nvWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | (y << CURSOR_Y_SHIFT));
395 void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
397 ScrnInfoPtr pScrn = crtc->scrn;
398 NVPtr pNv = NVPTR(pScrn);
401 fore = ConvertToRGB555(fg);
402 back = ConvertToRGB555(bg);
403 #if X_BYTE_ORDER == X_BIG_ENDIAN
404 if(pNv->NVArch == 0x11) {
405 fore = ((fore & 0xff) << 8) | (fore >> 8);
406 back = ((back & 0xff) << 8) | (back >> 8);
410 /* Eventually this must be replaced as well */
411 if ((pNv->curFg != fore) || (pNv->curBg != back)) {
414 TransformCursor(pNv);
419 void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
421 ScrnInfoPtr pScrn = crtc->scrn;
422 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
423 NVPtr pNv = NVPTR(pScrn);
425 /* save copy of image for color changes */
426 memcpy(pNv->curImage, image, 256);
428 /* Due to legacy code */
429 if (nv_crtc->head == 1) {
430 pNv->CURSOR = (CARD32 *) pNv->Cursor2->map;
432 pNv->CURSOR = (CARD32 *) pNv->Cursor->map;
435 /* Eventually this has to be replaced as well */
436 TransformCursor(pNv);
439 void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
441 ScrnInfoPtr pScrn = crtc->scrn;
442 NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
443 NVPtr pNv = NVPTR(pScrn);
444 uint32_t *dst = NULL;
445 uint32_t *src = image;
447 if (nv_crtc->head == 1) {
448 dst = (uint32_t *) pNv->Cursor2->map;
450 dst = (uint32_t *) pNv->Cursor->map;
453 /* It seems we get premultiplied alpha and the hardware takes non-premultiplied? */
454 /* This is needed, because without bit28 of cursorControl, we use what ever ROP is set currently */
455 /* This causes artifacts (on nv4x at least) */
457 uint32_t alpha, value;
459 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
460 for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
462 if (alpha == 0x0 || alpha == 0xff) {
465 value = ((((*src & 0xff) * 0xff) / alpha) & 0x000000ff) |
466 ((((*src & 0xff00) * 0xff) / alpha) & 0x0000ff00) |
467 ((((*src & 0xff0000) * 0xff) / alpha) & 0x00ff0000) |
468 ((alpha << 24) & 0xff000000);
471 #if X_BYTE_ORDER == X_BIG_ENDIAN
472 *dst++ = BYTE_SWAP_32(value);