Move cursor show/hide funcs to nv_hw, document nv40 bug, and set curctl2 before apply...
[nouveau] / src / nv_cursor.c
1 /*
2  * Copyright 2003 NVIDIA, Corporation
3  * Copyright 2007 Maarten Maathuis
4  *
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:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
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
21  * SOFTWARE.
22  */
23
24 #include "nv_include.h"
25
26 #include "cursorstr.h"
27
28 /****************************************************************************\
29 *                                                                            *
30 *                          HW Cursor Entrypoints                             *
31 *                                                                            *
32 \****************************************************************************/
33
34 #define CURSOR_X_SHIFT 0
35 #define CURSOR_Y_SHIFT 16
36 #define CURSOR_POS_MASK 0xffff
37
38 #define TRANSPARENT_PIXEL   0
39
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. */
44
45 #define ConvertToRGB888(c) (c | 0xff000000)
46
47 #define BYTE_SWAP_32(c)  ((c & 0xff000000) >> 24) |  \
48                          ((c & 0xff0000) >> 8) |     \
49                          ((c & 0xff00) << 8) |       \
50                          ((c & 0xff) << 24)
51
52 /* Limit non-alpha cursors to 32x32 (x2 bytes) */
53 #define MAX_CURSOR_SIZE 32
54
55 /* Limit alpha cursors to 64x64 (x4 bytes) */
56 #define MAX_CURSOR_SIZE_ALPHA (MAX_CURSOR_SIZE * 2)
57
58 static void 
59 ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst)
60 {
61         CARD32 b, m;
62         int i, j;
63         int sz=pNv->NVArch==0x10?MAX_CURSOR_SIZE_ALPHA:MAX_CURSOR_SIZE;
64
65         for ( i = 0; i < sz; i++ ) {
66                 b = *src++;
67                 m = *src++;
68                 for ( j = 0; j < sz; j++ ) {
69 #if X_BYTE_ORDER == X_BIG_ENDIAN
70                         if ( m & 0x80000000)
71                                 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
72                         else
73                                 *dst = TRANSPARENT_PIXEL;
74                         b <<= 1;
75                         m <<= 1;
76 #else
77                         if ( m & 1 )
78                                 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
79                         else
80                                 *dst = TRANSPARENT_PIXEL;
81                         b >>= 1;
82                         m >>= 1;
83 #endif
84                         dst++;
85                 }
86         }
87 }
88
89
90 static void
91 ConvertCursor8888(NVPtr pNv, CARD32 *src, CARD32 *dst)
92 {
93         CARD32 b, m;
94         int i, j;
95
96         /* Iterate over each byte in the cursor. */
97         for ( i = 0; i < MAX_CURSOR_SIZE * 4; i++ ) {
98                 b = *src++;
99                 m = *src++;
100                 for ( j = 0; j < MAX_CURSOR_SIZE; j++ ) {
101 #if X_BYTE_ORDER == X_BIG_ENDIAN
102                         if ( m & 0x80000000)
103                                 *dst = ( b & 0x80000000) ? pNv->curFg : pNv->curBg;
104                         else
105                                 *dst = TRANSPARENT_PIXEL;
106                         b <<= 1;
107                         m <<= 1;
108 #else
109                         if ( m & 1 )
110                                 *dst = ( b & 1) ? pNv->curFg : pNv->curBg;
111                         else
112                                 *dst = TRANSPARENT_PIXEL;
113                         b >>= 1;
114                         m >>= 1;
115 #endif
116                         dst++;
117                 }
118         }
119 }
120
121 static void
122 TransformCursor (NVPtr pNv)
123 {
124         CARD32 *tmp;
125         int i, dwords;
126
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);
136         } else {
137                 dwords = (MAX_CURSOR_SIZE * MAX_CURSOR_SIZE) >> 1;
138                 if(!(tmp = xalloc(dwords * 4))) return;
139                 ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
140         }
141
142         for(i = 0; i < dwords; i++)
143                 pNv->CURSOR[i] = tmp[i];
144
145         xfree(tmp);
146 }
147
148 static void
149 NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src )
150 {
151     NVPtr pNv = NVPTR(pScrn);
152
153     /* save copy of image for color changes */
154     memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256);
155
156     TransformCursor(pNv);
157 }
158
159 static void
160 NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
161 {
162         NVPtr pNv = NVPTR(pScrn);
163         nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, (x & 0xFFFF) | (y << 16));
164 }
165
166 static void
167 NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
168 {
169     NVPtr pNv = NVPTR(pScrn);
170     CARD32 fore, back;
171
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);
179         }
180 #endif
181     } else {
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);
188         }
189 #endif
190    }
191
192     if ((pNv->curFg != fore) || (pNv->curBg != back)) {
193         pNv->curFg = fore;
194         pNv->curBg = back;
195             
196         TransformCursor(pNv);
197     }
198 }
199
200
201 static void 
202 NVShowCursor(ScrnInfoPtr pScrn)
203 {
204         /* Enable cursor - X-Windows mode */
205         NVShowHideCursor(pScrn, 1);
206 }
207
208 static void
209 NVHideCursor(ScrnInfoPtr pScrn)
210 {
211         /* Disable cursor */
212         NVShowHideCursor(pScrn, 0);
213 }
214
215 static Bool 
216 NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
217 {
218         return TRUE;
219 }
220
221 #ifdef ARGB_CURSOR
222 static Bool 
223 NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
224 {
225     if((pCurs->bits->width <= MAX_CURSOR_SIZE_ALPHA) && (pCurs->bits->height <= MAX_CURSOR_SIZE_ALPHA))
226         return TRUE;
227
228     return FALSE;
229 }
230
231 static void
232 NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
233 {
234     NVPtr pNv = NVPTR(pScrn);
235     CARD32 *image = pCurs->bits->argb;
236     CARD32 *dst = (CARD32*)pNv->CURSOR;
237     CARD32 alpha, tmp;
238     int x, y, w, h;
239
240     w = pCurs->bits->width;
241     h = pCurs->bits->height;
242
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;
247              if(alpha == 0xff)
248                 tmp = *image;
249              else {
250                 tmp = (alpha << 24) |
251                          (((*image & 0xff) * alpha) / 255) |
252                         ((((*image & 0xff00) * alpha) / 255) & 0xff00) |
253                        ((((*image & 0xff0000) * alpha) / 255) & 0xff0000); 
254              }
255              image++;
256 #if X_BYTE_ORDER == X_BIG_ENDIAN
257              *dst++ = BYTE_SWAP_32(tmp);
258 #else
259              *dst++ = tmp;
260 #endif
261          }
262          for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
263              *dst++ = 0;
264       }
265     } else {
266        for(y = 0; y < h; y++) {
267           for(x = 0; x < w; x++)
268               *dst++ = *image++;
269           for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
270               *dst++ = 0;
271        }
272     }
273
274     if(y < MAX_CURSOR_SIZE_ALPHA)
275       memset(dst, 0, MAX_CURSOR_SIZE_ALPHA * (MAX_CURSOR_SIZE_ALPHA - y) * 4);
276 }
277 #endif
278
279 Bool 
280 NVCursorInit(ScreenPtr pScreen)
281 {
282     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
283     NVPtr pNv = NVPTR(pScrn);
284     xf86CursorInfoPtr infoPtr;
285
286     infoPtr = xf86CreateCursorInfoRec();
287     if(!infoPtr) return FALSE;
288     
289     pNv->CursorInfoRec = infoPtr;
290
291     if(pNv->alphaCursor)
292        infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE_ALPHA;
293     else
294        infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE;
295
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;
304
305 #ifdef ARGB_CURSOR
306     if(pNv->alphaCursor) {
307        infoPtr->UseHWCursorARGB = NVUseHWCursorARGB;
308        infoPtr->LoadCursorARGB = NVLoadCursorARGB;
309     }
310 #endif
311
312     return(xf86InitCursor(pScreen, infoPtr));
313 }
314
315 #define CURSOR_PTR ((CARD32*)pNv->Cursor->map)
316
317 Bool NVCursorInitRandr12(ScreenPtr pScreen)
318 {
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;
323         int cursor_size = 0;
324         if (pNv->alphaCursor) { /* >= NV11 */
325                 cursor_size = MAX_CURSOR_SIZE_ALPHA;
326                 flags |= HARDWARE_CURSOR_ARGB;
327         } else {
328                 cursor_size = MAX_CURSOR_SIZE;
329         }
330         return xf86_cursors_init(pScreen, cursor_size, cursor_size, flags);
331 }
332
333 void nv_crtc_show_cursor(xf86CrtcPtr crtc)
334 {
335         struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
336
337         nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, true);
338 }
339
340 void nv_crtc_hide_cursor(xf86CrtcPtr crtc)
341 {
342         struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
343
344         nv_show_cursor(NVPTR(crtc->scrn), nv_crtc->head, false);
345 }
346
347 void nv_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
348 {
349         struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
350         ScrnInfoPtr pScrn = crtc->scrn;
351         NVPtr pNv = NVPTR(pScrn);
352
353         NVWriteRAMDAC(pNv, nv_crtc->head, NV_RAMDAC_CURSOR_POS, ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | (y << CURSOR_Y_SHIFT));
354 }
355
356 void nv_crtc_set_cursor_colors(xf86CrtcPtr crtc, int bg, int fg)
357 {
358         ScrnInfoPtr pScrn = crtc->scrn;
359         NVPtr pNv = NVPTR(pScrn);
360         CARD32 fore, back;
361
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);
368         }
369 #endif
370
371         /* Eventually this must be replaced as well */
372         if ((pNv->curFg != fore) || (pNv->curBg != back)) {
373                 pNv->curFg = fore;
374                 pNv->curBg = back;
375                 TransformCursor(pNv);
376         }
377 }
378
379
380 void nv_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *image)
381 {
382         ScrnInfoPtr pScrn = crtc->scrn;
383         struct nouveau_crtc *nv_crtc = to_nouveau_crtc(crtc);
384         NVPtr pNv = NVPTR(pScrn);
385
386         /* save copy of image for color changes */
387         memcpy(pNv->curImage, image, 256);
388
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;
393                 else
394                         pNv->CURSOR = (CARD32 *) pNv->Cursor->map;
395         }
396
397         /* Eventually this has to be replaced as well */
398         TransformCursor(pNv);
399 }
400
401 void nv_crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image)
402 {
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;
408
409         if (nv_crtc->head == 1) {
410                 dst = (uint32_t *) pNv->Cursor2->map;
411         } else {
412                 dst = (uint32_t *) pNv->Cursor->map;
413         }
414
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) */
418         int x, y;
419         uint32_t alpha, value;
420
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++);
427                                 #else
428                                         *dst++ = *src++;
429                                 #endif
430                         }
431                 }
432         } else {
433                 for (x = 0; x < MAX_CURSOR_SIZE_ALPHA; x++) {
434                         for (y = 0; y < MAX_CURSOR_SIZE_ALPHA; y++) {
435                                 alpha = *src >> 24;
436                                 if (alpha == 0x0 || alpha == 0xff) {
437                                         value = *src;
438                                 } else {
439                                         value =         ((((*src & 0xff) * 0xff) / alpha)               & 0x000000ff)   |
440                                                         ((((*src & 0xff00) * 0xff) / alpha)     & 0x0000ff00)   |
441                                                         ((((*src & 0xff0000) * 0xff) / alpha)   & 0x00ff0000)   |
442                                                         ((alpha << 24)                          & 0xff000000);
443                                 }
444                                 src++;
445                                 *dst++ = value;
446                         }
447                 }
448         }
449 }