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