1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2007 Keith Packard
3*4882a593Smuzhiyun * Copyright © 2010-2011 Aaron Plattner
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software and its
6*4882a593Smuzhiyun * documentation for any purpose is hereby granted without fee, provided that
7*4882a593Smuzhiyun * the above copyright notice appear in all copies and that both that copyright
8*4882a593Smuzhiyun * notice and this permission notice appear in supporting documentation, and
9*4882a593Smuzhiyun * that the name of the copyright holders not be used in advertising or
10*4882a593Smuzhiyun * publicity pertaining to distribution of the software without specific,
11*4882a593Smuzhiyun * written prior permission. The copyright holders make no representations
12*4882a593Smuzhiyun * about the suitability of this software for any purpose. It is provided "as
13*4882a593Smuzhiyun * is" without express or implied warranty.
14*4882a593Smuzhiyun *
15*4882a593Smuzhiyun * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16*4882a593Smuzhiyun * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
17*4882a593Smuzhiyun * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
19*4882a593Smuzhiyun * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20*4882a593Smuzhiyun * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21*4882a593Smuzhiyun * OF THIS SOFTWARE.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
25*4882a593Smuzhiyun #include <xorg-config.h>
26*4882a593Smuzhiyun #endif
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #include <stddef.h>
29*4882a593Smuzhiyun #include <string.h>
30*4882a593Smuzhiyun #include <stdio.h>
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #include <X11/Xarch.h>
33*4882a593Smuzhiyun #include "xf86.h"
34*4882a593Smuzhiyun #include "xf86DDC.h"
35*4882a593Smuzhiyun #include "xf86Crtc.h"
36*4882a593Smuzhiyun #include "xf86Modes.h"
37*4882a593Smuzhiyun #include "xf86RandR12.h"
38*4882a593Smuzhiyun #include "xf86CursorPriv.h"
39*4882a593Smuzhiyun #include "X11/extensions/render.h"
40*4882a593Smuzhiyun #include "X11/extensions/dpmsconst.h"
41*4882a593Smuzhiyun #include "X11/Xatom.h"
42*4882a593Smuzhiyun #include "picturestr.h"
43*4882a593Smuzhiyun #include "cursorstr.h"
44*4882a593Smuzhiyun #include "inputstr.h"
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /*
47*4882a593Smuzhiyun * Returns the rotation being performed by the server. If the driver indicates
48*4882a593Smuzhiyun * that it's handling the screen transform, then this returns RR_Rotate_0.
49*4882a593Smuzhiyun */
50*4882a593Smuzhiyun static Rotation
xf86_crtc_cursor_rotation(xf86CrtcPtr crtc)51*4882a593Smuzhiyun xf86_crtc_cursor_rotation(xf86CrtcPtr crtc)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun if (crtc->driverIsPerformingTransform & XF86DriverTransformCursorImage)
54*4882a593Smuzhiyun return RR_Rotate_0;
55*4882a593Smuzhiyun return crtc->rotation;
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /*
59*4882a593Smuzhiyun * Given a screen coordinate, rotate back to a cursor source coordinate
60*4882a593Smuzhiyun */
61*4882a593Smuzhiyun static void
xf86_crtc_rotate_coord(Rotation rotation,int width,int height,int x_dst,int y_dst,int * x_src,int * y_src)62*4882a593Smuzhiyun xf86_crtc_rotate_coord(Rotation rotation,
63*4882a593Smuzhiyun int width,
64*4882a593Smuzhiyun int height, int x_dst, int y_dst, int *x_src, int *y_src)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun int t;
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun switch (rotation & 0xf) {
69*4882a593Smuzhiyun case RR_Rotate_0:
70*4882a593Smuzhiyun break;
71*4882a593Smuzhiyun case RR_Rotate_90:
72*4882a593Smuzhiyun t = x_dst;
73*4882a593Smuzhiyun x_dst = width - y_dst - 1;
74*4882a593Smuzhiyun y_dst = t;
75*4882a593Smuzhiyun break;
76*4882a593Smuzhiyun case RR_Rotate_180:
77*4882a593Smuzhiyun x_dst = width - x_dst - 1;
78*4882a593Smuzhiyun y_dst = height - y_dst - 1;
79*4882a593Smuzhiyun break;
80*4882a593Smuzhiyun case RR_Rotate_270:
81*4882a593Smuzhiyun t = x_dst;
82*4882a593Smuzhiyun x_dst = y_dst;
83*4882a593Smuzhiyun y_dst = height - t - 1;
84*4882a593Smuzhiyun break;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun if (rotation & RR_Reflect_X)
87*4882a593Smuzhiyun x_dst = width - x_dst - 1;
88*4882a593Smuzhiyun if (rotation & RR_Reflect_Y)
89*4882a593Smuzhiyun y_dst = height - y_dst - 1;
90*4882a593Smuzhiyun *x_src = x_dst;
91*4882a593Smuzhiyun *y_src = y_dst;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun /*
95*4882a593Smuzhiyun * Given a cursor source coordinate, rotate to a screen coordinate
96*4882a593Smuzhiyun */
97*4882a593Smuzhiyun static void
xf86_crtc_rotate_coord_back(Rotation rotation,int width,int height,int x_dst,int y_dst,int * x_src,int * y_src)98*4882a593Smuzhiyun xf86_crtc_rotate_coord_back(Rotation rotation,
99*4882a593Smuzhiyun int width,
100*4882a593Smuzhiyun int height,
101*4882a593Smuzhiyun int x_dst, int y_dst, int *x_src, int *y_src)
102*4882a593Smuzhiyun {
103*4882a593Smuzhiyun int t;
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun if (rotation & RR_Reflect_X)
106*4882a593Smuzhiyun x_dst = width - x_dst - 1;
107*4882a593Smuzhiyun if (rotation & RR_Reflect_Y)
108*4882a593Smuzhiyun y_dst = height - y_dst - 1;
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun switch (rotation & 0xf) {
111*4882a593Smuzhiyun case RR_Rotate_0:
112*4882a593Smuzhiyun break;
113*4882a593Smuzhiyun case RR_Rotate_90:
114*4882a593Smuzhiyun t = x_dst;
115*4882a593Smuzhiyun x_dst = y_dst;
116*4882a593Smuzhiyun y_dst = width - t - 1;
117*4882a593Smuzhiyun break;
118*4882a593Smuzhiyun case RR_Rotate_180:
119*4882a593Smuzhiyun x_dst = width - x_dst - 1;
120*4882a593Smuzhiyun y_dst = height - y_dst - 1;
121*4882a593Smuzhiyun break;
122*4882a593Smuzhiyun case RR_Rotate_270:
123*4882a593Smuzhiyun t = x_dst;
124*4882a593Smuzhiyun x_dst = height - y_dst - 1;
125*4882a593Smuzhiyun y_dst = t;
126*4882a593Smuzhiyun break;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun *x_src = x_dst;
129*4882a593Smuzhiyun *y_src = y_dst;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun struct cursor_bit {
133*4882a593Smuzhiyun CARD8 *byte;
134*4882a593Smuzhiyun char bitpos;
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun
137*4882a593Smuzhiyun /*
138*4882a593Smuzhiyun * Convert an x coordinate to a position within the cursor bitmap
139*4882a593Smuzhiyun */
140*4882a593Smuzhiyun static struct cursor_bit
cursor_bitpos(CARD8 * image,xf86CursorInfoPtr cursor_info,int x,int y,Bool mask)141*4882a593Smuzhiyun cursor_bitpos(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y,
142*4882a593Smuzhiyun Bool mask)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun const int flags = cursor_info->Flags;
145*4882a593Smuzhiyun const Bool interleaved =
146*4882a593Smuzhiyun ! !(flags & (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
147*4882a593Smuzhiyun HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
148*4882a593Smuzhiyun HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 |
149*4882a593Smuzhiyun HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
150*4882a593Smuzhiyun HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64));
151*4882a593Smuzhiyun const int width = cursor_info->MaxWidth;
152*4882a593Smuzhiyun const int height = cursor_info->MaxHeight;
153*4882a593Smuzhiyun const int stride = interleaved ? width / 4 : width / 8;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun struct cursor_bit ret;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun image += y * stride;
158*4882a593Smuzhiyun
159*4882a593Smuzhiyun if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
160*4882a593Smuzhiyun mask = !mask;
161*4882a593Smuzhiyun if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED)
162*4882a593Smuzhiyun x = (x & ~3) | (3 - (x & 3));
163*4882a593Smuzhiyun if (((flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST) == 0) ==
164*4882a593Smuzhiyun (X_BYTE_ORDER == X_BIG_ENDIAN))
165*4882a593Smuzhiyun x = (x & ~7) | (7 - (x & 7));
166*4882a593Smuzhiyun if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1)
167*4882a593Smuzhiyun x = (x << 1) + mask;
168*4882a593Smuzhiyun else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8)
169*4882a593Smuzhiyun x = ((x & ~7) << 1) | (mask << 3) | (x & 7);
170*4882a593Smuzhiyun else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16)
171*4882a593Smuzhiyun x = ((x & ~15) << 1) | (mask << 4) | (x & 15);
172*4882a593Smuzhiyun else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32)
173*4882a593Smuzhiyun x = ((x & ~31) << 1) | (mask << 5) | (x & 31);
174*4882a593Smuzhiyun else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)
175*4882a593Smuzhiyun x = ((x & ~63) << 1) | (mask << 6) | (x & 63);
176*4882a593Smuzhiyun else if (mask)
177*4882a593Smuzhiyun image += stride * height;
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun ret.byte = image + (x / 8);
180*4882a593Smuzhiyun ret.bitpos = x & 7;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun return ret;
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun /*
186*4882a593Smuzhiyun * Fetch one bit from a cursor bitmap
187*4882a593Smuzhiyun */
188*4882a593Smuzhiyun static CARD8
get_bit(CARD8 * image,xf86CursorInfoPtr cursor_info,int x,int y,Bool mask)189*4882a593Smuzhiyun get_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
190*4882a593Smuzhiyun {
191*4882a593Smuzhiyun struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask);
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun return (*bit.byte >> bit.bitpos) & 1;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun /*
197*4882a593Smuzhiyun * Set one bit in a cursor bitmap
198*4882a593Smuzhiyun */
199*4882a593Smuzhiyun static void
set_bit(CARD8 * image,xf86CursorInfoPtr cursor_info,int x,int y,Bool mask)200*4882a593Smuzhiyun set_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
201*4882a593Smuzhiyun {
202*4882a593Smuzhiyun struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun *bit.byte |= 1 << bit.bitpos;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * Wrappers to deal with API compatibility with drivers that don't expose
209*4882a593Smuzhiyun * *_cursor_*_check
210*4882a593Smuzhiyun */
211*4882a593Smuzhiyun static inline Bool
xf86_driver_has_show_cursor(xf86CrtcPtr crtc)212*4882a593Smuzhiyun xf86_driver_has_show_cursor(xf86CrtcPtr crtc)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun return crtc->funcs->show_cursor_check || crtc->funcs->show_cursor;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun static inline Bool
xf86_driver_has_load_cursor_image(xf86CrtcPtr crtc)218*4882a593Smuzhiyun xf86_driver_has_load_cursor_image(xf86CrtcPtr crtc)
219*4882a593Smuzhiyun {
220*4882a593Smuzhiyun return crtc->funcs->load_cursor_image_check || crtc->funcs->load_cursor_image;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun static inline Bool
xf86_driver_has_load_cursor_argb(xf86CrtcPtr crtc)224*4882a593Smuzhiyun xf86_driver_has_load_cursor_argb(xf86CrtcPtr crtc)
225*4882a593Smuzhiyun {
226*4882a593Smuzhiyun return crtc->funcs->load_cursor_argb_check || crtc->funcs->load_cursor_argb;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun static inline Bool
xf86_driver_show_cursor(xf86CrtcPtr crtc)230*4882a593Smuzhiyun xf86_driver_show_cursor(xf86CrtcPtr crtc)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun if (crtc->funcs->show_cursor_check)
233*4882a593Smuzhiyun return crtc->funcs->show_cursor_check(crtc);
234*4882a593Smuzhiyun crtc->funcs->show_cursor(crtc);
235*4882a593Smuzhiyun return TRUE;
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun static inline Bool
xf86_driver_load_cursor_image(xf86CrtcPtr crtc,CARD8 * cursor_image)239*4882a593Smuzhiyun xf86_driver_load_cursor_image(xf86CrtcPtr crtc, CARD8 *cursor_image)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun if (crtc->funcs->load_cursor_image_check)
242*4882a593Smuzhiyun return crtc->funcs->load_cursor_image_check(crtc, cursor_image);
243*4882a593Smuzhiyun crtc->funcs->load_cursor_image(crtc, cursor_image);
244*4882a593Smuzhiyun return TRUE;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun static inline Bool
xf86_driver_load_cursor_argb(xf86CrtcPtr crtc,CARD32 * cursor_argb)248*4882a593Smuzhiyun xf86_driver_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *cursor_argb)
249*4882a593Smuzhiyun {
250*4882a593Smuzhiyun if (crtc->funcs->load_cursor_argb_check)
251*4882a593Smuzhiyun return crtc->funcs->load_cursor_argb_check(crtc, cursor_argb);
252*4882a593Smuzhiyun crtc->funcs->load_cursor_argb(crtc, cursor_argb);
253*4882a593Smuzhiyun return TRUE;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /*
257*4882a593Smuzhiyun * Load a two color cursor into a driver that supports only ARGB cursors
258*4882a593Smuzhiyun */
259*4882a593Smuzhiyun static Bool
xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc,unsigned char * src)260*4882a593Smuzhiyun xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src)
261*4882a593Smuzhiyun {
262*4882a593Smuzhiyun ScrnInfoPtr scrn = crtc->scrn;
263*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
264*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
265*4882a593Smuzhiyun CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image;
266*4882a593Smuzhiyun int x, y;
267*4882a593Smuzhiyun int xin, yin;
268*4882a593Smuzhiyun int flags = cursor_info->Flags;
269*4882a593Smuzhiyun CARD32 bits;
270*4882a593Smuzhiyun const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun crtc->cursor_argb = FALSE;
273*4882a593Smuzhiyun
274*4882a593Smuzhiyun for (y = 0; y < cursor_info->MaxHeight; y++)
275*4882a593Smuzhiyun for (x = 0; x < cursor_info->MaxWidth; x++) {
276*4882a593Smuzhiyun xf86_crtc_rotate_coord(rotation,
277*4882a593Smuzhiyun cursor_info->MaxWidth,
278*4882a593Smuzhiyun cursor_info->MaxHeight, x, y, &xin, &yin);
279*4882a593Smuzhiyun if (get_bit(src, cursor_info, xin, yin, TRUE) ==
280*4882a593Smuzhiyun ((flags & HARDWARE_CURSOR_INVERT_MASK) == 0)) {
281*4882a593Smuzhiyun if (get_bit(src, cursor_info, xin, yin, FALSE))
282*4882a593Smuzhiyun bits = xf86_config->cursor_fg;
283*4882a593Smuzhiyun else
284*4882a593Smuzhiyun bits = xf86_config->cursor_bg;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun else
287*4882a593Smuzhiyun bits = 0;
288*4882a593Smuzhiyun cursor_image[y * cursor_info->MaxWidth + x] = bits;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun return xf86_driver_load_cursor_argb(crtc, cursor_image);
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun /*
294*4882a593Smuzhiyun * Set the colors for a two-color cursor (ignore for ARGB cursors)
295*4882a593Smuzhiyun */
296*4882a593Smuzhiyun static void
xf86_set_cursor_colors(ScrnInfoPtr scrn,int bg,int fg)297*4882a593Smuzhiyun xf86_set_cursor_colors(ScrnInfoPtr scrn, int bg, int fg)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun ScreenPtr screen = scrn->pScreen;
300*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
301*4882a593Smuzhiyun CursorPtr cursor = xf86CurrentCursor(screen);
302*4882a593Smuzhiyun int c;
303*4882a593Smuzhiyun CARD8 *bits = cursor ?
304*4882a593Smuzhiyun dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, screen)
305*4882a593Smuzhiyun : NULL;
306*4882a593Smuzhiyun
307*4882a593Smuzhiyun /* Save ARGB versions of these colors */
308*4882a593Smuzhiyun xf86_config->cursor_fg = (CARD32) fg | 0xff000000;
309*4882a593Smuzhiyun xf86_config->cursor_bg = (CARD32) bg | 0xff000000;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
312*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun if (crtc->enabled && !crtc->cursor_argb) {
315*4882a593Smuzhiyun if (xf86_driver_has_load_cursor_image(crtc))
316*4882a593Smuzhiyun crtc->funcs->set_cursor_colors(crtc, bg, fg);
317*4882a593Smuzhiyun else if (bits)
318*4882a593Smuzhiyun xf86_crtc_convert_cursor_to_argb(crtc, bits);
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun void
xf86_crtc_hide_cursor(xf86CrtcPtr crtc)324*4882a593Smuzhiyun xf86_crtc_hide_cursor(xf86CrtcPtr crtc)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun if (crtc->cursor_shown) {
327*4882a593Smuzhiyun crtc->funcs->hide_cursor(crtc);
328*4882a593Smuzhiyun crtc->cursor_shown = FALSE;
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun void
xf86_hide_cursors(ScrnInfoPtr scrn)333*4882a593Smuzhiyun xf86_hide_cursors(ScrnInfoPtr scrn)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
336*4882a593Smuzhiyun int c;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun xf86_config->cursor_on = FALSE;
339*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
340*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun if (crtc->enabled)
343*4882a593Smuzhiyun xf86_crtc_hide_cursor(crtc);
344*4882a593Smuzhiyun }
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun Bool
xf86_crtc_show_cursor(xf86CrtcPtr crtc)348*4882a593Smuzhiyun xf86_crtc_show_cursor(xf86CrtcPtr crtc)
349*4882a593Smuzhiyun {
350*4882a593Smuzhiyun if (!crtc->cursor_in_range) {
351*4882a593Smuzhiyun crtc->funcs->hide_cursor(crtc);
352*4882a593Smuzhiyun return TRUE;
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun if (!crtc->cursor_shown)
356*4882a593Smuzhiyun crtc->cursor_shown = xf86_driver_show_cursor(crtc);
357*4882a593Smuzhiyun
358*4882a593Smuzhiyun return crtc->cursor_shown;
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun Bool
xf86_show_cursors(ScrnInfoPtr scrn)362*4882a593Smuzhiyun xf86_show_cursors(ScrnInfoPtr scrn)
363*4882a593Smuzhiyun {
364*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
365*4882a593Smuzhiyun int c;
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun xf86_config->cursor_on = TRUE;
368*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
369*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun if (crtc->enabled && !xf86_crtc_show_cursor(crtc))
372*4882a593Smuzhiyun return FALSE;
373*4882a593Smuzhiyun }
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun return TRUE;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun static void
xf86_crtc_transform_cursor_position(xf86CrtcPtr crtc,int * x,int * y)379*4882a593Smuzhiyun xf86_crtc_transform_cursor_position(xf86CrtcPtr crtc, int *x, int *y)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun ScrnInfoPtr scrn = crtc->scrn;
382*4882a593Smuzhiyun ScreenPtr screen = scrn->pScreen;
383*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
384*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
385*4882a593Smuzhiyun xf86CursorScreenPtr ScreenPriv =
386*4882a593Smuzhiyun (xf86CursorScreenPtr) dixLookupPrivate(&screen->devPrivates,
387*4882a593Smuzhiyun xf86CursorScreenKey);
388*4882a593Smuzhiyun int dx, dy, t;
389*4882a593Smuzhiyun Bool swap_reflection = FALSE;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun *x = *x - crtc->x + ScreenPriv->HotX;
392*4882a593Smuzhiyun *y = *y - crtc->y + ScreenPriv->HotY;
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun switch (crtc->rotation & 0xf) {
395*4882a593Smuzhiyun case RR_Rotate_0:
396*4882a593Smuzhiyun break;
397*4882a593Smuzhiyun case RR_Rotate_90:
398*4882a593Smuzhiyun t = *x;
399*4882a593Smuzhiyun *x = *y;
400*4882a593Smuzhiyun *y = crtc->mode.VDisplay - t - 1;
401*4882a593Smuzhiyun swap_reflection = TRUE;
402*4882a593Smuzhiyun break;
403*4882a593Smuzhiyun case RR_Rotate_180:
404*4882a593Smuzhiyun *x = crtc->mode.HDisplay - *x - 1;
405*4882a593Smuzhiyun *y = crtc->mode.VDisplay - *y - 1;
406*4882a593Smuzhiyun break;
407*4882a593Smuzhiyun case RR_Rotate_270:
408*4882a593Smuzhiyun t = *x;
409*4882a593Smuzhiyun *x = crtc->mode.HDisplay - *y - 1;
410*4882a593Smuzhiyun *y = t;
411*4882a593Smuzhiyun swap_reflection = TRUE;
412*4882a593Smuzhiyun break;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun if (swap_reflection) {
416*4882a593Smuzhiyun if (crtc->rotation & RR_Reflect_Y)
417*4882a593Smuzhiyun *x = crtc->mode.HDisplay - *x - 1;
418*4882a593Smuzhiyun if (crtc->rotation & RR_Reflect_X)
419*4882a593Smuzhiyun *y = crtc->mode.VDisplay - *y - 1;
420*4882a593Smuzhiyun } else {
421*4882a593Smuzhiyun if (crtc->rotation & RR_Reflect_X)
422*4882a593Smuzhiyun *x = crtc->mode.HDisplay - *x - 1;
423*4882a593Smuzhiyun if (crtc->rotation & RR_Reflect_Y)
424*4882a593Smuzhiyun *y = crtc->mode.VDisplay - *y - 1;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun /*
428*4882a593Smuzhiyun * Transform position of cursor upper left corner
429*4882a593Smuzhiyun */
430*4882a593Smuzhiyun xf86_crtc_rotate_coord_back(crtc->rotation, cursor_info->MaxWidth,
431*4882a593Smuzhiyun cursor_info->MaxHeight, ScreenPriv->HotX,
432*4882a593Smuzhiyun ScreenPriv->HotY, &dx, &dy);
433*4882a593Smuzhiyun *x -= dx;
434*4882a593Smuzhiyun *y -= dy;
435*4882a593Smuzhiyun }
436*4882a593Smuzhiyun
437*4882a593Smuzhiyun static void
xf86_crtc_set_cursor_position(xf86CrtcPtr crtc,int x,int y)438*4882a593Smuzhiyun xf86_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
439*4882a593Smuzhiyun {
440*4882a593Smuzhiyun ScrnInfoPtr scrn = crtc->scrn;
441*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
442*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
443*4882a593Smuzhiyun DisplayModePtr mode = &crtc->mode;
444*4882a593Smuzhiyun int crtc_x = x, crtc_y = y;
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun /*
447*4882a593Smuzhiyun * Transform position of cursor on screen
448*4882a593Smuzhiyun */
449*4882a593Smuzhiyun if (crtc->rotation != RR_Rotate_0)
450*4882a593Smuzhiyun xf86_crtc_transform_cursor_position(crtc, &crtc_x, &crtc_y);
451*4882a593Smuzhiyun else {
452*4882a593Smuzhiyun crtc_x -= crtc->x;
453*4882a593Smuzhiyun crtc_y -= crtc->y;
454*4882a593Smuzhiyun }
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun /*
457*4882a593Smuzhiyun * Disable the cursor when it is outside the viewport
458*4882a593Smuzhiyun */
459*4882a593Smuzhiyun if (crtc_x >= mode->HDisplay || crtc_y >= mode->VDisplay ||
460*4882a593Smuzhiyun crtc_x <= -cursor_info->MaxWidth || crtc_y <= -cursor_info->MaxHeight) {
461*4882a593Smuzhiyun crtc->cursor_in_range = FALSE;
462*4882a593Smuzhiyun xf86_crtc_hide_cursor(crtc);
463*4882a593Smuzhiyun } else {
464*4882a593Smuzhiyun crtc->cursor_in_range = TRUE;
465*4882a593Smuzhiyun if (crtc->driverIsPerformingTransform & XF86DriverTransformCursorPosition)
466*4882a593Smuzhiyun crtc->funcs->set_cursor_position(crtc, x, y);
467*4882a593Smuzhiyun else
468*4882a593Smuzhiyun crtc->funcs->set_cursor_position(crtc, crtc_x, crtc_y);
469*4882a593Smuzhiyun xf86_crtc_show_cursor(crtc);
470*4882a593Smuzhiyun }
471*4882a593Smuzhiyun }
472*4882a593Smuzhiyun
473*4882a593Smuzhiyun static void
xf86_set_cursor_position(ScrnInfoPtr scrn,int x,int y)474*4882a593Smuzhiyun xf86_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
475*4882a593Smuzhiyun {
476*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
477*4882a593Smuzhiyun int c;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun /* undo what xf86HWCurs did to the coordinates */
480*4882a593Smuzhiyun x += scrn->frameX0;
481*4882a593Smuzhiyun y += scrn->frameY0;
482*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
483*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun if (crtc->enabled)
486*4882a593Smuzhiyun xf86_crtc_set_cursor_position(crtc, x, y);
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
490*4882a593Smuzhiyun /*
491*4882a593Smuzhiyun * Load a two-color cursor into a crtc, performing rotation as needed
492*4882a593Smuzhiyun */
493*4882a593Smuzhiyun static Bool
xf86_crtc_load_cursor_image(xf86CrtcPtr crtc,CARD8 * src)494*4882a593Smuzhiyun xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src)
495*4882a593Smuzhiyun {
496*4882a593Smuzhiyun ScrnInfoPtr scrn = crtc->scrn;
497*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
498*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
499*4882a593Smuzhiyun CARD8 *cursor_image;
500*4882a593Smuzhiyun const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
501*4882a593Smuzhiyun
502*4882a593Smuzhiyun crtc->cursor_argb = FALSE;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun if (rotation == RR_Rotate_0)
505*4882a593Smuzhiyun cursor_image = src;
506*4882a593Smuzhiyun else {
507*4882a593Smuzhiyun int x, y;
508*4882a593Smuzhiyun int xin, yin;
509*4882a593Smuzhiyun int stride = cursor_info->MaxWidth >> 2;
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun cursor_image = xf86_config->cursor_image;
512*4882a593Smuzhiyun memset(cursor_image, 0, cursor_info->MaxHeight * stride);
513*4882a593Smuzhiyun
514*4882a593Smuzhiyun for (y = 0; y < cursor_info->MaxHeight; y++)
515*4882a593Smuzhiyun for (x = 0; x < cursor_info->MaxWidth; x++) {
516*4882a593Smuzhiyun xf86_crtc_rotate_coord(rotation,
517*4882a593Smuzhiyun cursor_info->MaxWidth,
518*4882a593Smuzhiyun cursor_info->MaxHeight,
519*4882a593Smuzhiyun x, y, &xin, &yin);
520*4882a593Smuzhiyun if (get_bit(src, cursor_info, xin, yin, FALSE))
521*4882a593Smuzhiyun set_bit(cursor_image, cursor_info, x, y, FALSE);
522*4882a593Smuzhiyun if (get_bit(src, cursor_info, xin, yin, TRUE))
523*4882a593Smuzhiyun set_bit(cursor_image, cursor_info, x, y, TRUE);
524*4882a593Smuzhiyun }
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun return xf86_driver_load_cursor_image(crtc, cursor_image);
527*4882a593Smuzhiyun }
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun /*
530*4882a593Smuzhiyun * Load a cursor image into all active CRTCs
531*4882a593Smuzhiyun */
532*4882a593Smuzhiyun static Bool
xf86_load_cursor_image(ScrnInfoPtr scrn,unsigned char * src)533*4882a593Smuzhiyun xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
534*4882a593Smuzhiyun {
535*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
536*4882a593Smuzhiyun int c;
537*4882a593Smuzhiyun
538*4882a593Smuzhiyun xf86_config->cursor = xf86CurrentCursor(scrn->pScreen);
539*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
540*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
541*4882a593Smuzhiyun
542*4882a593Smuzhiyun if (crtc->enabled) {
543*4882a593Smuzhiyun if (xf86_driver_has_load_cursor_image(crtc)) {
544*4882a593Smuzhiyun if (!xf86_crtc_load_cursor_image(crtc, src))
545*4882a593Smuzhiyun return FALSE;
546*4882a593Smuzhiyun } else if (xf86_driver_has_load_cursor_argb(crtc)) {
547*4882a593Smuzhiyun if (!xf86_crtc_convert_cursor_to_argb(crtc, src))
548*4882a593Smuzhiyun return FALSE;
549*4882a593Smuzhiyun } else
550*4882a593Smuzhiyun return FALSE;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun return TRUE;
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun static Bool
xf86_use_hw_cursor(ScreenPtr screen,CursorPtr cursor)557*4882a593Smuzhiyun xf86_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
558*4882a593Smuzhiyun {
559*4882a593Smuzhiyun ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
560*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
561*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
562*4882a593Smuzhiyun int c;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun if (cursor->bits->width > cursor_info->MaxWidth ||
565*4882a593Smuzhiyun cursor->bits->height > cursor_info->MaxHeight)
566*4882a593Smuzhiyun return FALSE;
567*4882a593Smuzhiyun
568*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
569*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
570*4882a593Smuzhiyun
571*4882a593Smuzhiyun if (!crtc->enabled)
572*4882a593Smuzhiyun continue;
573*4882a593Smuzhiyun
574*4882a593Smuzhiyun if (crtc->transformPresent)
575*4882a593Smuzhiyun return FALSE;
576*4882a593Smuzhiyun }
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun return TRUE;
579*4882a593Smuzhiyun }
580*4882a593Smuzhiyun
581*4882a593Smuzhiyun static Bool
xf86_use_hw_cursor_argb(ScreenPtr screen,CursorPtr cursor)582*4882a593Smuzhiyun xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
583*4882a593Smuzhiyun {
584*4882a593Smuzhiyun ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
585*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
586*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
587*4882a593Smuzhiyun
588*4882a593Smuzhiyun if (!xf86_use_hw_cursor(screen, cursor))
589*4882a593Smuzhiyun return FALSE;
590*4882a593Smuzhiyun
591*4882a593Smuzhiyun /* Make sure ARGB support is available */
592*4882a593Smuzhiyun if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
593*4882a593Smuzhiyun return FALSE;
594*4882a593Smuzhiyun
595*4882a593Smuzhiyun return TRUE;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
598*4882a593Smuzhiyun static Bool
xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc,CursorPtr cursor)599*4882a593Smuzhiyun xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun ScrnInfoPtr scrn = crtc->scrn;
602*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
603*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
604*4882a593Smuzhiyun CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image;
605*4882a593Smuzhiyun CARD32 *cursor_source = (CARD32 *) cursor->bits->argb;
606*4882a593Smuzhiyun int x, y;
607*4882a593Smuzhiyun int xin, yin;
608*4882a593Smuzhiyun CARD32 bits;
609*4882a593Smuzhiyun int source_width = cursor->bits->width;
610*4882a593Smuzhiyun int source_height = cursor->bits->height;
611*4882a593Smuzhiyun int image_width = cursor_info->MaxWidth;
612*4882a593Smuzhiyun int image_height = cursor_info->MaxHeight;
613*4882a593Smuzhiyun const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
614*4882a593Smuzhiyun
615*4882a593Smuzhiyun for (y = 0; y < image_height; y++)
616*4882a593Smuzhiyun for (x = 0; x < image_width; x++) {
617*4882a593Smuzhiyun xf86_crtc_rotate_coord(rotation, image_width, image_height, x, y,
618*4882a593Smuzhiyun &xin, &yin);
619*4882a593Smuzhiyun if (xin < source_width && yin < source_height)
620*4882a593Smuzhiyun bits = cursor_source[yin * source_width + xin];
621*4882a593Smuzhiyun else
622*4882a593Smuzhiyun bits = 0;
623*4882a593Smuzhiyun cursor_image[y * image_width + x] = bits;
624*4882a593Smuzhiyun }
625*4882a593Smuzhiyun
626*4882a593Smuzhiyun return xf86_driver_load_cursor_argb(crtc, cursor_image);
627*4882a593Smuzhiyun }
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun static Bool
xf86_load_cursor_argb(ScrnInfoPtr scrn,CursorPtr cursor)630*4882a593Smuzhiyun xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
633*4882a593Smuzhiyun int c;
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun xf86_config->cursor = cursor;
636*4882a593Smuzhiyun for (c = 0; c < xf86_config->num_crtc; c++) {
637*4882a593Smuzhiyun xf86CrtcPtr crtc = xf86_config->crtc[c];
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun if (crtc->enabled)
640*4882a593Smuzhiyun if (!xf86_crtc_load_cursor_argb(crtc, cursor))
641*4882a593Smuzhiyun return FALSE;
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun return TRUE;
644*4882a593Smuzhiyun }
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun Bool
xf86_cursors_init(ScreenPtr screen,int max_width,int max_height,int flags)647*4882a593Smuzhiyun xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags)
648*4882a593Smuzhiyun {
649*4882a593Smuzhiyun ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
650*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
651*4882a593Smuzhiyun xf86CursorInfoPtr cursor_info;
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun cursor_info = xf86CreateCursorInfoRec();
654*4882a593Smuzhiyun if (!cursor_info)
655*4882a593Smuzhiyun return FALSE;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun xf86_config->cursor_image = malloc(max_width * max_height * 4);
658*4882a593Smuzhiyun
659*4882a593Smuzhiyun if (!xf86_config->cursor_image) {
660*4882a593Smuzhiyun xf86DestroyCursorInfoRec(cursor_info);
661*4882a593Smuzhiyun return FALSE;
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun xf86_config->cursor_info = cursor_info;
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun cursor_info->MaxWidth = max_width;
667*4882a593Smuzhiyun cursor_info->MaxHeight = max_height;
668*4882a593Smuzhiyun cursor_info->Flags = flags;
669*4882a593Smuzhiyun
670*4882a593Smuzhiyun cursor_info->SetCursorColors = xf86_set_cursor_colors;
671*4882a593Smuzhiyun cursor_info->SetCursorPosition = xf86_set_cursor_position;
672*4882a593Smuzhiyun cursor_info->LoadCursorImageCheck = xf86_load_cursor_image;
673*4882a593Smuzhiyun cursor_info->HideCursor = xf86_hide_cursors;
674*4882a593Smuzhiyun cursor_info->ShowCursorCheck = xf86_show_cursors;
675*4882a593Smuzhiyun cursor_info->UseHWCursor = xf86_use_hw_cursor;
676*4882a593Smuzhiyun if (flags & HARDWARE_CURSOR_ARGB) {
677*4882a593Smuzhiyun cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
678*4882a593Smuzhiyun cursor_info->LoadCursorARGBCheck = xf86_load_cursor_argb;
679*4882a593Smuzhiyun }
680*4882a593Smuzhiyun
681*4882a593Smuzhiyun xf86_hide_cursors(scrn);
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun return xf86InitCursor(screen, cursor_info);
684*4882a593Smuzhiyun }
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /**
687*4882a593Smuzhiyun * Clean up CRTC-based cursor code
688*4882a593Smuzhiyun */
689*4882a593Smuzhiyun void
xf86_cursors_fini(ScreenPtr screen)690*4882a593Smuzhiyun xf86_cursors_fini(ScreenPtr screen)
691*4882a593Smuzhiyun {
692*4882a593Smuzhiyun ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
693*4882a593Smuzhiyun xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun if (xf86_config->cursor_info) {
696*4882a593Smuzhiyun xf86DestroyCursorInfoRec(xf86_config->cursor_info);
697*4882a593Smuzhiyun xf86_config->cursor_info = NULL;
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun free(xf86_config->cursor_image);
700*4882a593Smuzhiyun xf86_config->cursor_image = NULL;
701*4882a593Smuzhiyun xf86_config->cursor = NULL;
702*4882a593Smuzhiyun }
703