2 * Copyright © 2007 Keith Packard
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission. The copyright holders make no representations
11 * about the suitability of this software for any purpose. It is provided "as
12 * is" without express or implied warranty.
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
38 #include "xf86Modes.h"
39 #include "xf86RandR12.h"
40 #include "X11/extensions/render.h"
42 #include "X11/extensions/dpms.h"
43 #include "X11/Xatom.h"
45 #include "picturestr.h"
47 #include "cursorstr.h"
50 * Given a screen coordinate, rotate back to a cursor source coordinate
53 xf86_crtc_rotate_coord (Rotation rotation
,
63 switch (rotation
& 0xf) {
68 x_dst
= height
- y_dst
- 1;
72 x_dst
= width
- x_dst
- 1;
73 y_dst
= height
- y_dst
- 1;
78 y_dst
= width
- t
- 1;
81 if (rotation
& RR_Reflect_X
)
82 x_dst
= width
- x_dst
- 1;
83 if (rotation
& RR_Reflect_Y
)
84 y_dst
= height
- y_dst
- 1;
90 * Given a cursor source coordinate, rotate to a screen coordinate
93 xf86_crtc_rotate_coord_back (Rotation rotation
,
103 if (rotation
& RR_Reflect_X
)
104 x_dst
= width
- x_dst
- 1;
105 if (rotation
& RR_Reflect_Y
)
106 y_dst
= height
- y_dst
- 1;
108 switch (rotation
& 0xf) {
114 y_dst
= width
- t
- 1;
117 x_dst
= width
- x_dst
- 1;
118 y_dst
= height
- y_dst
- 1;
122 x_dst
= height
- y_dst
- 1;
131 * Convert an x coordinate to a position within the cursor bitmap
134 cursor_bitpos (int flags
, int x
, Bool mask
)
136 if (flags
& HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK
)
138 if (flags
& HARDWARE_CURSOR_NIBBLE_SWAPPED
)
139 x
= (x
& ~3) | (3 - (x
& 3));
140 if (flags
& HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
)
141 x
= (x
& ~7) | (7 - (x
& 7));
142 if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1
)
144 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8
)
145 x
= ((x
& ~7) << 1) | (mask
<< 3) | (x
& 7);
146 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16
)
147 x
= ((x
& ~15) << 1) | (mask
<< 4) | (x
& 15);
148 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32
)
149 x
= ((x
& ~31) << 1) | (mask
<< 5) | (x
& 31);
150 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
)
151 x
= ((x
& ~63) << 1) | (mask
<< 6) | (x
& 63);
156 * Fetch one bit from a cursor bitmap
159 get_bit (CARD8
*image
, int stride
, int flags
, int x
, int y
, Bool mask
)
161 x
= cursor_bitpos (flags
, x
, mask
);
163 return (image
[(x
>> 3)] >> (x
& 7)) & 1;
167 * Set one bit in a cursor bitmap
170 set_bit (CARD8
*image
, int stride
, int flags
, int x
, int y
, Bool mask
)
172 x
= cursor_bitpos (flags
, x
, mask
);
174 image
[(x
>> 3)] |= 1 << (x
& 7);
178 * Load a two color cursor into a driver that supports only ARGB cursors
181 xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc
, unsigned char *src
)
183 ScrnInfoPtr scrn
= crtc
->scrn
;
184 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
185 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
186 CARD32
*cursor_image
= (CARD32
*) xf86_config
->cursor_image
;
189 int stride
= cursor_info
->MaxWidth
>> 2;
190 int flags
= cursor_info
->Flags
;
194 crtc
->cursor_argb
= FALSE
;
197 for (y
= 0; y
< cursor_info
->MaxHeight
; y
++)
198 for (x
= 0; x
< cursor_info
->MaxWidth
; x
++)
200 xf86_crtc_rotate_coord (crtc
->rotation
,
201 cursor_info
->MaxWidth
,
202 cursor_info
->MaxHeight
,
204 if (get_bit (src
, stride
, flags
, xin
, yin
, TRUE
) ==
205 ((flags
& HARDWARE_CURSOR_INVERT_MASK
) == 0))
207 if (get_bit (src
, stride
, flags
, xin
, yin
, FALSE
))
208 bits
= xf86_config
->cursor_fg
;
210 bits
= xf86_config
->cursor_bg
;
214 cursor_image
[y
* cursor_info
->MaxWidth
+ x
] = bits
;
216 crtc
->funcs
->load_cursor_argb (crtc
, cursor_image
);
220 * Set the colors for a two-color cursor (ignore for ARGB cursors)
223 xf86_set_cursor_colors (ScrnInfoPtr scrn
, int bg
, int fg
)
225 ScreenPtr screen
= scrn
->pScreen
;
226 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
227 CursorPtr cursor
= xf86_config
->cursor
;
229 CARD8
*bits
= cursor
? cursor
->devPriv
[screen
->myNum
] : NULL
;
231 /* Save ARGB versions of these colors */
232 xf86_config
->cursor_fg
= (CARD32
) fg
| 0xff000000;
233 xf86_config
->cursor_bg
= (CARD32
) bg
| 0xff000000;
235 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
237 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
239 if (crtc
->enabled
&& !crtc
->cursor_argb
)
241 if (crtc
->funcs
->load_cursor_image
)
242 crtc
->funcs
->set_cursor_colors (crtc
, bg
, fg
);
244 xf86_crtc_convert_cursor_to_argb (crtc
, bits
);
250 xf86_crtc_hide_cursor (xf86CrtcPtr crtc
)
252 if (crtc
->cursor_shown
)
254 crtc
->funcs
->hide_cursor (crtc
);
255 crtc
->cursor_shown
= FALSE
;
260 xf86_hide_cursors (ScrnInfoPtr scrn
)
262 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
265 xf86_config
->cursor_on
= FALSE
;
266 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
268 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
271 xf86_crtc_hide_cursor (crtc
);
276 xf86_crtc_show_cursor (xf86CrtcPtr crtc
)
278 if (!crtc
->cursor_shown
&& crtc
->cursor_in_range
)
280 crtc
->funcs
->show_cursor (crtc
);
281 crtc
->cursor_shown
= TRUE
;
286 xf86_show_cursors (ScrnInfoPtr scrn
)
288 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
291 xf86_config
->cursor_on
= TRUE
;
292 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
294 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
297 xf86_crtc_show_cursor (crtc
);
302 xf86_crtc_set_cursor_position (xf86CrtcPtr crtc
, int x
, int y
)
304 ScrnInfoPtr scrn
= crtc
->scrn
;
305 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
306 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
307 DisplayModePtr mode
= &crtc
->mode
;
312 * Transform position of cursor on screen
314 if (crtc
->transform_in_use
)
317 v
.vector
[0] = IntToxFixed (x
); v
.vector
[1] = IntToxFixed (y
); v
.vector
[2] = IntToxFixed(1);
318 PictureTransformPoint (&crtc
->framebuffer_to_crtc
, &v
);
319 x
= xFixedToInt (v
.vector
[0]); y
= xFixedToInt (v
.vector
[1]);
327 * Transform position of cursor upper left corner
329 xf86_crtc_rotate_coord_back (crtc
->rotation
,
330 cursor_info
->MaxWidth
,
331 cursor_info
->MaxHeight
,
337 * Disable the cursor when it is outside the viewport
340 if (x
>= mode
->HDisplay
|| y
>= mode
->VDisplay
||
341 x
<= -cursor_info
->MaxWidth
|| y
<= -cursor_info
->MaxHeight
)
348 crtc
->cursor_in_range
= in_range
;
352 crtc
->funcs
->set_cursor_position (crtc
, x
, y
);
353 xf86_crtc_show_cursor (crtc
);
356 xf86_crtc_hide_cursor (crtc
);
360 xf86_set_cursor_position (ScrnInfoPtr scrn
, int x
, int y
)
362 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
365 /* undo what xf86HWCurs did to the coordinates */
368 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
370 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
373 xf86_crtc_set_cursor_position (crtc
, x
, y
);
378 * Load a two-color cursor into a crtc, performing rotation as needed
381 xf86_crtc_load_cursor_image (xf86CrtcPtr crtc
, CARD8
*src
)
383 ScrnInfoPtr scrn
= crtc
->scrn
;
384 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
385 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
389 crtc
->cursor_argb
= FALSE
;
392 if (crtc
->rotation
== RR_Rotate_0
)
398 int stride
= cursor_info
->MaxWidth
>> 2;
399 int flags
= cursor_info
->Flags
;
401 cursor_image
= xf86_config
->cursor_image
;
402 memset(cursor_image
, 0, cursor_info
->MaxWidth
* stride
);
404 for (y
= 0; y
< cursor_info
->MaxHeight
; y
++)
405 for (x
= 0; x
< cursor_info
->MaxWidth
; x
++)
407 xf86_crtc_rotate_coord (crtc
->rotation
,
408 cursor_info
->MaxWidth
,
409 cursor_info
->MaxHeight
,
411 if (get_bit(src
, stride
, flags
, xin
, yin
, FALSE
))
412 set_bit(cursor_image
, stride
, flags
, x
, y
, FALSE
);
413 if (get_bit(src
, stride
, flags
, xin
, yin
, TRUE
))
414 set_bit(cursor_image
, stride
, flags
, x
, y
, TRUE
);
417 crtc
->funcs
->load_cursor_image (crtc
, cursor_image
);
421 * Load a cursor image into all active CRTCs
424 xf86_load_cursor_image (ScrnInfoPtr scrn
, unsigned char *src
)
426 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
429 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
431 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
435 if (crtc
->funcs
->load_cursor_image
)
436 xf86_crtc_load_cursor_image (crtc
, src
);
437 else if (crtc
->funcs
->load_cursor_argb
)
438 xf86_crtc_convert_cursor_to_argb (crtc
, src
);
444 xf86_use_hw_cursor (ScreenPtr screen
, CursorPtr cursor
)
446 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
447 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
448 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
450 if (xf86_config
->cursor
)
451 FreeCursor (xf86_config
->cursor
, None
);
452 xf86_config
->cursor
= cursor
;
455 if (cursor
->bits
->width
> cursor_info
->MaxWidth
||
456 cursor
->bits
->height
> cursor_info
->MaxHeight
)
463 xf86_use_hw_cursor_argb (ScreenPtr screen
, CursorPtr cursor
)
465 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
466 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
467 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
469 if (xf86_config
->cursor
)
470 FreeCursor (xf86_config
->cursor
, None
);
471 xf86_config
->cursor
= cursor
;
474 /* Make sure ARGB support is available */
475 if ((cursor_info
->Flags
& HARDWARE_CURSOR_ARGB
) == 0)
478 if (cursor
->bits
->width
> cursor_info
->MaxWidth
||
479 cursor
->bits
->height
> cursor_info
->MaxHeight
)
486 xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc
, CursorPtr cursor
)
488 ScrnInfoPtr scrn
= crtc
->scrn
;
489 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
490 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
491 CARD32
*cursor_image
= (CARD32
*) xf86_config
->cursor_image
;
492 CARD32
*cursor_source
= (CARD32
*) cursor
->bits
->argb
;
496 int source_width
= cursor
->bits
->width
;
497 int source_height
= cursor
->bits
->height
;
498 int image_width
= cursor_info
->MaxWidth
;
499 int image_height
= cursor_info
->MaxHeight
;
501 for (y
= 0; y
< image_height
; y
++)
502 for (x
= 0; x
< image_width
; x
++)
504 xf86_crtc_rotate_coord (crtc
->rotation
, image_width
, image_height
,
506 if (xin
< source_width
&& yin
< source_height
)
507 bits
= cursor_source
[yin
* source_width
+ xin
];
510 cursor_image
[y
* image_width
+ x
] = bits
;
513 crtc
->funcs
->load_cursor_argb (crtc
, cursor_image
);
517 xf86_load_cursor_argb (ScrnInfoPtr scrn
, CursorPtr cursor
)
519 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
522 for (c
= 0; c
< xf86_config
->num_crtc
; c
++)
524 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
527 xf86_crtc_load_cursor_argb (crtc
, cursor
);
532 xf86_cursors_init (ScreenPtr screen
, int max_width
, int max_height
, int flags
)
534 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
535 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
536 xf86CursorInfoPtr cursor_info
;
538 cursor_info
= xf86CreateCursorInfoRec();
542 xf86_config
->cursor_image
= xalloc (max_width
* max_height
* 4);
544 if (!xf86_config
->cursor_image
)
546 xf86DestroyCursorInfoRec (cursor_info
);
550 xf86_config
->cursor_info
= cursor_info
;
552 cursor_info
->MaxWidth
= max_width
;
553 cursor_info
->MaxHeight
= max_height
;
554 cursor_info
->Flags
= flags
;
556 cursor_info
->SetCursorColors
= xf86_set_cursor_colors
;
557 cursor_info
->SetCursorPosition
= xf86_set_cursor_position
;
558 cursor_info
->LoadCursorImage
= xf86_load_cursor_image
;
559 cursor_info
->HideCursor
= xf86_hide_cursors
;
560 cursor_info
->ShowCursor
= xf86_show_cursors
;
561 cursor_info
->UseHWCursor
= xf86_use_hw_cursor
;
563 if (flags
& HARDWARE_CURSOR_ARGB
)
565 cursor_info
->UseHWCursorARGB
= xf86_use_hw_cursor_argb
;
566 cursor_info
->LoadCursorARGB
= xf86_load_cursor_argb
;
570 xf86_config
->cursor
= NULL
;
571 xf86_hide_cursors (scrn
);
573 return xf86InitCursor (screen
, cursor_info
);
577 * Called when anything on the screen is reconfigured.
579 * Reloads cursor images as needed, then adjusts cursor positions
583 xf86_reload_cursors (ScreenPtr screen
)
586 xf86CrtcConfigPtr xf86_config
;
587 xf86CursorInfoPtr cursor_info
;
591 /* initial mode setting will not have set a screen yet */
594 scrn
= xf86Screens
[screen
->myNum
];
595 xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
597 /* make sure the cursor code has been initialized */
598 cursor_info
= xf86_config
->cursor_info
;
602 cursor
= xf86_config
->cursor
;
603 GetSpritePosition (&x
, &y
);
604 if (!(cursor_info
->Flags
& HARDWARE_CURSOR_UPDATE_UNHIDDEN
))
605 (*cursor_info
->HideCursor
)(scrn
);
610 if (cursor
->bits
->argb
&& cursor_info
->LoadCursorARGB
)
611 (*cursor_info
->LoadCursorARGB
) (scrn
, cursor
);
614 (*cursor_info
->LoadCursorImage
)(cursor_info
->pScrn
,
615 cursor
->devPriv
[screen
->myNum
]);
617 (*cursor_info
->SetCursorPosition
)(cursor_info
->pScrn
, x
, y
);
618 (*cursor_info
->ShowCursor
)(cursor_info
->pScrn
);
623 * Clean up CRTC-based cursor code
626 xf86_cursors_fini (ScreenPtr screen
)
628 ScrnInfoPtr scrn
= xf86Screens
[screen
->myNum
];
629 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
631 if (xf86_config
->cursor_info
)
633 xf86DestroyCursorInfoRec (xf86_config
->cursor_info
);
634 xf86_config
->cursor_info
= NULL
;
636 if (xf86_config
->cursor_image
)
638 xfree (xf86_config
->cursor_image
);
639 xf86_config
->cursor_image
= NULL
;
641 if (xf86_config
->cursor
)
643 FreeCursor (xf86_config
->cursor
, None
);
644 xf86_config
->cursor
= NULL
;