NV50: Remove the remnants of cached_status.
[nouveau] / src / nv_cursor.c
1  /***************************************************************************\
2 |*                                                                           *|
3 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
4 |*                                                                           *|
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.                  *|
9 |*                                                                           *|
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     *|
12 |*     as follows:                                                           *|
13 |*                                                                           *|
14 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
15 |*                                                                           *|
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.     *|
27 |*                                                                           *|
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.                                        *|
37 |*                                                                           *|
38  \***************************************************************************/
39
40 /* Copyright 2007 Maarten Maathuis */
41
42 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_cursor.c,v 1.13 2004/03/13 22:07:05 mvojkovi Exp $ */
43
44 #include "nv_include.h"
45
46 #include "cursorstr.h"
47
48 /****************************************************************************\
49 *                                                                            *
50 *                          HW Cursor Entrypoints                             *
51 *                                                                            *
52 \****************************************************************************/
53
54 #define CURSOR_X_SHIFT 0
55 #define CURSOR_Y_SHIFT 16
56 #define CURSOR_POS_MASK 0xffff
57
58 #define TRANSPARENT_PIXEL   0
59
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. */
64
65 #define ConvertToRGB888(c) (c | 0xff000000)
66
67 #define BYTE_SWAP_32(c)  ((c & 0xff000000) >> 24) |  \
68                          ((c & 0xff0000) >> 8) |     \
69                          ((c & 0xff00) << 8) |       \
70                          ((c & 0xff) << 24)
71
72 /* Limit non-alpha cursors to 32x32 (x2 bytes) */
73 #define MAX_CURSOR_SIZE 32
74
75 /* Limit alpha cursors to 64x64 (x4 bytes) */
76 #define MAX_CURSOR_SIZE_ALPHA (MAX_CURSOR_SIZE * 2)
77
78 static void 
79 ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst)
80 {
81         CARD32 b, m;
82         int i, j;
83         int sz=pNv->NVArch==0x10?MAX_CURSOR_SIZE_ALPHA:MAX_CURSOR_SIZE;
84
85         for ( i = 0; i < sz; i++ ) {
86                 b = *src++;
87                 m = *src++;
88                 for ( j = 0; j < sz; j++ ) {
89 #if X_BYTE_ORDER == X_BIG_ENDIAN
90                         if ( m & 0x80000000)
91                                 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
92                         else
93                                 *dst = TRANSPARENT_PIXEL;
94                         b <<= 1;
95                         m <<= 1;
96 #else
97                         if ( m & 1 )
98                                 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
99                         else
100                                 *dst = TRANSPARENT_PIXEL;
101                         b >>= 1;
102                         m >>= 1;
103 #endif
104                         dst++;
105                 }
106         }
107 }
108
109
110 static void
111 ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst)
112 {
113         CARD32 b, m;
114         int i, j;
115
116         /* Iterate over each byte in the cursor. */
117         for ( i = 0; i < MAX_CURSOR_SIZE * 4; i++ ) {
118                 b = *src++;
119                 m = *src++;
120                 for ( j = 0; j < MAX_CURSOR_SIZE; j++ ) {
121 #if X_BYTE_ORDER == X_BIG_ENDIAN
122                         if ( m & 0x80000000)
123                                 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
124                         else
125                                 *dst = TRANSPARENT_PIXEL;
126                         b <<= 1;
127                         m <<= 1;
128 #else
129                         if ( m & 1 )
130                                 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
131                         else
132                                 *dst = TRANSPARENT_PIXEL;
133                         b >>= 1;
134                         m >>= 1;
135 #endif
136                         dst++;
137                 }
138         }
139 }
140
141 static void
142 TransformCursor (NVPtr pNv)
143 {
144         CARD32 *tmp;
145         int i, dwords;
146
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);
156         } else {
157                 dwords = (MAX_CURSOR_SIZE * MAX_CURSOR_SIZE) >> 1;
158                 if(!(tmp = xalloc(dwords * 4))) return;
159                 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
160         }
161
162         for(i = 0; i < dwords; i++)
163                 pNv->CURSOR[i] = tmp[i];
164
165         xfree(tmp);
166 }
167
168 static void
169 NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src )
170 {
171     NVPtr pNv = NVPTR(pScrn);
172
173     /* save copy of image for color changes */
174     memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256);
175
176     TransformCursor(pNv);
177 }
178
179 static void
180 NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
181 {
182         NVPtr pNv = NVPTR(pScrn);
183         nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, (x & 0xFFFF) | (y << 16));
184 }
185
186 static void
187 NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
188 {
189     NVPtr pNv = NVPTR(pScrn);
190     CARD32 fore, back;
191
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);
199         }
200 #endif
201     } else {
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);
208         }
209 #endif
210    }
211
212     if ((pNv->curFg != fore) || (pNv->curBg != back)) {
213         pNv->curFg = fore;
214         pNv->curBg = back;
215             
216         TransformCursor(pNv);
217     }
218 }
219
220
221 static void 
222 NVShowCursor(ScrnInfoPtr pScrn)
223 {
224         /* Enable cursor - X-Windows mode */
225         NVShowHideCursor(pScrn, 1);
226 }
227
228 static void
229 NVHideCursor(ScrnInfoPtr pScrn)
230 {
231         /* Disable cursor */
232         NVShowHideCursor(pScrn, 0);
233 }
234
235 static Bool 
236 NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
237 {
238         return TRUE;
239 }
240
241 #ifdef ARGB_CURSOR
242 static Bool 
243 NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
244 {
245     if((pCurs->bits->width <= MAX_CURSOR_SIZE_ALPHA) && (pCurs->bits->height <= MAX_CURSOR_SIZE_ALPHA))
246         return TRUE;
247
248     return FALSE;
249 }
250
251 static void
252 NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
253 {
254     NVPtr pNv = NVPTR(pScrn);
255     CARD32 *image = pCurs->bits->argb;
256     CARD32 *dst = (CARD32*)pNv->CURSOR;
257     CARD32 alpha, tmp;
258     int x, y, w, h;
259
260     w = pCurs->bits->width;
261     h = pCurs->bits->height;
262
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;
267              if(alpha == 0xff)
268                 tmp = *image;
269              else {
270                 tmp = (alpha << 24) |
271                          (((*image & 0xff) * alpha) / 255) |
272                         ((((*image & 0xff00) * alpha) / 255) & 0xff00) |
273                        ((((*image & 0xff0000) * alpha) / 255) & 0xff0000); 
274              }
275              image++;
276 #if X_BYTE_ORDER == X_BIG_ENDIAN
277              *dst++ = BYTE_SWAP_32(tmp);
278 #else
279              *dst++ = tmp;
280 #endif
281          }
282          for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
283              *dst++ = 0;
284       }
285     } else {
286        for(y = 0; y < h; y++) {
287           for(x = 0; x < w; x++)
288               *dst++ = *image++;
289           for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
290               *dst++ = 0;
291        }
292     }
293
294     if(y < MAX_CURSOR_SIZE_ALPHA)
295       memset(dst, 0, MAX_CURSOR_SIZE_ALPHA * (MAX_CURSOR_SIZE_ALPHA - y) * 4);
296 }
297 #endif
298
299 Bool 
300 NVCursorInit(ScreenPtr pScreen)
301 {
302     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
303     NVPtr pNv = NVPTR(pScrn);
304     xf86CursorInfoPtr infoPtr;
305
306     infoPtr = xf86CreateCursorInfoRec();
307     if(!infoPtr) return FALSE;
308     
309     pNv->CursorInfoRec = infoPtr;
310
311     if(pNv->alphaCursor)
312        infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE_ALPHA;
313     else
314        infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE;
315
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;
324
325 #ifdef ARGB_CURSOR
326     if(pNv->alphaCursor) {
327        infoPtr->UseHWCursorARGB = NVUseHWCursorARGB;
328        infoPtr->LoadCursorARGB = NVLoadCursorARGB;
329     }
330 #endif
331
332     return(xf86InitCursor(pScreen, infoPtr));
333 }
334
335 #define CURSOR_PTR ((CARD32*)pNv->Cursor->map)
336
337 Bool NVCursorInitRandr12(ScreenPtr pScreen)
338 {
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;
343         int cursor_size = 0;
344         if (pNv->alphaCursor) { /* >= NV11 */
345                 cursor_size = MAX_CURSOR_SIZE_ALPHA;
346                 flags |= HARDWARE_CURSOR_ARGB;
347         } else {
348                 cursor_size = MAX_CURSOR_SIZE;
349         }
350         return xf86_cursors_init(pScreen, cursor_size, cursor_size, flags);
351 }
352
353 void nv_crtc_fix_nv40_hw_cursor(ScrnInfoPtr pScrn, uint8_t head)
354 {
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);
358 }
359
360 void nv_crtc_show_hide_cursor(ScrnInfoPtr pScrn, uint8_t head, Bool show)
361 {
362         NVPtr pNv = NVPTR(pScrn);
363         int curctl1 = NVReadVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1);
364
365         if (show)
366                 NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1, curctl1 | 1);
367         else
368                 NVWriteVgaCrtc(pNv, head, NV_VGA_CRTCX_CURCTL1, curctl1 & ~1);
369
370         if (pNv->Architecture == NV_ARCH_40) /* HW bug */
371                 nv_crtc_fix_nv40_hw_cursor(pScrn, head);
372 }
373
374 void nv_crtc_show_cursor(xf86CrtcPtr crtc)
375 {
376         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
377         ScrnInfoPtr pScrn = crtc->scrn;
378
379         nv_crtc->cursorVisible = TRUE;
380
381         nv_crtc_show_hide_cursor(pScrn, nv_crtc->head, TRUE);
382 }
383
384 void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
385 {
386         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
387         ScrnInfoPtr pScrn = crtc->scrn;
388
389         nv_crtc->cursorVisible = FALSE;
390
391         nv_crtc_show_hide_cursor(pScrn, nv_crtc->head, FALSE);
392 }
393
394 void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
395 {
396         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
397         ScrnInfoPtr pScrn = crtc->scrn;
398         NVPtr pNv = NVPTR(pScrn);
399
400         NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | (y << CURSOR_Y_SHIFT));
401 }
402
403 void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
404 {
405         ScrnInfoPtr pScrn = crtc->scrn;
406         NVPtr pNv = NVPTR(pScrn);
407         CARD32 fore, back;
408
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);
415         }
416 #endif
417
418         /* Eventually this must be replaced as well */
419         if ((pNv->curFg != fore) || (pNv->curBg != back)) {
420                 pNv->curFg = fore;
421                 pNv->curBg = back;
422                 TransformCursor(pNv);
423         }
424 }
425
426
427 void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
428 {
429         ScrnInfoPtr pScrn = crtc->scrn;
430         NVCrtcPrivatePtr nv_crtc = crtc->driver_private;
431         NVPtr pNv = NVPTR(pScrn);
432
433         /* save copy of image for color changes */
434         memcpy(pNv->curImage, image, 256);
435
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;
440                 else
441                         pNv->CURSOR = (CARD32 *) pNv->Cursor->map;
442         }
443
444         /* Eventually this has to be replaced as well */
445         TransformCursor(pNv);
446 }
447
448 void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
449 {
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;
455
456         if (nv_crtc->head == 1) {
457                 dst = (uint32_t *) pNv->Cursor2->map;
458         } else {
459                 dst = (uint32_t *) pNv->Cursor->map;
460         }
461
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) */
465         int x, y;
466         uint32_t alpha, value;
467
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++);
474                                 #else
475                                         *dst++ = *src++;
476                                 #endif
477                         }
478                 }
479         } else {
480                 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
481                         for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
482                                 alpha = *src >> 24;
483                                 if (alpha == 0x0 || alpha == 0xff) {
484                                         value = *src;
485                                 } else {
486                                         value =         ((((*src & 0xff) * 0xff) / alpha)               & 0x000000ff)   |
487                                                         ((((*src & 0xff00) * 0xff) / alpha)     & 0x0000ff00)   |
488                                                         ((((*src & 0xff0000) * 0xff) / alpha)   & 0x00ff0000)   |
489                                                         ((alpha << 24)                          & 0xff000000);
490                                 }
491                                 src++;
492                                 *dst++ = value;
493                         }
494                 }
495         }
496 }