randr12: bring over cursor code
[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 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/nv_cursor.c,v 1.13 2004/03/13 22:07:05 mvojkovi Exp $ */
41
42 #include "nv_include.h"
43
44 #include "cursorstr.h"
45
46 /****************************************************************************\
47 *                                                                            *
48 *                          HW Cursor Entrypoints                             *
49 *                                                                            *
50 \****************************************************************************/
51
52 #define NV_CURSOR_X 64
53 #define NV_CURSOR_Y 64
54
55 #define CURSOR_X_SHIFT 0
56 #define CURSOR_Y_SHIFT 16
57 #define CURSOR_POS_MASK 0xffff
58
59 #define TRANSPARENT_PIXEL   0
60
61 #define ConvertToRGB555(c)  (((c & 0xf80000) >> 9 ) | /* Blue  */           \
62                             ((c & 0xf800) >> 6 )    | /* Green */           \
63                             ((c & 0xf8) >> 3 )      | /* Red   */           \
64                             0x8000)                   /* Set upper bit, else we get complete transparency. */
65
66 #define ConvertToRGB888(c) (c | 0xff000000)
67
68 #define BYTE_SWAP_32(c)  ((c & 0xff000000) >> 24) |  \
69                          ((c & 0xff0000) >> 8) |     \
70                          ((c & 0xff00) << 8) |       \
71                          ((c & 0xff) << 24)
72
73 /* Limit non-alpha cursors to 32x32 (x2 bytes) */
74 #define MAX_CURSOR_SIZE 32
75
76 /* Limit alpha cursors to 32x32 (x4 bytes) */
77 #define MAX_CURSOR_SIZE_ALPHA (MAX_CURSOR_SIZE * 2)
78
79 static void 
80 ConvertCursor1555(NVPtr pNv, CARD32 *src, CARD16 *dst)
81 {
82     CARD32 b, m;
83     int i, j;
84     
85     for ( i = 0; i < MAX_CURSOR_SIZE; i++ ) {
86         b = *src++;
87         m = *src++;
88         for ( j = 0; j < MAX_CURSOR_SIZE; 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
142 static void
143 TransformCursor (NVPtr pNv)
144 {
145     CARD32 *tmp;
146     int i, dwords;
147
148     /* convert to color cursor */
149     if(pNv->alphaCursor) {
150        dwords = MAX_CURSOR_SIZE_ALPHA * MAX_CURSOR_SIZE_ALPHA;
151        if(!(tmp = ALLOCATE_LOCAL(dwords * 4))) return;
152        ConvertCursor8888(pNv, pNv->curImage, tmp);
153     } else {
154        dwords = (MAX_CURSOR_SIZE * MAX_CURSOR_SIZE) >> 1;
155        if(!(tmp = ALLOCATE_LOCAL(dwords * 4))) return;
156        ConvertCursor1555(pNv, pNv->curImage, (CARD16*)tmp);
157     }
158
159     for(i = 0; i < dwords; i++)
160         pNv->CURSOR[i] = tmp[i];
161
162     DEALLOCATE_LOCAL(tmp);
163 }
164
165 static void
166 NVLoadCursorImage( ScrnInfoPtr pScrn, unsigned char *src )
167 {
168     NVPtr pNv = NVPTR(pScrn);
169
170     /* save copy of image for color changes */
171     memcpy(pNv->curImage, src, (pNv->alphaCursor) ? 1024 : 256);
172
173     TransformCursor(pNv);
174 }
175
176 static void
177 NVSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
178 {
179     NVPtr pNv = NVPTR(pScrn);
180
181     if (pNv->randr12_enable) {
182         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
183         xf86CrtcPtr crtc;
184         NVCrtcPrivatePtr nv_crtc;
185         DisplayModePtr mode;
186         int thisx;
187         int thisy;
188         int o;
189         Bool inrange;
190         CARD32 temp;
191         
192         for (o = 0; o < xf86_config->num_output; o++)
193         {
194             xf86OutputPtr output = xf86_config->output[o];
195             
196             if (!output->crtc)
197                 continue;
198             
199             if (!output->crtc->enabled)
200                 continue;
201             
202             crtc = output->crtc;
203             mode = &crtc->mode;
204             thisx = x - crtc->x;
205             thisy = y - crtc->y;
206             
207             inrange = TRUE;
208             if (thisx >= mode->HDisplay ||
209                 thisy >= mode->VDisplay ||
210                 thisx <= -NV_CURSOR_X || thisy <= -NV_CURSOR_Y) 
211             {
212                 inrange = FALSE;
213                 thisx = 0;
214                 thisy = 0;
215             }
216             
217             temp = 0;
218             temp |= ((thisx & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
219             temp |= ((thisy & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
220             
221             nv_crtc = output->crtc->driver_private;
222             
223             nvWriteRAMDAC(pNv, nv_crtc->crtc, NV_RAMDAC_CURSOR_POS, temp);
224         }
225     } else
226       nvWriteCurRAMDAC(pNv, NV_RAMDAC_CURSOR_POS, (x & 0xFFFF) | (y << 16));
227 }
228
229 static void
230 NVSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
231 {
232     NVPtr pNv = NVPTR(pScrn);
233     CARD32 fore, back;
234
235     if(pNv->alphaCursor) {
236         fore = ConvertToRGB888(fg);
237         back = ConvertToRGB888(bg);
238 #if X_BYTE_ORDER == X_BIG_ENDIAN
239         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
240            fore = BYTE_SWAP_32(fore);
241            back = BYTE_SWAP_32(back);
242         }
243 #endif
244     } else {
245         fore = ConvertToRGB555(fg);
246         back = ConvertToRGB555(bg);
247 #if X_BYTE_ORDER == X_BIG_ENDIAN
248         if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {
249            fore = ((fore & 0xff) << 8) | (fore >> 8);
250            back = ((back & 0xff) << 8) | (back >> 8);
251         }
252 #endif
253    }
254
255     if ((pNv->curFg != fore) || (pNv->curBg != back)) {
256         pNv->curFg = fore;
257         pNv->curBg = back;
258             
259         TransformCursor(pNv);
260     }
261 }
262
263
264 static void 
265 NVShowCursor(ScrnInfoPtr pScrn)
266 {
267     NVPtr pNv = NVPTR(pScrn);
268     if (pNv->randr12_enable) {
269         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
270         int c;
271         
272         pNv->cursorOn = TRUE;
273         for (c= 0; c < xf86_config->num_crtc; c++)
274             NVCrtcSetCursor (xf86_config->crtc[c], TRUE);
275     } else {
276         /* Enable cursor - X-Windows mode */
277         NVShowHideCursor(pNv, 1);
278     }
279 }
280
281 static void
282 NVHideCursor(ScrnInfoPtr pScrn)
283 {
284     NVPtr pNv = NVPTR(pScrn);
285
286     if (pNv->randr12_enable) {
287         xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
288         int c;
289         
290         pNv->cursorOn = FALSE;
291         for (c = 0; c < xf86_config->num_crtc; c++)
292             NVCrtcSetCursor (xf86_config->crtc[c], TRUE);
293   
294     } else
295         /* Disable cursor */
296         NVShowHideCursor(pNv, 0);
297 }
298
299 static Bool 
300 NVUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
301 {
302     return TRUE;
303 }
304
305 #ifdef ARGB_CURSOR
306 static Bool 
307 NVUseHWCursorARGB(ScreenPtr pScreen, CursorPtr pCurs)
308 {
309     if((pCurs->bits->width <= MAX_CURSOR_SIZE_ALPHA) && (pCurs->bits->height <= MAX_CURSOR_SIZE_ALPHA))
310         return TRUE;
311
312     return FALSE;
313 }
314
315 static void
316 NVLoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
317 {
318     NVPtr pNv = NVPTR(pScrn);
319     CARD32 *image = pCurs->bits->argb;
320     CARD32 *dst = (CARD32*)pNv->CURSOR;
321     CARD32 alpha, tmp;
322     int x, y, w, h;
323
324     w = pCurs->bits->width;
325     h = pCurs->bits->height;
326
327     if((pNv->Chipset & 0x0ff0) == CHIPSET_NV11) {  /* premultiply */
328        for(y = 0; y < h; y++) {
329           for(x = 0; x < w; x++) {
330              alpha = *image >> 24;
331              if(alpha == 0xff)
332                 tmp = *image;
333              else {
334                 tmp = (alpha << 24) |
335                          (((*image & 0xff) * alpha) / 255) |
336                         ((((*image & 0xff00) * alpha) / 255) & 0xff00) |
337                        ((((*image & 0xff0000) * alpha) / 255) & 0xff0000); 
338              }
339              image++;
340 #if X_BYTE_ORDER == X_BIG_ENDIAN
341              *dst++ = BYTE_SWAP_32(tmp);
342 #else
343              *dst++ = tmp;
344 #endif
345          }
346          for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
347              *dst++ = 0;
348       }
349     } else {
350        for(y = 0; y < h; y++) {
351           for(x = 0; x < w; x++)
352               *dst++ = *image++;
353           for(; x < MAX_CURSOR_SIZE_ALPHA; x++)
354               *dst++ = 0;
355        }
356     }
357
358     if(y < MAX_CURSOR_SIZE_ALPHA)
359       memset(dst, 0, MAX_CURSOR_SIZE_ALPHA * (MAX_CURSOR_SIZE_ALPHA - y) * 4);
360 }
361 #endif
362
363 Bool 
364 NVCursorInit(ScreenPtr pScreen)
365 {
366     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
367     NVPtr pNv = NVPTR(pScrn);
368     xf86CursorInfoPtr infoPtr;
369
370     infoPtr = xf86CreateCursorInfoRec();
371     if(!infoPtr) return FALSE;
372     
373     pNv->CursorInfoRec = infoPtr;
374
375     if(pNv->alphaCursor)
376        infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE_ALPHA;
377     else
378        infoPtr->MaxWidth = infoPtr->MaxHeight = MAX_CURSOR_SIZE;
379
380     infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
381                      HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32; 
382     infoPtr->SetCursorColors = NVSetCursorColors;
383     infoPtr->SetCursorPosition = NVSetCursorPosition;
384     infoPtr->LoadCursorImage = NVLoadCursorImage;
385     infoPtr->HideCursor = NVHideCursor;
386     infoPtr->ShowCursor = NVShowCursor;
387     infoPtr->UseHWCursor = NVUseHWCursor;
388
389 #ifdef ARGB_CURSOR
390     if(pNv->alphaCursor) {
391        infoPtr->UseHWCursorARGB = NVUseHWCursorARGB;
392        infoPtr->LoadCursorARGB = NVLoadCursorARGB;
393     }
394 #endif
395
396     return(xf86InitCursor(pScreen, infoPtr));
397 }