xf86Cursors.c 19.9 KB
Newer Older
1 2
/*
 * Copyright © 2007 Keith Packard
3
 * Copyright © 2010-2011 Aaron Plattner
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting documentation, and
 * that the name of the copyright holders not be used in advertising or
 * publicity pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no representations
 * about the suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
 * OF THIS SOFTWARE.
 */

#ifdef HAVE_XORG_CONFIG_H
#include <xorg-config.h>
#else
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#endif

#include <stddef.h>
#include <string.h>
#include <stdio.h>

36
#include <X11/Xarch.h>
37 38 39 40 41
#include "xf86.h"
#include "xf86DDC.h"
#include "xf86Crtc.h"
#include "xf86Modes.h"
#include "xf86RandR12.h"
42
#include "xf86CursorPriv.h"
43
#include "X11/extensions/render.h"
Peter Hutterer's avatar
Peter Hutterer committed
44
#include "X11/extensions/dpmsconst.h"
45 46 47
#include "X11/Xatom.h"
#include "picturestr.h"
#include "cursorstr.h"
48
#include "inputstr.h"
49

50 51 52 53 54
/*
 * Returns the rotation being performed by the server.  If the driver indicates
 * that it's handling the screen transform, then this returns RR_Rotate_0.
 */
static Rotation
55
xf86_crtc_cursor_rotation(xf86CrtcPtr crtc)
56 57
{
    if (crtc->driverIsPerformingTransform)
58
        return RR_Rotate_0;
59 60 61
    return crtc->rotation;
}

62 63 64 65
/*
 * Given a screen coordinate, rotate back to a cursor source coordinate
 */
static void
66 67 68
xf86_crtc_rotate_coord(Rotation rotation,
                       int width,
                       int height, int x_dst, int y_dst, int *x_src, int *y_src)
69
{
Keith Packard's avatar
Keith Packard committed
70
    int t;
71

Keith Packard's avatar
Keith Packard committed
72 73
    switch (rotation & 0xf) {
    case RR_Rotate_0:
74
        break;
Keith Packard's avatar
Keith Packard committed
75
    case RR_Rotate_90:
76 77 78 79
        t = x_dst;
        x_dst = height - y_dst - 1;
        y_dst = t;
        break;
Keith Packard's avatar
Keith Packard committed
80
    case RR_Rotate_180:
81 82 83
        x_dst = width - x_dst - 1;
        y_dst = height - y_dst - 1;
        break;
Keith Packard's avatar
Keith Packard committed
84
    case RR_Rotate_270:
85 86 87 88
        t = x_dst;
        x_dst = y_dst;
        y_dst = width - t - 1;
        break;
Keith Packard's avatar
Keith Packard committed
89
    }
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;
Keith Packard's avatar
Keith Packard committed
94 95 96 97 98 99 100 101
    *x_src = x_dst;
    *y_src = y_dst;
}

/*
 * Given a cursor source  coordinate, rotate to a screen coordinate
 */
static void
102 103 104 105
xf86_crtc_rotate_coord_back(Rotation rotation,
                            int width,
                            int height,
                            int x_dst, int y_dst, int *x_src, int *y_src)
Keith Packard's avatar
Keith Packard committed
106 107
{
    int t;
108

Keith Packard's avatar
Keith Packard committed
109
    if (rotation & RR_Reflect_X)
110
        x_dst = width - x_dst - 1;
Keith Packard's avatar
Keith Packard committed
111
    if (rotation & RR_Reflect_Y)
112
        y_dst = height - y_dst - 1;
Keith Packard's avatar
Keith Packard committed
113

114 115
    switch (rotation & 0xf) {
    case RR_Rotate_0:
116
        break;
117
    case RR_Rotate_90:
118 119 120 121
        t = x_dst;
        x_dst = y_dst;
        y_dst = width - t - 1;
        break;
122
    case RR_Rotate_180:
123 124 125
        x_dst = width - x_dst - 1;
        y_dst = height - y_dst - 1;
        break;
126
    case RR_Rotate_270:
127 128 129 130
        t = x_dst;
        x_dst = height - y_dst - 1;
        y_dst = t;
        break;
131
    }
Keith Packard's avatar
Keith Packard committed
132 133
    *x_src = x_dst;
    *y_src = y_dst;
134 135
}

136 137 138 139 140
struct cursor_bit {
    CARD8 *byte;
    char bitpos;
};

141 142 143
/*
 * Convert an x coordinate to a position within the cursor bitmap
 */
144
static struct cursor_bit
145 146
cursor_bitpos(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y,
              Bool mask)
147
{
148 149
    const int flags = cursor_info->Flags;
    const Bool interleaved =
150 151 152 153 154
        ! !(flags & (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
                     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
                     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16 |
                     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32 |
                     HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64));
155 156 157 158 159 160 161 162
    const int width = cursor_info->MaxWidth;
    const int height = cursor_info->MaxHeight;
    const int stride = interleaved ? width / 4 : width / 8;

    struct cursor_bit ret;

    image += y * stride;

163
    if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
164
        mask = !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 169
        (X_BYTE_ORDER == X_BIG_ENDIAN))
        x = (x & ~7) | (7 - (x & 7));
170
    if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1)
171
        x = (x << 1) + mask;
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);
180
    else if (mask)
181
        image += stride * height;
182 183 184 185 186

    ret.byte = image + (x / 8);
    ret.bitpos = x & 7;

    return ret;
187 188 189 190 191 192
}

/*
 * Fetch one bit from a cursor bitmap
 */
static CARD8
193
get_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
194
{
195
    struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask);
196

197
    return (*bit.byte >> bit.bitpos) & 1;
198 199 200 201 202 203
}

/*
 * Set one bit in a cursor bitmap
 */
static void
204
set_bit(CARD8 *image, xf86CursorInfoPtr cursor_info, int x, int y, Bool mask)
205
{
206
    struct cursor_bit bit = cursor_bitpos(image, cursor_info, x, y, mask);
207

208
    *bit.byte |= 1 << bit.bitpos;
209
}
210

211 212 213 214
/*
 * Load a two color cursor into a driver that supports only ARGB cursors
 */
static void
215
xf86_crtc_convert_cursor_to_argb(xf86CrtcPtr crtc, unsigned char *src)
216
{
217 218 219 220 221 222 223 224 225
    ScrnInfoPtr scrn = crtc->scrn;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image;
    int x, y;
    int xin, yin;
    int flags = cursor_info->Flags;
    CARD32 bits;
    const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
226 227 228 229 230 231

#ifdef ARGB_CURSOR
    crtc->cursor_argb = FALSE;
#endif

    for (y = 0; y < cursor_info->MaxHeight; y++)
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
        for (x = 0; x < cursor_info->MaxWidth; x++) {
            xf86_crtc_rotate_coord(rotation,
                                   cursor_info->MaxWidth,
                                   cursor_info->MaxHeight, x, y, &xin, &yin);
            if (get_bit(src, cursor_info, xin, yin, TRUE) ==
                ((flags & HARDWARE_CURSOR_INVERT_MASK) == 0)) {
                if (get_bit(src, cursor_info, xin, yin, FALSE))
                    bits = xf86_config->cursor_fg;
                else
                    bits = xf86_config->cursor_bg;
            }
            else
                bits = 0;
            cursor_image[y * cursor_info->MaxWidth + x] = bits;
        }
    crtc->funcs->load_cursor_argb(crtc, cursor_image);
248 249 250 251 252 253
}

/*
 * Set the colors for a two-color cursor (ignore for ARGB cursors)
 */
static void
254
xf86_set_cursor_colors(ScrnInfoPtr scrn, int bg, int fg)
255
{
256 257 258 259 260
    ScreenPtr screen = scrn->pScreen;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    CursorPtr cursor = xf86_config->cursor;
    int c;
    CARD8 *bits = cursor ?
261
        dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey, screen)
262
        : NULL;
263 264 265 266

    /* Save ARGB versions of these colors */
    xf86_config->cursor_fg = (CARD32) fg | 0xff000000;
    xf86_config->cursor_bg = (CARD32) bg | 0xff000000;
267 268 269 270 271 272 273 274 275 276

    for (c = 0; c < xf86_config->num_crtc; c++) {
        xf86CrtcPtr crtc = xf86_config->crtc[c];

        if (crtc->enabled && !crtc->cursor_argb) {
            if (crtc->funcs->load_cursor_image)
                crtc->funcs->set_cursor_colors(crtc, bg, fg);
            else if (bits)
                xf86_crtc_convert_cursor_to_argb(crtc, bits);
        }
277 278 279 280
    }
}

static void
281
xf86_crtc_hide_cursor(xf86CrtcPtr crtc)
282
{
283 284 285
    if (crtc->cursor_shown) {
        crtc->funcs->hide_cursor(crtc);
        crtc->cursor_shown = FALSE;
286 287 288
    }
}

289
void
290
xf86_hide_cursors(ScrnInfoPtr scrn)
291
{
292 293
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    int c;
294 295

    xf86_config->cursor_on = FALSE;
296 297
    for (c = 0; c < xf86_config->num_crtc; c++) {
        xf86CrtcPtr crtc = xf86_config->crtc[c];
298

299 300
        if (crtc->enabled)
            xf86_crtc_hide_cursor(crtc);
301 302
    }
}
303

304
static void
305
xf86_crtc_show_cursor(xf86CrtcPtr crtc)
306
{
307 308 309
    if (!crtc->cursor_shown && crtc->cursor_in_range) {
        crtc->funcs->show_cursor(crtc);
        crtc->cursor_shown = TRUE;
310 311 312
    }
}

313
void
314
xf86_show_cursors(ScrnInfoPtr scrn)
315
{
316 317
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    int c;
318 319

    xf86_config->cursor_on = TRUE;
320 321
    for (c = 0; c < xf86_config->num_crtc; c++) {
        xf86CrtcPtr crtc = xf86_config->crtc[c];
322

323 324
        if (crtc->enabled)
            xf86_crtc_show_cursor(crtc);
325 326
    }
}
327

328 329
void
xf86CrtcTransformCursorPos(xf86CrtcPtr crtc, int *x, int *y)
330 331 332 333 334 335
{
    ScrnInfoPtr scrn = crtc->scrn;
    ScreenPtr screen = scrn->pScreen;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    xf86CursorScreenPtr ScreenPriv =
336 337
        (xf86CursorScreenPtr) dixLookupPrivate(&screen->devPrivates,
                                               xf86CursorScreenKey);
338 339 340 341 342 343
    struct pict_f_vector v;
    int dx, dy;

    v.v[0] = (*x + ScreenPriv->HotX) + 0.5;
    v.v[1] = (*y + ScreenPriv->HotY) + 0.5;
    v.v[2] = 1;
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 */
346 347
    *x = floor(v.v[0]);
    *y = floor(v.v[1]);
348 349 350
    /*
     * Transform position of cursor upper left corner
     */
351 352 353
    xf86_crtc_rotate_coord_back(crtc->rotation, cursor_info->MaxWidth,
                                cursor_info->MaxHeight, ScreenPriv->HotX,
                                ScreenPriv->HotY, &dx, &dy);
354 355 356 357
    *x -= dx;
    *y -= dy;
}

358
static void
359
xf86_crtc_set_cursor_position(xf86CrtcPtr crtc, int x, int y)
360
{
361 362 363 364 365
    ScrnInfoPtr scrn = crtc->scrn;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    DisplayModePtr mode = &crtc->mode;
    Bool in_range;
366 367

    /*
Keith Packard's avatar
Keith Packard committed
368
     * Transform position of cursor on screen
369
     */
370
    if (crtc->transform_in_use && !crtc->driverIsPerformingTransform)
371 372 373 374
        xf86CrtcTransformCursorPos(crtc, &x, &y);
    else {
        x -= crtc->x;
        y -= crtc->y;
375 376 377 378 379 380 381
    }

    /*
     * Disable the cursor when it is outside the viewport
     */
    in_range = TRUE;
    if (x >= mode->HDisplay || y >= mode->VDisplay ||
382 383 384 385
        x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) {
        in_range = FALSE;
        x = 0;
        y = 0;
386 387 388
    }

    crtc->cursor_in_range = in_range;
389 390 391 392

    if (in_range) {
        crtc->funcs->set_cursor_position(crtc, x, y);
        xf86_crtc_show_cursor(crtc);
393 394
    }
    else
395
        xf86_crtc_hide_cursor(crtc);
396 397 398
}

static void
399
xf86_set_cursor_position(ScrnInfoPtr scrn, int x, int y)
400
{
401 402
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    int c;
403 404 405 406

    /* undo what xf86HWCurs did to the coordinates */
    x += scrn->frameX0;
    y += scrn->frameY0;
407 408
    for (c = 0; c < xf86_config->num_crtc; c++) {
        xf86CrtcPtr crtc = xf86_config->crtc[c];
409

410 411
        if (crtc->enabled)
            xf86_crtc_set_cursor_position(crtc, x, y);
412 413
    }
}
414

415 416 417 418
/*
 * Load a two-color cursor into a crtc, performing rotation as needed
 */
static void
419
xf86_crtc_load_cursor_image(xf86CrtcPtr crtc, CARD8 *src)
420
{
421 422 423 424 425
    ScrnInfoPtr scrn = crtc->scrn;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    CARD8 *cursor_image;
    const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
426 427 428 429 430

#ifdef ARGB_CURSOR
    crtc->cursor_argb = FALSE;
#endif

431
    if (rotation == RR_Rotate_0)
432 433
        cursor_image = src;
    else {
434
        int x, y;
435 436 437 438 439 440
        int xin, yin;
        int stride = cursor_info->MaxWidth >> 2;

        cursor_image = xf86_config->cursor_image;
        memset(cursor_image, 0, cursor_info->MaxHeight * stride);

441
        for (y = 0; y < cursor_info->MaxHeight; y++)
442 443 444 445 446 447 448 449 450 451
            for (x = 0; x < cursor_info->MaxWidth; x++) {
                xf86_crtc_rotate_coord(rotation,
                                       cursor_info->MaxWidth,
                                       cursor_info->MaxHeight,
                                       x, y, &xin, &yin);
                if (get_bit(src, cursor_info, xin, yin, FALSE))
                    set_bit(cursor_image, cursor_info, x, y, FALSE);
                if (get_bit(src, cursor_info, xin, yin, TRUE))
                    set_bit(cursor_image, cursor_info, x, y, TRUE);
            }
452
    }
453
    crtc->funcs->load_cursor_image(crtc, cursor_image);
454
}
455

456 457 458 459
/*
 * Load a cursor image into all active CRTCs
 */
static void
460
xf86_load_cursor_image(ScrnInfoPtr scrn, unsigned char *src)
461
{
462 463 464 465 466 467 468 469 470 471 472 473
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    int c;

    for (c = 0; c < xf86_config->num_crtc; c++) {
        xf86CrtcPtr crtc = xf86_config->crtc[c];

        if (crtc->enabled) {
            if (crtc->funcs->load_cursor_image)
                xf86_crtc_load_cursor_image(crtc, src);
            else if (crtc->funcs->load_cursor_argb)
                xf86_crtc_convert_cursor_to_argb(crtc, src);
        }
474 475 476 477
    }
}

static Bool
478
xf86_use_hw_cursor(ScreenPtr screen, CursorPtr cursor)
479
{
480
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
481 482
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    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
    if (cursor->bits->width > cursor_info->MaxWidth ||
490 491
        cursor->bits->height > cursor_info->MaxHeight)
        return FALSE;
492 493 494 495 496

    return TRUE;
}

static Bool
497
xf86_use_hw_cursor_argb(ScreenPtr screen, CursorPtr cursor)
498
{
499
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
500 501 502
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;

503
    ++cursor->refcnt;
504
    if (xf86_config->cursor)
505
        FreeCursor(xf86_config->cursor, None);
506
    xf86_config->cursor = cursor;
507

508 509
    /* Make sure ARGB support is available */
    if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
510 511
        return FALSE;

512
    if (cursor->bits->width > cursor_info->MaxWidth ||
513 514
        cursor->bits->height > cursor_info->MaxHeight)
        return FALSE;
515 516 517 518 519

    return TRUE;
}

static void
520
xf86_crtc_load_cursor_argb(xf86CrtcPtr crtc, CursorPtr cursor)
521
{
522 523 524 525 526 527 528 529 530 531 532 533 534
    ScrnInfoPtr scrn = crtc->scrn;
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info = xf86_config->cursor_info;
    CARD32 *cursor_image = (CARD32 *) xf86_config->cursor_image;
    CARD32 *cursor_source = (CARD32 *) cursor->bits->argb;
    int x, y;
    int xin, yin;
    CARD32 bits;
    int source_width = cursor->bits->width;
    int source_height = cursor->bits->height;
    int image_width = cursor_info->MaxWidth;
    int image_height = cursor_info->MaxHeight;
    const Rotation rotation = xf86_crtc_cursor_rotation(crtc);
535

536
    for (y = 0; y < image_height; y++)
537 538 539 540 541 542 543 544 545 546 547
        for (x = 0; x < image_width; x++) {
            xf86_crtc_rotate_coord(rotation, image_width, image_height, x, y,
                                   &xin, &yin);
            if (xin < source_width && yin < source_height)
                bits = cursor_source[yin * source_width + xin];
            else
                bits = 0;
            cursor_image[y * image_width + x] = bits;
        }

    crtc->funcs->load_cursor_argb(crtc, cursor_image);
548 549 550
}

static void
551
xf86_load_cursor_argb(ScrnInfoPtr scrn, CursorPtr cursor)
552
{
553 554
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    int c;
555

556 557
    for (c = 0; c < xf86_config->num_crtc; c++) {
        xf86CrtcPtr crtc = xf86_config->crtc[c];
558

559 560
        if (crtc->enabled)
            xf86_crtc_load_cursor_argb(crtc, cursor);
561 562 563
    }
}

564
Bool
565
xf86_cursors_init(ScreenPtr screen, int max_width, int max_height, int flags)
566
{
567
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
568 569
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
    xf86CursorInfoPtr cursor_info;
570 571 572

    cursor_info = xf86CreateCursorInfoRec();
    if (!cursor_info)
573
        return FALSE;
574

575
    xf86_config->cursor_image = malloc(max_width * max_height * 4);
576

577 578 579
    if (!xf86_config->cursor_image) {
        xf86DestroyCursorInfoRec(cursor_info);
        return FALSE;
580
    }
581

582 583 584 585 586 587 588 589 590 591 592 593 594
    xf86_config->cursor_info = cursor_info;

    cursor_info->MaxWidth = max_width;
    cursor_info->MaxHeight = max_height;
    cursor_info->Flags = flags;

    cursor_info->SetCursorColors = xf86_set_cursor_colors;
    cursor_info->SetCursorPosition = xf86_set_cursor_position;
    cursor_info->LoadCursorImage = xf86_load_cursor_image;
    cursor_info->HideCursor = xf86_hide_cursors;
    cursor_info->ShowCursor = xf86_show_cursors;
    cursor_info->UseHWCursor = xf86_use_hw_cursor;
#ifdef ARGB_CURSOR
595 596 597
    if (flags & HARDWARE_CURSOR_ARGB) {
        cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
        cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
598 599
    }
#endif
600

601
    xf86_config->cursor = NULL;
602 603 604
    xf86_hide_cursors(scrn);

    return xf86InitCursor(screen, cursor_info);
605 606 607 608 609 610 611 612
}

/**
 * Called when anything on the screen is reconfigured.
 *
 * Reloads cursor images as needed, then adjusts cursor positions
 */

613
void
614
xf86_reload_cursors(ScreenPtr screen)
615
{
616 617 618 619 620
    ScrnInfoPtr scrn;
    xf86CrtcConfigPtr xf86_config;
    xf86CursorInfoPtr cursor_info;
    CursorPtr cursor;
    int x, y;
621
    xf86CursorScreenPtr cursor_screen_priv;
622

623 624 625 626
    /* initial mode setting will not have set a screen yet.
       May be called before the devices are initialised.
     */
    if (!screen || !inputInfo.pointer)
627
        return;
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)
632
        return;
633

634
    scrn = xf86ScreenToScrn(screen);
635 636 637 638 639
    xf86_config = XF86_CRTC_CONFIG_PTR(scrn);

    /* make sure the cursor code has been initialized */
    cursor_info = xf86_config->cursor_info;
    if (!cursor_info)
640
        return;
641

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);
646

647 648 649 650
    if (cursor) {
        void *src =
            dixLookupScreenPrivate(&cursor->devPrivates, CursorScreenKey,
                                   screen);
651
#ifdef ARGB_CURSOR
652 653 654
        if (cursor->bits->argb && cursor_info->LoadCursorARGB)
            (*cursor_info->LoadCursorARGB) (scrn, cursor);
        else if (src)
655
#endif
656
            (*cursor_info->LoadCursorImage) (scrn, src);
657

658 659 660
        x += scrn->frameX0 + cursor_screen_priv->HotX;
        y += scrn->frameY0 + cursor_screen_priv->HotY;
        (*cursor_info->SetCursorPosition) (scrn, x, y);
661 662 663 664 665 666
    }
}

/**
 * Clean up CRTC-based cursor code
 */
667
void
668
xf86_cursors_fini(ScreenPtr screen)
669
{
670
    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
671 672 673 674 675
    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);

    if (xf86_config->cursor_info) {
        xf86DestroyCursorInfoRec(xf86_config->cursor_info);
        xf86_config->cursor_info = NULL;
676
    }
677 678
    free(xf86_config->cursor_image);
    xf86_config->cursor_image = NULL;
679 680 681
    if (xf86_config->cursor) {
        FreeCursor(xf86_config->cursor, None);
        xf86_config->cursor = NULL;
682
    }
683
}