xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xf86Cursors.c (20923B)


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