xserver

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

ephyrcursor.c (7708B)


      1 /*
      2  * Copyright © 2014 Red Hat, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  *
     23  * Author:
     24  *      Adam Jackson <ajax@redhat.com>
     25  */
     26 
     27 #ifdef HAVE_DIX_CONFIG_H
     28 #include <dix-config.h>
     29 #endif
     30 #include "ephyr.h"
     31 #include "ephyrlog.h"
     32 #include "hostx.h"
     33 #include "cursorstr.h"
     34 #include <xcb/render.h>
     35 #include <xcb/xcb_renderutil.h>
     36 
     37 static DevPrivateKeyRec ephyrCursorPrivateKey;
     38 
     39 typedef struct _ephyrCursor {
     40     xcb_cursor_t cursor;
     41 } ephyrCursorRec, *ephyrCursorPtr;
     42 
     43 static ephyrCursorPtr
     44 ephyrGetCursor(CursorPtr cursor)
     45 {
     46     return dixGetPrivateAddr(&cursor->devPrivates, &ephyrCursorPrivateKey);
     47 }
     48 
     49 static void
     50 ephyrRealizeCoreCursor(EphyrScrPriv *scr, CursorPtr cursor)
     51 {
     52     ephyrCursorPtr hw = ephyrGetCursor(cursor);
     53     xcb_connection_t *conn = hostx_get_xcbconn();
     54     xcb_pixmap_t source, mask;
     55     xcb_image_t *image;
     56     xcb_gcontext_t gc;
     57     int w = cursor->bits->width, h = cursor->bits->height;
     58     uint32_t gcmask = XCB_GC_FUNCTION |
     59                       XCB_GC_PLANE_MASK |
     60                       XCB_GC_FOREGROUND |
     61                       XCB_GC_BACKGROUND |
     62                       XCB_GC_CLIP_MASK;
     63     uint32_t val[] = {
     64         XCB_GX_COPY,    /* function */
     65         ~0,             /* planemask */
     66         1L,             /* foreground */
     67         0L,             /* background */
     68         None,           /* clipmask */
     69     };
     70 
     71     source = xcb_generate_id(conn);
     72     mask = xcb_generate_id(conn);
     73     xcb_create_pixmap(conn, 1, source, scr->win, w, h);
     74     xcb_create_pixmap(conn, 1, mask, scr->win, w, h);
     75 
     76     gc = xcb_generate_id(conn);
     77     xcb_create_gc(conn, gc, source, gcmask, val);
     78 
     79     image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_XY_BITMAP,
     80                                     1, NULL, ~0, NULL);
     81     image->data = cursor->bits->source;
     82     xcb_image_put(conn, source, gc, image, 0, 0, 0);
     83     xcb_image_destroy(image);
     84 
     85     image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_XY_BITMAP,
     86                                     1, NULL, ~0, NULL);
     87     image->data = cursor->bits->mask;
     88     xcb_image_put(conn, mask, gc, image, 0, 0, 0);
     89     xcb_image_destroy(image);
     90 
     91     xcb_free_gc(conn, gc);
     92 
     93     hw->cursor = xcb_generate_id(conn);
     94     xcb_create_cursor(conn, hw->cursor, source, mask,
     95                       cursor->foreRed, cursor->foreGreen, cursor->foreBlue,
     96                       cursor->backRed, cursor->backGreen, cursor->backBlue,
     97                       cursor->bits->xhot, cursor->bits->yhot);
     98 
     99     xcb_free_pixmap(conn, source);
    100     xcb_free_pixmap(conn, mask);
    101 }
    102 
    103 static xcb_render_pictformat_t
    104 get_argb_format(void)
    105 {
    106     static xcb_render_pictformat_t format;
    107     if (format == None) {
    108         xcb_connection_t *conn = hostx_get_xcbconn();
    109         xcb_render_query_pict_formats_cookie_t cookie;
    110         xcb_render_query_pict_formats_reply_t *formats;
    111 
    112         cookie = xcb_render_query_pict_formats(conn);
    113         formats =
    114             xcb_render_query_pict_formats_reply(conn, cookie, NULL);
    115 
    116         format =
    117             xcb_render_util_find_standard_format(formats,
    118                                                  XCB_PICT_STANDARD_ARGB_32)->id;
    119 
    120         free(formats);
    121     }
    122 
    123     return format;
    124 }
    125 
    126 static void
    127 ephyrRealizeARGBCursor(EphyrScrPriv *scr, CursorPtr cursor)
    128 {
    129     ephyrCursorPtr hw = ephyrGetCursor(cursor);
    130     xcb_connection_t *conn = hostx_get_xcbconn();
    131     xcb_gcontext_t gc;
    132     xcb_pixmap_t source;
    133     xcb_render_picture_t picture;
    134     xcb_image_t *image;
    135     int w = cursor->bits->width, h = cursor->bits->height;
    136 
    137     /* dix' storage is PICT_a8r8g8b8 */
    138     source = xcb_generate_id(conn);
    139     xcb_create_pixmap(conn, 32, source, scr->win, w, h);
    140 
    141     gc = xcb_generate_id(conn);
    142     xcb_create_gc(conn, gc, source, 0, NULL);
    143     image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP,
    144                                     32, NULL, ~0, NULL);
    145     image->data = (void *)cursor->bits->argb;
    146     xcb_image_put(conn, source, gc, image, 0, 0, 0);
    147     xcb_free_gc(conn, gc);
    148     xcb_image_destroy(image);
    149 
    150     picture = xcb_generate_id(conn);
    151     xcb_render_create_picture(conn, picture, source, get_argb_format(),
    152                               0, NULL);
    153     xcb_free_pixmap(conn, source);
    154 
    155     hw->cursor = xcb_generate_id(conn);
    156     xcb_render_create_cursor(conn, hw->cursor, picture,
    157                              cursor->bits->xhot, cursor->bits->yhot);
    158 
    159     xcb_render_free_picture(conn, picture);
    160 }
    161 
    162 static Bool
    163 can_argb_cursor(void)
    164 {
    165     static const xcb_render_query_version_reply_t *v;
    166 
    167     if (!v)
    168         v = xcb_render_util_query_version(hostx_get_xcbconn());
    169 
    170     return v->major_version == 0 && v->minor_version >= 5;
    171 }
    172 
    173 static Bool
    174 ephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor)
    175 {
    176     KdScreenPriv(screen);
    177     KdScreenInfo *kscr = pScreenPriv->screen;
    178     EphyrScrPriv *scr = kscr->driver;
    179 
    180     if (cursor->bits->argb && can_argb_cursor())
    181         ephyrRealizeARGBCursor(scr, cursor);
    182     else
    183     {
    184         ephyrRealizeCoreCursor(scr, cursor);
    185     }
    186     return TRUE;
    187 }
    188 
    189 static Bool
    190 ephyrUnrealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor)
    191 {
    192     ephyrCursorPtr hw = ephyrGetCursor(cursor);
    193 
    194     if (hw->cursor) {
    195         xcb_free_cursor(hostx_get_xcbconn(), hw->cursor);
    196         hw->cursor = None;
    197     }
    198 
    199     return TRUE;
    200 }
    201 
    202 static void
    203 ephyrSetCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor, int x,
    204                int y)
    205 {
    206     KdScreenPriv(screen);
    207     KdScreenInfo *kscr = pScreenPriv->screen;
    208     EphyrScrPriv *scr = kscr->driver;
    209     uint32_t attr = None;
    210 
    211     if (cursor)
    212         attr = ephyrGetCursor(cursor)->cursor;
    213     else
    214         attr = hostx_get_empty_cursor();
    215 
    216     xcb_change_window_attributes(hostx_get_xcbconn(), scr->win,
    217                                  XCB_CW_CURSOR, &attr);
    218     xcb_flush(hostx_get_xcbconn());
    219 }
    220 
    221 static void
    222 ephyrMoveCursor(DeviceIntPtr dev, ScreenPtr screen, int x, int y)
    223 {
    224 }
    225 
    226 static Bool
    227 ephyrDeviceCursorInitialize(DeviceIntPtr dev, ScreenPtr screen)
    228 {
    229     return TRUE;
    230 }
    231 
    232 static void
    233 ephyrDeviceCursorCleanup(DeviceIntPtr dev, ScreenPtr screen)
    234 {
    235 }
    236 
    237 miPointerSpriteFuncRec EphyrPointerSpriteFuncs = {
    238     ephyrRealizeCursor,
    239     ephyrUnrealizeCursor,
    240     ephyrSetCursor,
    241     ephyrMoveCursor,
    242     ephyrDeviceCursorInitialize,
    243     ephyrDeviceCursorCleanup
    244 };
    245 
    246 Bool
    247 ephyrCursorInit(ScreenPtr screen)
    248 {
    249     if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR_BITS,
    250                                sizeof(ephyrCursorRec)))
    251         return FALSE;
    252 
    253     miPointerInitialize(screen,
    254                         &EphyrPointerSpriteFuncs,
    255                         &ephyrPointerScreenFuncs, FALSE);
    256 
    257     return TRUE;
    258 }