First import
[xorg_rtime.git] / xorg-server-1.4 / hw / xfree86 / modes / xf86Cursors.c
blobb5101642be164a6954afac61079fece1249ecfef
1 /*
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
20 * OF THIS SOFTWARE.
23 #ifdef HAVE_XORG_CONFIG_H
24 #include <xorg-config.h>
25 #else
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 #endif
31 #include <stddef.h>
32 #include <string.h>
33 #include <stdio.h>
35 #include "xf86.h"
36 #include "xf86DDC.h"
37 #include "xf86Crtc.h"
38 #include "xf86Modes.h"
39 #include "xf86RandR12.h"
40 #include "X11/extensions/render.h"
41 #define DPMS_SERVER
42 #include "X11/extensions/dpms.h"
43 #include "X11/Xatom.h"
44 #ifdef RENDER
45 #include "picturestr.h"
46 #endif
47 #include "cursorstr.h"
50 * Given a screen coordinate, rotate back to a cursor source coordinate
52 static void
53 xf86_crtc_rotate_coord (Rotation rotation,
54 int width,
55 int height,
56 int x_dst,
57 int y_dst,
58 int *x_src,
59 int *y_src)
61 int t;
63 switch (rotation & 0xf) {
64 case RR_Rotate_0:
65 break;
66 case RR_Rotate_90:
67 t = x_dst;
68 x_dst = height - y_dst - 1;
69 y_dst = t;
70 break;
71 case RR_Rotate_180:
72 x_dst = width - x_dst - 1;
73 y_dst = height - y_dst - 1;
74 break;
75 case RR_Rotate_270:
76 t = x_dst;
77 x_dst = y_dst;
78 y_dst = width - t - 1;
79 break;
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;
85 *x_src = x_dst;
86 *y_src = y_dst;
90 * Given a cursor source coordinate, rotate to a screen coordinate
92 static void
93 xf86_crtc_rotate_coord_back (Rotation rotation,
94 int width,
95 int height,
96 int x_dst,
97 int y_dst,
98 int *x_src,
99 int *y_src)
101 int t;
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) {
109 case RR_Rotate_0:
110 break;
111 case RR_Rotate_90:
112 t = x_dst;
113 x_dst = y_dst;
114 y_dst = width - t - 1;
115 break;
116 case RR_Rotate_180:
117 x_dst = width - x_dst - 1;
118 y_dst = height - y_dst - 1;
119 break;
120 case RR_Rotate_270:
121 t = x_dst;
122 x_dst = height - y_dst - 1;
123 y_dst = t;
124 break;
126 *x_src = x_dst;
127 *y_src = y_dst;
131 * Convert an x coordinate to a position within the cursor bitmap
133 static int
134 cursor_bitpos (int flags, int x, Bool mask)
136 if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
137 mask = !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)
143 x = (x << 1) + mask;
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);
152 return x;
156 * Fetch one bit from a cursor bitmap
158 static CARD8
159 get_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
161 x = cursor_bitpos (flags, x, mask);
162 image += y * stride;
163 return (image[(x >> 3)] >> (x & 7)) & 1;
167 * Set one bit in a cursor bitmap
169 static void
170 set_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
172 x = cursor_bitpos (flags, x, mask);
173 image += y * stride;
174 image[(x >> 3)] |= 1 << (x & 7);
178 * Load a two color cursor into a driver that supports only ARGB cursors
180 static void
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;
187 int x, y;
188 int xin, yin;
189 int stride = cursor_info->MaxWidth >> 2;
190 int flags = cursor_info->Flags;
191 CARD32 bits;
193 #ifdef ARGB_CURSOR
194 crtc->cursor_argb = FALSE;
195 #endif
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,
203 x, y, &xin, &yin);
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;
209 else
210 bits = xf86_config->cursor_bg;
212 else
213 bits = 0;
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)
222 static void
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;
228 int c;
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);
243 else if (bits)
244 xf86_crtc_convert_cursor_to_argb (crtc, bits);
249 static void
250 xf86_crtc_hide_cursor (xf86CrtcPtr crtc)
252 if (crtc->cursor_shown)
254 crtc->funcs->hide_cursor (crtc);
255 crtc->cursor_shown = FALSE;
259 _X_EXPORT void
260 xf86_hide_cursors (ScrnInfoPtr scrn)
262 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
263 int c;
265 xf86_config->cursor_on = FALSE;
266 for (c = 0; c < xf86_config->num_crtc; c++)
268 xf86CrtcPtr crtc = xf86_config->crtc[c];
270 if (crtc->enabled)
271 xf86_crtc_hide_cursor (crtc);
275 static void
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;
285 _X_EXPORT void
286 xf86_show_cursors (ScrnInfoPtr scrn)
288 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
289 int c;
291 xf86_config->cursor_on = TRUE;
292 for (c = 0; c < xf86_config->num_crtc; c++)
294 xf86CrtcPtr crtc = xf86_config->crtc[c];
296 if (crtc->enabled)
297 xf86_crtc_show_cursor (crtc);
301 static void
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;
308 Bool in_range;
309 int dx, dy;
312 * Transform position of cursor on screen
314 if (crtc->transform_in_use)
316 PictVector v;
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]);
321 else
323 x -= crtc->x;
324 y -= crtc->y;
327 * Transform position of cursor upper left corner
329 xf86_crtc_rotate_coord_back (crtc->rotation,
330 cursor_info->MaxWidth,
331 cursor_info->MaxHeight,
332 0, 0, &dx, &dy);
333 x -= dx;
334 y -= dy;
337 * Disable the cursor when it is outside the viewport
339 in_range = TRUE;
340 if (x >= mode->HDisplay || y >= mode->VDisplay ||
341 x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight)
343 in_range = FALSE;
344 x = 0;
345 y = 0;
348 crtc->cursor_in_range = in_range;
350 if (in_range)
352 crtc->funcs->set_cursor_position (crtc, x, y);
353 xf86_crtc_show_cursor (crtc);
355 else
356 xf86_crtc_hide_cursor (crtc);
359 static void
360 xf86_set_cursor_position (ScrnInfoPtr scrn, int x, int y)
362 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
363 int c;
365 /* undo what xf86HWCurs did to the coordinates */
366 x += scrn->frameX0;
367 y += scrn->frameY0;
368 for (c = 0; c < xf86_config->num_crtc; c++)
370 xf86CrtcPtr crtc = xf86_config->crtc[c];
372 if (crtc->enabled)
373 xf86_crtc_set_cursor_position (crtc, x, y);
378 * Load a two-color cursor into a crtc, performing rotation as needed
380 static void
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;
386 CARD8 *cursor_image;
388 #ifdef ARGB_CURSOR
389 crtc->cursor_argb = FALSE;
390 #endif
392 if (crtc->rotation == RR_Rotate_0)
393 cursor_image = src;
394 else
396 int x, y;
397 int xin, yin;
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,
410 x, y, &xin, &yin);
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
423 static void
424 xf86_load_cursor_image (ScrnInfoPtr scrn, unsigned char *src)
426 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
427 int c;
429 for (c = 0; c < xf86_config->num_crtc; c++)
431 xf86CrtcPtr crtc = xf86_config->crtc[c];
433 if (crtc->enabled)
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);
443 static Bool
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;
453 ++cursor->refcnt;
455 if (cursor->bits->width > cursor_info->MaxWidth ||
456 cursor->bits->height> cursor_info->MaxHeight)
457 return FALSE;
459 return TRUE;
462 static Bool
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;
472 ++cursor->refcnt;
474 /* Make sure ARGB support is available */
475 if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
476 return FALSE;
478 if (cursor->bits->width > cursor_info->MaxWidth ||
479 cursor->bits->height> cursor_info->MaxHeight)
480 return FALSE;
482 return TRUE;
485 static void
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;
493 int x, y;
494 int xin, yin;
495 CARD32 bits;
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,
505 x, y, &xin, &yin);
506 if (xin < source_width && yin < source_height)
507 bits = cursor_source[yin * source_width + xin];
508 else
509 bits = 0;
510 cursor_image[y * image_width + x] = bits;
513 crtc->funcs->load_cursor_argb (crtc, cursor_image);
516 static void
517 xf86_load_cursor_argb (ScrnInfoPtr scrn, CursorPtr cursor)
519 xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
520 int c;
522 for (c = 0; c < xf86_config->num_crtc; c++)
524 xf86CrtcPtr crtc = xf86_config->crtc[c];
526 if (crtc->enabled)
527 xf86_crtc_load_cursor_argb (crtc, cursor);
531 _X_EXPORT Bool
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();
539 if (!cursor_info)
540 return FALSE;
542 xf86_config->cursor_image = xalloc (max_width * max_height * 4);
544 if (!xf86_config->cursor_image)
546 xf86DestroyCursorInfoRec (cursor_info);
547 return FALSE;
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;
562 #ifdef ARGB_CURSOR
563 if (flags & HARDWARE_CURSOR_ARGB)
565 cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
566 cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
568 #endif
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
582 _X_EXPORT void
583 xf86_reload_cursors (ScreenPtr screen)
585 ScrnInfoPtr scrn;
586 xf86CrtcConfigPtr xf86_config;
587 xf86CursorInfoPtr cursor_info;
588 CursorPtr cursor;
589 int x, y;
591 /* initial mode setting will not have set a screen yet */
592 if (!screen)
593 return;
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;
599 if (!cursor_info)
600 return;
602 cursor = xf86_config->cursor;
603 GetSpritePosition (&x, &y);
604 if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
605 (*cursor_info->HideCursor)(scrn);
607 if (cursor)
609 #ifdef ARGB_CURSOR
610 if (cursor->bits->argb && cursor_info->LoadCursorARGB)
611 (*cursor_info->LoadCursorARGB) (scrn, cursor);
612 else
613 #endif
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
625 _X_EXPORT void
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;