2 * Copyright © 2007 Keith Packard
3 * Copyright © 2010-2011 Aaron Plattner
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting documentation, and
9 * that the name of the copyright holders not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no representations
12 * about the suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24 #ifdef HAVE_XORG_CONFIG_H
25 #include <xorg-config.h>
36 #include <X11/Xarch.h>
40 #include "xf86Modes.h"
41 #include "xf86RandR12.h"
42 #include "xf86CursorPriv.h"
43 #include "X11/extensions/render.h"
44 #include "X11/extensions/dpmsconst.h"
45 #include "X11/Xatom.h"
46 #include "picturestr.h"
47 #include "cursorstr.h"
51 * Returns the rotation being performed by the server. If the driver indicates
52 * that it's handling the screen transform, then this returns RR_Rotate_0.
55 xf86_crtc_cursor_rotation(xf86CrtcPtr crtc
)
57 if (crtc
->driverIsPerformingTransform
)
59 return crtc
->rotation
;
63 * Given a screen coordinate, rotate back to a cursor source coordinate
66 xf86_crtc_rotate_coord(Rotation rotation
,
68 int height
, int x_dst
, int y_dst
, int *x_src
, int *y_src
)
72 switch (rotation
& 0xf) {
77 x_dst
= height
- y_dst
- 1;
81 x_dst
= width
- x_dst
- 1;
82 y_dst
= height
- y_dst
- 1;
87 y_dst
= width
- t
- 1;
90 if (rotation
& RR_Reflect_X
)
91 x_dst
= width
- x_dst
- 1;
92 if (rotation
& RR_Reflect_Y
)
93 y_dst
= height
- y_dst
- 1;
99 * Given a cursor source coordinate, rotate to a screen coordinate
102 xf86_crtc_rotate_coord_back(Rotation rotation
,
105 int x_dst
, int y_dst
, int *x_src
, int *y_src
)
109 if (rotation
& RR_Reflect_X
)
110 x_dst
= width
- x_dst
- 1;
111 if (rotation
& RR_Reflect_Y
)
112 y_dst
= height
- y_dst
- 1;
114 switch (rotation
& 0xf) {
120 y_dst
= width
- t
- 1;
123 x_dst
= width
- x_dst
- 1;
124 y_dst
= height
- y_dst
- 1;
128 x_dst
= height
- y_dst
- 1;
142 * Convert an x coordinate to a position within the cursor bitmap
144 static struct cursor_bit
145 cursor_bitpos(CARD8
*image
, xf86CursorInfoPtr cursor_info
, int x
, int y
,
148 const int flags
= cursor_info
->Flags
;
149 const Bool interleaved
=
150 ! !(flags
& (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1
|
151 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8
|
152 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16
|
153 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32
|
154 HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
));
155 const int width
= cursor_info
->MaxWidth
;
156 const int height
= cursor_info
->MaxHeight
;
157 const int stride
= interleaved
? width
/ 4 : width
/ 8;
159 struct cursor_bit ret
;
163 if (flags
& HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK
)
165 if (flags
& HARDWARE_CURSOR_NIBBLE_SWAPPED
)
166 x
= (x
& ~3) | (3 - (x
& 3));
167 if (((flags
& HARDWARE_CURSOR_BIT_ORDER_MSBFIRST
) == 0) ==
168 (X_BYTE_ORDER
== X_BIG_ENDIAN
))
169 x
= (x
& ~7) | (7 - (x
& 7));
170 if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1
)
172 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8
)
173 x
= ((x
& ~7) << 1) | (mask
<< 3) | (x
& 7);
174 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16
)
175 x
= ((x
& ~15) << 1) | (mask
<< 4) | (x
& 15);
176 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32
)
177 x
= ((x
& ~31) << 1) | (mask
<< 5) | (x
& 31);
178 else if (flags
& HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64
)
179 x
= ((x
& ~63) << 1) | (mask
<< 6) | (x
& 63);
181 image
+= stride
* height
;
183 ret
.byte
= image
+ (x
/ 8);
190 * Fetch one bit from a cursor bitmap
193 get_bit(CARD8
*image
, xf86CursorInfoPtr cursor_info
, int x
, int y
, Bool mask
)
195 struct cursor_bit bit
= cursor_bitpos(image
, cursor_info
, x
, y
, mask
);
197 return (*bit
.byte
>> bit
.bitpos
) & 1;
201 * Set one bit in a cursor bitmap
204 set_bit(CARD8
*image
, xf86CursorInfoPtr cursor_info
, int x
, int y
, Bool mask
)
206 struct cursor_bit bit
= cursor_bitpos(image
, cursor_info
, x
, y
, mask
);
208 *bit
.byte
|= 1 << bit
.bitpos
;
212 * Load a two color cursor into a driver that supports only ARGB cursors
215 xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc
, unsigned char *src
)
217 ScrnInfoPtr scrn
= crtc
->scrn
;
218 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
219 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
220 CARD32
*cursor_image
= (CARD32
*) xf86_config
->cursor_image
;
223 int flags
= cursor_info
->Flags
;
225 const Rotation rotation
= xf86_crtc_cursor_rotation(crtc
);
228 crtc
->cursor_argb
= FALSE
;
231 for (y
= 0; y
< cursor_info
->MaxHeight
; y
++)
232 for (x
= 0; x
< cursor_info
->MaxWidth
; x
++) {
233 xf86_crtc_rotate_coord(rotation
,
234 cursor_info
->MaxWidth
,
235 cursor_info
->MaxHeight
, x
, y
, &xin
, &yin
);
236 if (get_bit(src
, cursor_info
, xin
, yin
, TRUE
) ==
237 ((flags
& HARDWARE_CURSOR_INVERT_MASK
) == 0)) {
238 if (get_bit(src
, cursor_info
, xin
, yin
, FALSE
))
239 bits
= xf86_config
->cursor_fg
;
241 bits
= xf86_config
->cursor_bg
;
245 cursor_image
[y
* cursor_info
->MaxWidth
+ x
] = bits
;
247 crtc
->funcs
->load_cursor_argb(crtc
, cursor_image
);
251 * Set the colors for a two-color cursor (ignore for ARGB cursors)
254 xf86_set_cursor_colors(ScrnInfoPtr scrn
, int bg
, int fg
)
256 ScreenPtr screen
= scrn
->pScreen
;
257 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
258 CursorPtr cursor
= xf86_config
->cursor
;
260 CARD8
*bits
= cursor
?
261 dixLookupScreenPrivate(&cursor
->devPrivates
, CursorScreenKey
, screen
)
264 /* Save ARGB versions of these colors */
265 xf86_config
->cursor_fg
= (CARD32
) fg
| 0xff000000;
266 xf86_config
->cursor_bg
= (CARD32
) bg
| 0xff000000;
268 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
269 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
271 if (crtc
->enabled
&& !crtc
->cursor_argb
) {
272 if (crtc
->funcs
->load_cursor_image
)
273 crtc
->funcs
->set_cursor_colors(crtc
, bg
, fg
);
275 xf86_crtc_convert_cursor_to_argb(crtc
, bits
);
281 xf86_crtc_hide_cursor(xf86CrtcPtr crtc
)
283 if (crtc
->cursor_shown
) {
284 crtc
->funcs
->hide_cursor(crtc
);
285 crtc
->cursor_shown
= FALSE
;
290 xf86_hide_cursors(ScrnInfoPtr scrn
)
292 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
295 xf86_config
->cursor_on
= FALSE
;
296 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
297 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
300 xf86_crtc_hide_cursor(crtc
);
305 xf86_crtc_show_cursor(xf86CrtcPtr crtc
)
307 if (!crtc
->cursor_shown
&& crtc
->cursor_in_range
) {
308 crtc
->funcs
->show_cursor(crtc
);
309 crtc
->cursor_shown
= TRUE
;
314 xf86_show_cursors(ScrnInfoPtr scrn
)
316 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
319 xf86_config
->cursor_on
= TRUE
;
320 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
321 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
324 xf86_crtc_show_cursor(crtc
);
329 xf86CrtcTransformCursorPos(xf86CrtcPtr crtc
, int *x
, int *y
)
331 ScrnInfoPtr scrn
= crtc
->scrn
;
332 ScreenPtr screen
= scrn
->pScreen
;
333 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
334 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
335 xf86CursorScreenPtr ScreenPriv
=
336 (xf86CursorScreenPtr
) dixLookupPrivate(&screen
->devPrivates
,
337 xf86CursorScreenKey
);
338 struct pict_f_vector v
;
341 v
.v
[0] = (*x
+ ScreenPriv
->HotX
) + 0.5;
342 v
.v
[1] = (*y
+ ScreenPriv
->HotY
) + 0.5;
344 pixman_f_transform_point(&crtc
->f_framebuffer_to_crtc
, &v
);
345 /* cursor will have 0.5 added to it already so floor is sufficent */
349 * Transform position of cursor upper left corner
351 xf86_crtc_rotate_coord_back(crtc
->rotation
, cursor_info
->MaxWidth
,
352 cursor_info
->MaxHeight
, ScreenPriv
->HotX
,
353 ScreenPriv
->HotY
, &dx
, &dy
);
359 xf86_crtc_set_cursor_position(xf86CrtcPtr crtc
, int x
, int y
)
361 ScrnInfoPtr scrn
= crtc
->scrn
;
362 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
363 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
364 DisplayModePtr mode
= &crtc
->mode
;
368 * Transform position of cursor on screen
370 if (crtc
->transform_in_use
&& !crtc
->driverIsPerformingTransform
)
371 xf86CrtcTransformCursorPos(crtc
, &x
, &y
);
378 * Disable the cursor when it is outside the viewport
381 if (x
>= mode
->HDisplay
|| y
>= mode
->VDisplay
||
382 x
<= -cursor_info
->MaxWidth
|| y
<= -cursor_info
->MaxHeight
) {
388 crtc
->cursor_in_range
= in_range
;
391 crtc
->funcs
->set_cursor_position(crtc
, x
, y
);
392 xf86_crtc_show_cursor(crtc
);
395 xf86_crtc_hide_cursor(crtc
);
399 xf86_set_cursor_position(ScrnInfoPtr scrn
, int x
, int y
)
401 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
404 /* undo what xf86HWCurs did to the coordinates */
407 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
408 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
411 xf86_crtc_set_cursor_position(crtc
, x
, y
);
416 * Load a two-color cursor into a crtc, performing rotation as needed
419 xf86_crtc_load_cursor_image(xf86CrtcPtr crtc
, CARD8
*src
)
421 ScrnInfoPtr scrn
= crtc
->scrn
;
422 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
423 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
425 const Rotation rotation
= xf86_crtc_cursor_rotation(crtc
);
428 crtc
->cursor_argb
= FALSE
;
431 if (rotation
== RR_Rotate_0
)
436 int stride
= cursor_info
->MaxWidth
>> 2;
438 cursor_image
= xf86_config
->cursor_image
;
439 memset(cursor_image
, 0, cursor_info
->MaxHeight
* stride
);
441 for (y
= 0; y
< cursor_info
->MaxHeight
; y
++)
442 for (x
= 0; x
< cursor_info
->MaxWidth
; x
++) {
443 xf86_crtc_rotate_coord(rotation
,
444 cursor_info
->MaxWidth
,
445 cursor_info
->MaxHeight
,
447 if (get_bit(src
, cursor_info
, xin
, yin
, FALSE
))
448 set_bit(cursor_image
, cursor_info
, x
, y
, FALSE
);
449 if (get_bit(src
, cursor_info
, xin
, yin
, TRUE
))
450 set_bit(cursor_image
, cursor_info
, x
, y
, TRUE
);
453 crtc
->funcs
->load_cursor_image(crtc
, cursor_image
);
457 * Load a cursor image into all active CRTCs
460 xf86_load_cursor_image(ScrnInfoPtr scrn
, unsigned char *src
)
462 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
465 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
466 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
469 if (crtc
->funcs
->load_cursor_image
)
470 xf86_crtc_load_cursor_image(crtc
, src
);
471 else if (crtc
->funcs
->load_cursor_argb
)
472 xf86_crtc_convert_cursor_to_argb(crtc
, src
);
478 xf86_use_hw_cursor(ScreenPtr screen
, CursorPtr cursor
)
480 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
481 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
482 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
484 cursor
= RefCursor(cursor
);
485 if (xf86_config
->cursor
)
486 FreeCursor(xf86_config
->cursor
, None
);
487 xf86_config
->cursor
= cursor
;
489 if (cursor
->bits
->width
> cursor_info
->MaxWidth
||
490 cursor
->bits
->height
> cursor_info
->MaxHeight
)
497 xf86_use_hw_cursor_argb(ScreenPtr screen
, CursorPtr cursor
)
499 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
500 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
501 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
503 cursor
= RefCursor(cursor
);
504 if (xf86_config
->cursor
)
505 FreeCursor(xf86_config
->cursor
, None
);
506 xf86_config
->cursor
= cursor
;
508 /* Make sure ARGB support is available */
509 if ((cursor_info
->Flags
& HARDWARE_CURSOR_ARGB
) == 0)
512 if (cursor
->bits
->width
> cursor_info
->MaxWidth
||
513 cursor
->bits
->height
> cursor_info
->MaxHeight
)
520 xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc
, CursorPtr cursor
)
522 ScrnInfoPtr scrn
= crtc
->scrn
;
523 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
524 xf86CursorInfoPtr cursor_info
= xf86_config
->cursor_info
;
525 CARD32
*cursor_image
= (CARD32
*) xf86_config
->cursor_image
;
526 CARD32
*cursor_source
= (CARD32
*) cursor
->bits
->argb
;
530 int source_width
= cursor
->bits
->width
;
531 int source_height
= cursor
->bits
->height
;
532 int image_width
= cursor_info
->MaxWidth
;
533 int image_height
= cursor_info
->MaxHeight
;
534 const Rotation rotation
= xf86_crtc_cursor_rotation(crtc
);
536 for (y
= 0; y
< image_height
; y
++)
537 for (x
= 0; x
< image_width
; x
++) {
538 xf86_crtc_rotate_coord(rotation
, image_width
, image_height
, x
, y
,
540 if (xin
< source_width
&& yin
< source_height
)
541 bits
= cursor_source
[yin
* source_width
+ xin
];
544 cursor_image
[y
* image_width
+ x
] = bits
;
547 crtc
->funcs
->load_cursor_argb(crtc
, cursor_image
);
551 xf86_load_cursor_argb(ScrnInfoPtr scrn
, CursorPtr cursor
)
553 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
556 for (c
= 0; c
< xf86_config
->num_crtc
; c
++) {
557 xf86CrtcPtr crtc
= xf86_config
->crtc
[c
];
560 xf86_crtc_load_cursor_argb(crtc
, cursor
);
565 xf86_cursors_init(ScreenPtr screen
, int max_width
, int max_height
, int flags
)
567 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
568 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
569 xf86CursorInfoPtr cursor_info
;
571 cursor_info
= xf86CreateCursorInfoRec();
575 xf86_config
->cursor_image
= malloc(max_width
* max_height
* 4);
577 if (!xf86_config
->cursor_image
) {
578 xf86DestroyCursorInfoRec(cursor_info
);
582 xf86_config
->cursor_info
= cursor_info
;
584 cursor_info
->MaxWidth
= max_width
;
585 cursor_info
->MaxHeight
= max_height
;
586 cursor_info
->Flags
= flags
;
588 cursor_info
->SetCursorColors
= xf86_set_cursor_colors
;
589 cursor_info
->SetCursorPosition
= xf86_set_cursor_position
;
590 cursor_info
->LoadCursorImage
= xf86_load_cursor_image
;
591 cursor_info
->HideCursor
= xf86_hide_cursors
;
592 cursor_info
->ShowCursor
= xf86_show_cursors
;
593 cursor_info
->UseHWCursor
= xf86_use_hw_cursor
;
595 if (flags
& HARDWARE_CURSOR_ARGB
) {
596 cursor_info
->UseHWCursorARGB
= xf86_use_hw_cursor_argb
;
597 cursor_info
->LoadCursorARGB
= xf86_load_cursor_argb
;
601 xf86_config
->cursor
= NULL
;
602 xf86_hide_cursors(scrn
);
604 return xf86InitCursor(screen
, cursor_info
);
608 * Called when anything on the screen is reconfigured.
610 * Reloads cursor images as needed, then adjusts cursor positions
614 xf86_reload_cursors(ScreenPtr screen
)
617 xf86CrtcConfigPtr xf86_config
;
618 xf86CursorInfoPtr cursor_info
;
621 xf86CursorScreenPtr cursor_screen_priv
;
623 /* initial mode setting will not have set a screen yet.
624 May be called before the devices are initialised.
626 if (!screen
|| !inputInfo
.pointer
)
628 cursor_screen_priv
= dixLookupPrivate(&screen
->devPrivates
,
629 xf86CursorScreenKey
);
630 /* return if HW cursor is inactive, to avoid displaying two cursors */
631 if (!cursor_screen_priv
|| !cursor_screen_priv
->isUp
)
634 scrn
= xf86ScreenToScrn(screen
);
635 xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
637 /* make sure the cursor code has been initialized */
638 cursor_info
= xf86_config
->cursor_info
;
642 cursor
= xf86_config
->cursor
;
643 GetSpritePosition(inputInfo
.pointer
, &x
, &y
);
644 if (!(cursor_info
->Flags
& HARDWARE_CURSOR_UPDATE_UNHIDDEN
))
645 (*cursor_info
->HideCursor
) (scrn
);
649 dixLookupScreenPrivate(&cursor
->devPrivates
, CursorScreenKey
,
652 if (cursor
->bits
->argb
&& cursor_info
->LoadCursorARGB
)
653 (*cursor_info
->LoadCursorARGB
) (scrn
, cursor
);
656 (*cursor_info
->LoadCursorImage
) (scrn
, src
);
658 x
+= scrn
->frameX0
+ cursor_screen_priv
->HotX
;
659 y
+= scrn
->frameY0
+ cursor_screen_priv
->HotY
;
660 (*cursor_info
->SetCursorPosition
) (scrn
, x
, y
);
665 * Clean up CRTC-based cursor code
668 xf86_cursors_fini(ScreenPtr screen
)
670 ScrnInfoPtr scrn
= xf86ScreenToScrn(screen
);
671 xf86CrtcConfigPtr xf86_config
= XF86_CRTC_CONFIG_PTR(scrn
);
673 if (xf86_config
->cursor_info
) {
674 xf86DestroyCursorInfoRec(xf86_config
->cursor_info
);
675 xf86_config
->cursor_info
= NULL
;
677 free(xf86_config
->cursor_image
);
678 xf86_config
->cursor_image
= NULL
;
679 if (xf86_config
->cursor
) {
680 FreeCursor(xf86_config
->cursor
, None
);
681 xf86_config
->cursor
= NULL
;