xf86Cursors.c revision 1b684552
1/*
2 * Copyright © 2007 Keith Packard
3 * Copyright © 2010 Aaron Plattner
4 *
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.
14 *
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
21 * OF THIS SOFTWARE.
22 */
23
24#ifdef HAVE_XORG_CONFIG_H
25#include <xorg-config.h>
26#else
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30#endif
31
32#include <stddef.h>
33#include <string.h>
34#include <stdio.h>
35
36#include "xf86.h"
37#include "xf86DDC.h"
38#include "xf86Crtc.h"
39#include "xf86Modes.h"
40#include "xf86RandR12.h"
41#include "xf86CursorPriv.h"
42#include "X11/extensions/render.h"
43#include "X11/extensions/dpmsconst.h"
44#include "X11/Xatom.h"
45#include "picturestr.h"
46#include "cursorstr.h"
47#include "inputstr.h"
48
49/*
50 * Given a screen coordinate, rotate back to a cursor source coordinate
51 */
52static void
53xf86_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)
60{
61    int t;
62
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;
80    }
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;
87}
88
89/*
90 * Given a cursor source  coordinate, rotate to a screen coordinate
91 */
92static void
93xf86_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)
100{
101    int t;
102
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;
107
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;
125    }
126    *x_src = x_dst;
127    *y_src = y_dst;
128}
129
130struct cursor_bit {
131    CARD8 *byte;
132    char bitpos;
133};
134
135/*
136 * Convert an x coordinate to a position within the cursor bitmap
137 */
138static struct cursor_bit
139cursor_bitpos (CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y,
140	       Bool mask)
141{
142    const int flags = cursor_info->Flags;
143    const Bool interleaved =
144	!!(flags & (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
145		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
146		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 |
147		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
148		    HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64));
149    const int width = cursor_info->MaxWidth;
150    const int height = cursor_info->MaxHeight;
151    const int stride = interleaved ? width / 4 : width / 8;
152
153    struct cursor_bit ret;
154
155    image += y * stride;
156
157    if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
158	mask = !mask;
159    if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED)
160	x = (x & ~3) | (3 - (x & 3));
161    if (((flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) == 0) ==
162	(X_BYTE_ORDER == X_BIG_ENDIAN))
163	x = (x & ~7) | (7 - (x & 7));
164    if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1)
165	x = (x << 1) + mask;
166    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8)
167	x = ((x & ~7) << 1) | (mask << 3) | (x & 7);
168    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16)
169	x = ((x & ~15) << 1) | (mask << 4) | (x & 15);
170    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32)
171	x = ((x & ~31) << 1) | (mask << 5) | (x & 31);
172    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)
173	x = ((x & ~63) << 1) | (mask << 6) | (x & 63);
174    else if (mask)
175	image += stride * height;
176
177    ret.byte = image + (x / 8);
178    ret.bitpos = x & 7;
179
180    return ret;
181}
182
183/*
184 * Fetch one bit from a cursor bitmap
185 */
186static CARD8
187get_bit (CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
188{
189    struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask);
190    return (*bit.byte >> bit.bitpos) & 1;
191}
192
193/*
194 * Set one bit in a cursor bitmap
195 */
196static void
197set_bit (CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
198{
199    struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask);
200    *bit.byte |= 1 << bit.bitpos;
201}
202
203/*
204 * Load a two color cursor into a driver that supports only ARGB cursors
205 */
206static void
207xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
208{
209    ScrnInfoPtr		scrn = crtc->scrn;
210    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
211    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
212    CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image;
213    int			x, y;
214    int			xin, yin;
215    int			flags = cursor_info->Flags;
216    CARD32		bits;
217
218#ifdef ARGB_CURSOR
219    crtc->cursor_argb = FALSE;
220#endif
221
222    for (y = 0; y < cursor_info->MaxHeight; y++)
223	for (x = 0; x < cursor_info->MaxWidth; x++)
224	{
225	    xf86_crtc_rotate_coord (crtc->rotation,
226				    cursor_info->MaxWidth,
227				    cursor_info->MaxHeight,
228				    x, y, &xin, &yin);
229	    if (get_bit (src, cursor_info, xin, yin, TRUE) ==
230		((flags & HARDWARE_CURSOR_INVERT_MASK) == 0))
231	    {
232		if (get_bit (src, cursor_info, xin, yin, FALSE))
233		    bits = xf86_config->cursor_fg;
234		else
235		    bits = xf86_config->cursor_bg;
236	    }
237	    else
238		bits = 0;
239	    cursor_image[y * cursor_info->MaxWidth + x] = bits;
240	}
241    crtc->funcs->load_cursor_argb (crtc, cursor_image);
242}
243
244/*
245 * Set the colors for a two-color cursor (ignore for ARGB cursors)
246 */
247static void
248xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg)
249{
250    ScreenPtr		screen = scrn->pScreen;
251    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
252    CursorPtr		cursor = xf86_config->cursor;
253    int			c;
254    CARD8		*bits = cursor ?
255#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
256        dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen))
257#else
258        cursor->devPriv[screen->myNum]
259#endif
260      : NULL;
261
262    /* Save ARGB versions of these colors */
263    xf86_config->cursor_fg = (CARD32) fg | 0xff000000;
264    xf86_config->cursor_bg = (CARD32) bg | 0xff000000;
265
266    for (c = 0; c < xf86_config->num_crtc; c++)
267    {
268	xf86CrtcPtr crtc = xf86_config->crtc[c];
269
270	if (crtc->enabled && !crtc->cursor_argb)
271	{
272	    if (crtc->funcs->load_cursor_image)
273		crtc->funcs->set_cursor_colors (crtc, bg, fg);
274	    else if (bits)
275		xf86_crtc_convert_cursor_to_argb (crtc, bits);
276	}
277    }
278}
279
280static void
281xf86_crtc_hide_cursor (xf86CrtcPtr crtc)
282{
283    if (crtc->cursor_shown)
284    {
285	crtc->funcs->hide_cursor (crtc);
286	crtc->cursor_shown = FALSE;
287    }
288}
289
290void
291xf86_hide_cursors (ScrnInfoPtr scrn)
292{
293    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
294    int			c;
295
296    xf86_config->cursor_on = FALSE;
297    for (c = 0; c < xf86_config->num_crtc; c++)
298    {
299	xf86CrtcPtr crtc = xf86_config->crtc[c];
300
301	if (crtc->enabled)
302	    xf86_crtc_hide_cursor (crtc);
303    }
304}
305
306static void
307xf86_crtc_show_cursor (xf86CrtcPtr crtc)
308{
309    if (!crtc->cursor_shown && crtc->cursor_in_range)
310    {
311	crtc->funcs->show_cursor (crtc);
312	crtc->cursor_shown = TRUE;
313    }
314}
315
316void
317xf86_show_cursors (ScrnInfoPtr scrn)
318{
319    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
320    int			c;
321
322    xf86_config->cursor_on = TRUE;
323    for (c = 0; c < xf86_config->num_crtc; c++)
324    {
325	xf86CrtcPtr crtc = xf86_config->crtc[c];
326
327	if (crtc->enabled)
328	    xf86_crtc_show_cursor (crtc);
329    }
330}
331
332static void
333xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
334{
335    ScrnInfoPtr		scrn = crtc->scrn;
336    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
337    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
338    DisplayModePtr	mode = &crtc->mode;
339    Bool		in_range;
340    int			dx, dy;
341
342    /*
343     * Transform position of cursor on screen
344     */
345    if (crtc->transform_in_use)
346    {
347	ScreenPtr	screen = scrn->pScreen;
348	xf86CursorScreenPtr ScreenPriv =
349	    (xf86CursorScreenPtr)dixLookupPrivate(&screen->devPrivates,
350						  xf86CursorScreenKey);
351	struct pict_f_vector   v;
352
353	v.v[0] = (x + ScreenPriv->HotX) + 0.5;
354	v.v[1] = (y + ScreenPriv->HotY) + 0.5;
355	v.v[2] = 1;
356	pixman_f_transform_point (&crtc->f_framebuffer_to_crtc, &v);
357	/* cursor will have 0.5 added to it already so floor is sufficent */
358	x = floor (v.v[0]);
359	y = floor (v.v[1]);
360	/*
361	 * Transform position of cursor upper left corner
362	 */
363	xf86_crtc_rotate_coord_back (crtc->rotation,
364				     cursor_info->MaxWidth,
365				     cursor_info->MaxHeight,
366				     ScreenPriv->HotX, ScreenPriv->HotY, &dx, &dy);
367	x -= dx;
368	y -= dy;
369   }
370    else
371    {
372	x -= crtc->x;
373	y -= crtc->y;
374    }
375
376    /*
377     * Disable the cursor when it is outside the viewport
378     */
379    in_range = TRUE;
380    if (x >= mode->HDisplay || y >= mode->VDisplay ||
381	x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight)
382    {
383	in_range = FALSE;
384	x = 0;
385	y = 0;
386    }
387
388    crtc->cursor_in_range = in_range;
389
390    if (in_range)
391    {
392	crtc->funcs->set_cursor_position (crtc, x, y);
393	xf86_crtc_show_cursor (crtc);
394    }
395    else
396	xf86_crtc_hide_cursor (crtc);
397}
398
399static void
400xf86_set_cursor_position (ScrnInfoPtr scrn, int x, int y)
401{
402    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
403    int			c;
404
405    /* undo what xf86HWCurs did to the coordinates */
406    x += scrn->frameX0;
407    y += scrn->frameY0;
408    for (c = 0; c < xf86_config->num_crtc; c++)
409    {
410	xf86CrtcPtr crtc = xf86_config->crtc[c];
411
412	if (crtc->enabled)
413	    xf86_crtc_set_cursor_position (crtc, x, y);
414    }
415}
416
417/*
418 * Load a two-color cursor into a crtc, performing rotation as needed
419 */
420static void
421xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
422{
423    ScrnInfoPtr		scrn = crtc->scrn;
424    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
425    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
426    CARD8		*cursor_image;
427
428#ifdef ARGB_CURSOR
429    crtc->cursor_argb = FALSE;
430#endif
431
432    if (crtc->rotation == RR_Rotate_0)
433	cursor_image = src;
434    else
435    {
436        int x, y;
437    	int xin, yin;
438	int stride = cursor_info->MaxWidth >> 2;
439
440	cursor_image = xf86_config->cursor_image;
441	memset(cursor_image, 0, cursor_info->MaxHeight * stride);
442
443        for (y = 0; y < cursor_info->MaxHeight; y++)
444	    for (x = 0; x < cursor_info->MaxWidth; x++)
445	    {
446		xf86_crtc_rotate_coord (crtc->rotation,
447					cursor_info->MaxWidth,
448					cursor_info->MaxHeight,
449					x, y, &xin, &yin);
450		if (get_bit(src, cursor_info, xin, yin, FALSE))
451		    set_bit(cursor_image, cursor_info, x, y, FALSE);
452		if (get_bit(src, cursor_info, xin, yin, TRUE))
453		    set_bit(cursor_image, cursor_info, x, y, TRUE);
454	    }
455    }
456    crtc->funcs->load_cursor_image (crtc, cursor_image);
457}
458
459/*
460 * Load a cursor image into all active CRTCs
461 */
462static void
463xf86_load_cursor_image (ScrnInfoPtr scrn, unsigned char *src)
464{
465    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
466    int			c;
467
468    for (c = 0; c < xf86_config->num_crtc; c++)
469    {
470	xf86CrtcPtr crtc = xf86_config->crtc[c];
471
472	if (crtc->enabled)
473	{
474	    if (crtc->funcs->load_cursor_image)
475		xf86_crtc_load_cursor_image (crtc, src);
476	    else if (crtc->funcs->load_cursor_argb)
477		xf86_crtc_convert_cursor_to_argb (crtc, src);
478	}
479    }
480}
481
482static Bool
483xf86_use_hw_cursor (ScreenPtr screen, CursorPtr cursor)
484{
485    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
486    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
487    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
488
489    ++cursor->refcnt;
490    if (xf86_config->cursor)
491	FreeCursor (xf86_config->cursor, None);
492    xf86_config->cursor = cursor;
493
494    if (cursor->bits->width > cursor_info->MaxWidth ||
495	cursor->bits->height> cursor_info->MaxHeight)
496	return FALSE;
497
498    return TRUE;
499}
500
501static Bool
502xf86_use_hw_cursor_argb (ScreenPtr screen, CursorPtr cursor)
503{
504    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
505    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
506    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
507
508    ++cursor->refcnt;
509    if (xf86_config->cursor)
510	FreeCursor (xf86_config->cursor, None);
511    xf86_config->cursor = cursor;
512
513    /* Make sure ARGB support is available */
514    if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
515	return FALSE;
516
517    if (cursor->bits->width > cursor_info->MaxWidth ||
518	cursor->bits->height> cursor_info->MaxHeight)
519	return FALSE;
520
521    return TRUE;
522}
523
524static void
525xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
526{
527    ScrnInfoPtr		scrn = crtc->scrn;
528    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
529    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
530    CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image;
531    CARD32		*cursor_source = (CARD32 *) cursor->bits->argb;
532    int			x, y;
533    int			xin, yin;
534    CARD32		bits;
535    int			source_width = cursor->bits->width;
536    int			source_height = cursor->bits->height;
537    int			image_width = cursor_info->MaxWidth;
538    int			image_height = cursor_info->MaxHeight;
539
540    for (y = 0; y < image_height; y++)
541	for (x = 0; x < image_width; x++)
542	{
543	    xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
544				    x, y, &xin, &yin);
545	    if (xin < source_width && yin < source_height)
546		bits = cursor_source[yin * source_width + xin];
547	    else
548		bits = 0;
549	    cursor_image[y * image_width + x] = bits;
550	}
551
552    crtc->funcs->load_cursor_argb (crtc, cursor_image);
553}
554
555static void
556xf86_load_cursor_argb (ScrnInfoPtr scrn, CursorPtr cursor)
557{
558    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
559    int			c;
560
561    for (c = 0; c < xf86_config->num_crtc; c++)
562    {
563	xf86CrtcPtr crtc = xf86_config->crtc[c];
564
565	if (crtc->enabled)
566	    xf86_crtc_load_cursor_argb (crtc, cursor);
567    }
568}
569
570Bool
571xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags)
572{
573    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
574    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
575    xf86CursorInfoPtr	cursor_info;
576
577    cursor_info = xf86CreateCursorInfoRec();
578    if (!cursor_info)
579	return FALSE;
580
581    xf86_config->cursor_image = malloc(max_width * max_height * 4);
582
583    if (!xf86_config->cursor_image)
584    {
585	xf86DestroyCursorInfoRec (cursor_info);
586	return FALSE;
587    }
588
589    xf86_config->cursor_info = cursor_info;
590
591    cursor_info->MaxWidth = max_width;
592    cursor_info->MaxHeight = max_height;
593    cursor_info->Flags = flags;
594
595    cursor_info->SetCursorColors = xf86_set_cursor_colors;
596    cursor_info->SetCursorPosition = xf86_set_cursor_position;
597    cursor_info->LoadCursorImage = xf86_load_cursor_image;
598    cursor_info->HideCursor = xf86_hide_cursors;
599    cursor_info->ShowCursor = xf86_show_cursors;
600    cursor_info->UseHWCursor = xf86_use_hw_cursor;
601#ifdef ARGB_CURSOR
602    if (flags & HARDWARE_CURSOR_ARGB)
603    {
604	cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
605	cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
606    }
607#endif
608
609    xf86_config->cursor = NULL;
610    xf86_hide_cursors (scrn);
611
612    return xf86InitCursor (screen, cursor_info);
613}
614
615/**
616 * Called when anything on the screen is reconfigured.
617 *
618 * Reloads cursor images as needed, then adjusts cursor positions
619 */
620
621void
622xf86_reload_cursors (ScreenPtr screen)
623{
624    ScrnInfoPtr		scrn;
625    xf86CrtcConfigPtr   xf86_config;
626    xf86CursorInfoPtr   cursor_info;
627    CursorPtr		cursor;
628    int			x, y;
629    xf86CursorScreenPtr cursor_screen_priv;
630
631    /* initial mode setting will not have set a screen yet.
632       May be called before the devices are initialised.
633     */
634    if (!screen || !inputInfo.pointer)
635	return;
636    cursor_screen_priv = dixLookupPrivate(&screen->devPrivates,
637					  xf86CursorScreenKey);
638    /* return if HW cursor is inactive, to avoid displaying two cursors */
639    if (!cursor_screen_priv || !cursor_screen_priv->isUp)
640	return;
641
642    scrn = xf86Screens[screen->myNum];
643    xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
644
645    /* make sure the cursor code has been initialized */
646    cursor_info = xf86_config->cursor_info;
647    if (!cursor_info)
648	return;
649
650    cursor = xf86_config->cursor;
651    GetSpritePosition (inputInfo.pointer, &x, &y);
652    if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
653	(*cursor_info->HideCursor)(scrn);
654
655    if (cursor)
656    {
657#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0)
658	void *src = dixLookupPrivate(&cursor->devPrivates, CursorScreenKey(screen));
659#else
660	void *src = cursor->devPriv[screen->myNum];
661#endif
662#ifdef ARGB_CURSOR
663	if (cursor->bits->argb && cursor_info->LoadCursorARGB)
664	    (*cursor_info->LoadCursorARGB) (scrn, cursor);
665	else if (src)
666#endif
667	    (*cursor_info->LoadCursorImage)(scrn, src);
668
669	x += scrn->frameX0 + cursor_screen_priv->HotX;
670	y += scrn->frameY0 + cursor_screen_priv->HotY;
671	(*cursor_info->SetCursorPosition)(scrn, x, y);
672    }
673}
674
675/**
676 * Clean up CRTC-based cursor code
677 */
678void
679xf86_cursors_fini (ScreenPtr screen)
680{
681    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
682    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
683
684    if (xf86_config->cursor_info)
685    {
686	xf86DestroyCursorInfoRec (xf86_config->cursor_info);
687	xf86_config->cursor_info = NULL;
688    }
689    free(xf86_config->cursor_image);
690    xf86_config->cursor_image = NULL;
691    if (xf86_config->cursor)
692    {
693	FreeCursor (xf86_config->cursor, None);
694	xf86_config->cursor = NULL;
695    }
696}
697