135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2014 Red Hat, Inc. 335c4bbdfSmrg * 435c4bbdfSmrg * Permission is hereby granted, free of charge, to any person obtaining a 535c4bbdfSmrg * copy of this software and associated documentation files (the "Software"), 635c4bbdfSmrg * to deal in the Software without restriction, including without limitation 735c4bbdfSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 835c4bbdfSmrg * and/or sell copies of the Software, and to permit persons to whom the 935c4bbdfSmrg * Software is furnished to do so, subject to the following conditions: 1035c4bbdfSmrg * 1135c4bbdfSmrg * The above copyright notice and this permission notice (including the next 1235c4bbdfSmrg * paragraph) shall be included in all copies or substantial portions of the 1335c4bbdfSmrg * Software. 1435c4bbdfSmrg * 1535c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1635c4bbdfSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1735c4bbdfSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1835c4bbdfSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1935c4bbdfSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2035c4bbdfSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2135c4bbdfSmrg * DEALINGS IN THE SOFTWARE. 2235c4bbdfSmrg * 2335c4bbdfSmrg * Author: 2435c4bbdfSmrg * Adam Jackson <ajax@redhat.com> 2535c4bbdfSmrg */ 2635c4bbdfSmrg 271b5d61b8Smrg#ifdef HAVE_DIX_CONFIG_H 281b5d61b8Smrg#include <dix-config.h> 2935c4bbdfSmrg#endif 3035c4bbdfSmrg#include "ephyr.h" 3135c4bbdfSmrg#include "ephyrlog.h" 3235c4bbdfSmrg#include "hostx.h" 3335c4bbdfSmrg#include "cursorstr.h" 3435c4bbdfSmrg#include <xcb/render.h> 3535c4bbdfSmrg#include <xcb/xcb_renderutil.h> 3635c4bbdfSmrg 3735c4bbdfSmrgstatic DevPrivateKeyRec ephyrCursorPrivateKey; 3835c4bbdfSmrg 3935c4bbdfSmrgtypedef struct _ephyrCursor { 4035c4bbdfSmrg xcb_cursor_t cursor; 4135c4bbdfSmrg} ephyrCursorRec, *ephyrCursorPtr; 4235c4bbdfSmrg 4335c4bbdfSmrgstatic ephyrCursorPtr 4435c4bbdfSmrgephyrGetCursor(CursorPtr cursor) 4535c4bbdfSmrg{ 4635c4bbdfSmrg return dixGetPrivateAddr(&cursor->devPrivates, &ephyrCursorPrivateKey); 4735c4bbdfSmrg} 4835c4bbdfSmrg 4935c4bbdfSmrgstatic void 5035c4bbdfSmrgephyrRealizeCoreCursor(EphyrScrPriv *scr, CursorPtr cursor) 5135c4bbdfSmrg{ 5235c4bbdfSmrg ephyrCursorPtr hw = ephyrGetCursor(cursor); 5335c4bbdfSmrg xcb_connection_t *conn = hostx_get_xcbconn(); 5435c4bbdfSmrg xcb_pixmap_t source, mask; 5535c4bbdfSmrg xcb_image_t *image; 5635c4bbdfSmrg xcb_gcontext_t gc; 5735c4bbdfSmrg int w = cursor->bits->width, h = cursor->bits->height; 5835c4bbdfSmrg uint32_t gcmask = XCB_GC_FUNCTION | 5935c4bbdfSmrg XCB_GC_PLANE_MASK | 6035c4bbdfSmrg XCB_GC_FOREGROUND | 6135c4bbdfSmrg XCB_GC_BACKGROUND | 6235c4bbdfSmrg XCB_GC_CLIP_MASK; 6335c4bbdfSmrg uint32_t val[] = { 6435c4bbdfSmrg XCB_GX_COPY, /* function */ 6535c4bbdfSmrg ~0, /* planemask */ 6635c4bbdfSmrg 1L, /* foreground */ 6735c4bbdfSmrg 0L, /* background */ 6835c4bbdfSmrg None, /* clipmask */ 6935c4bbdfSmrg }; 7035c4bbdfSmrg 7135c4bbdfSmrg source = xcb_generate_id(conn); 7235c4bbdfSmrg mask = xcb_generate_id(conn); 7335c4bbdfSmrg xcb_create_pixmap(conn, 1, source, scr->win, w, h); 7435c4bbdfSmrg xcb_create_pixmap(conn, 1, mask, scr->win, w, h); 7535c4bbdfSmrg 7635c4bbdfSmrg gc = xcb_generate_id(conn); 7735c4bbdfSmrg xcb_create_gc(conn, gc, source, gcmask, val); 7835c4bbdfSmrg 7935c4bbdfSmrg image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_XY_BITMAP, 8035c4bbdfSmrg 1, NULL, ~0, NULL); 8135c4bbdfSmrg image->data = cursor->bits->source; 8235c4bbdfSmrg xcb_image_put(conn, source, gc, image, 0, 0, 0); 8335c4bbdfSmrg xcb_image_destroy(image); 8435c4bbdfSmrg 8535c4bbdfSmrg image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_XY_BITMAP, 8635c4bbdfSmrg 1, NULL, ~0, NULL); 8735c4bbdfSmrg image->data = cursor->bits->mask; 8835c4bbdfSmrg xcb_image_put(conn, mask, gc, image, 0, 0, 0); 8935c4bbdfSmrg xcb_image_destroy(image); 9035c4bbdfSmrg 9135c4bbdfSmrg xcb_free_gc(conn, gc); 9235c4bbdfSmrg 9335c4bbdfSmrg hw->cursor = xcb_generate_id(conn); 9435c4bbdfSmrg xcb_create_cursor(conn, hw->cursor, source, mask, 9535c4bbdfSmrg cursor->foreRed, cursor->foreGreen, cursor->foreBlue, 9635c4bbdfSmrg cursor->backRed, cursor->backGreen, cursor->backBlue, 9735c4bbdfSmrg cursor->bits->xhot, cursor->bits->yhot); 9835c4bbdfSmrg 9935c4bbdfSmrg xcb_free_pixmap(conn, source); 10035c4bbdfSmrg xcb_free_pixmap(conn, mask); 10135c4bbdfSmrg} 10235c4bbdfSmrg 10335c4bbdfSmrgstatic xcb_render_pictformat_t 10435c4bbdfSmrgget_argb_format(void) 10535c4bbdfSmrg{ 10635c4bbdfSmrg static xcb_render_pictformat_t format; 10735c4bbdfSmrg if (format == None) { 10835c4bbdfSmrg xcb_connection_t *conn = hostx_get_xcbconn(); 10935c4bbdfSmrg xcb_render_query_pict_formats_cookie_t cookie; 11035c4bbdfSmrg xcb_render_query_pict_formats_reply_t *formats; 11135c4bbdfSmrg 11235c4bbdfSmrg cookie = xcb_render_query_pict_formats(conn); 11335c4bbdfSmrg formats = 11435c4bbdfSmrg xcb_render_query_pict_formats_reply(conn, cookie, NULL); 11535c4bbdfSmrg 11635c4bbdfSmrg format = 11735c4bbdfSmrg xcb_render_util_find_standard_format(formats, 11835c4bbdfSmrg XCB_PICT_STANDARD_ARGB_32)->id; 11935c4bbdfSmrg 12035c4bbdfSmrg free(formats); 12135c4bbdfSmrg } 12235c4bbdfSmrg 12335c4bbdfSmrg return format; 12435c4bbdfSmrg} 12535c4bbdfSmrg 12635c4bbdfSmrgstatic void 12735c4bbdfSmrgephyrRealizeARGBCursor(EphyrScrPriv *scr, CursorPtr cursor) 12835c4bbdfSmrg{ 12935c4bbdfSmrg ephyrCursorPtr hw = ephyrGetCursor(cursor); 13035c4bbdfSmrg xcb_connection_t *conn = hostx_get_xcbconn(); 13135c4bbdfSmrg xcb_gcontext_t gc; 13235c4bbdfSmrg xcb_pixmap_t source; 13335c4bbdfSmrg xcb_render_picture_t picture; 13435c4bbdfSmrg xcb_image_t *image; 13535c4bbdfSmrg int w = cursor->bits->width, h = cursor->bits->height; 13635c4bbdfSmrg 13735c4bbdfSmrg /* dix' storage is PICT_a8r8g8b8 */ 13835c4bbdfSmrg source = xcb_generate_id(conn); 13935c4bbdfSmrg xcb_create_pixmap(conn, 32, source, scr->win, w, h); 14035c4bbdfSmrg 14135c4bbdfSmrg gc = xcb_generate_id(conn); 14235c4bbdfSmrg xcb_create_gc(conn, gc, source, 0, NULL); 14335c4bbdfSmrg image = xcb_image_create_native(conn, w, h, XCB_IMAGE_FORMAT_Z_PIXMAP, 14435c4bbdfSmrg 32, NULL, ~0, NULL); 14535c4bbdfSmrg image->data = (void *)cursor->bits->argb; 14635c4bbdfSmrg xcb_image_put(conn, source, gc, image, 0, 0, 0); 14735c4bbdfSmrg xcb_free_gc(conn, gc); 14835c4bbdfSmrg xcb_image_destroy(image); 14935c4bbdfSmrg 15035c4bbdfSmrg picture = xcb_generate_id(conn); 15135c4bbdfSmrg xcb_render_create_picture(conn, picture, source, get_argb_format(), 15235c4bbdfSmrg 0, NULL); 15335c4bbdfSmrg xcb_free_pixmap(conn, source); 15435c4bbdfSmrg 15535c4bbdfSmrg hw->cursor = xcb_generate_id(conn); 15635c4bbdfSmrg xcb_render_create_cursor(conn, hw->cursor, picture, 15735c4bbdfSmrg cursor->bits->xhot, cursor->bits->yhot); 15835c4bbdfSmrg 15935c4bbdfSmrg xcb_render_free_picture(conn, picture); 16035c4bbdfSmrg} 16135c4bbdfSmrg 16235c4bbdfSmrgstatic Bool 16335c4bbdfSmrgcan_argb_cursor(void) 16435c4bbdfSmrg{ 16535c4bbdfSmrg static const xcb_render_query_version_reply_t *v; 16635c4bbdfSmrg 16735c4bbdfSmrg if (!v) 16835c4bbdfSmrg v = xcb_render_util_query_version(hostx_get_xcbconn()); 16935c4bbdfSmrg 17035c4bbdfSmrg return v->major_version == 0 && v->minor_version >= 5; 17135c4bbdfSmrg} 17235c4bbdfSmrg 17335c4bbdfSmrgstatic Bool 17435c4bbdfSmrgephyrRealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor) 17535c4bbdfSmrg{ 17635c4bbdfSmrg KdScreenPriv(screen); 17735c4bbdfSmrg KdScreenInfo *kscr = pScreenPriv->screen; 17835c4bbdfSmrg EphyrScrPriv *scr = kscr->driver; 17935c4bbdfSmrg 18035c4bbdfSmrg if (cursor->bits->argb && can_argb_cursor()) 18135c4bbdfSmrg ephyrRealizeARGBCursor(scr, cursor); 18235c4bbdfSmrg else 18335c4bbdfSmrg { 18435c4bbdfSmrg ephyrRealizeCoreCursor(scr, cursor); 18535c4bbdfSmrg } 18635c4bbdfSmrg return TRUE; 18735c4bbdfSmrg} 18835c4bbdfSmrg 18935c4bbdfSmrgstatic Bool 19035c4bbdfSmrgephyrUnrealizeCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor) 19135c4bbdfSmrg{ 19235c4bbdfSmrg ephyrCursorPtr hw = ephyrGetCursor(cursor); 19335c4bbdfSmrg 19435c4bbdfSmrg if (hw->cursor) { 19535c4bbdfSmrg xcb_free_cursor(hostx_get_xcbconn(), hw->cursor); 19635c4bbdfSmrg hw->cursor = None; 19735c4bbdfSmrg } 19835c4bbdfSmrg 19935c4bbdfSmrg return TRUE; 20035c4bbdfSmrg} 20135c4bbdfSmrg 20235c4bbdfSmrgstatic void 20335c4bbdfSmrgephyrSetCursor(DeviceIntPtr dev, ScreenPtr screen, CursorPtr cursor, int x, 20435c4bbdfSmrg int y) 20535c4bbdfSmrg{ 20635c4bbdfSmrg KdScreenPriv(screen); 20735c4bbdfSmrg KdScreenInfo *kscr = pScreenPriv->screen; 20835c4bbdfSmrg EphyrScrPriv *scr = kscr->driver; 20935c4bbdfSmrg uint32_t attr = None; 21035c4bbdfSmrg 21135c4bbdfSmrg if (cursor) 21235c4bbdfSmrg attr = ephyrGetCursor(cursor)->cursor; 21335c4bbdfSmrg else 21435c4bbdfSmrg attr = hostx_get_empty_cursor(); 21535c4bbdfSmrg 21635c4bbdfSmrg xcb_change_window_attributes(hostx_get_xcbconn(), scr->win, 21735c4bbdfSmrg XCB_CW_CURSOR, &attr); 21835c4bbdfSmrg xcb_flush(hostx_get_xcbconn()); 21935c4bbdfSmrg} 22035c4bbdfSmrg 22135c4bbdfSmrgstatic void 22235c4bbdfSmrgephyrMoveCursor(DeviceIntPtr dev, ScreenPtr screen, int x, int y) 22335c4bbdfSmrg{ 22435c4bbdfSmrg} 22535c4bbdfSmrg 22635c4bbdfSmrgstatic Bool 22735c4bbdfSmrgephyrDeviceCursorInitialize(DeviceIntPtr dev, ScreenPtr screen) 22835c4bbdfSmrg{ 22935c4bbdfSmrg return TRUE; 23035c4bbdfSmrg} 23135c4bbdfSmrg 23235c4bbdfSmrgstatic void 23335c4bbdfSmrgephyrDeviceCursorCleanup(DeviceIntPtr dev, ScreenPtr screen) 23435c4bbdfSmrg{ 23535c4bbdfSmrg} 23635c4bbdfSmrg 23735c4bbdfSmrgmiPointerSpriteFuncRec EphyrPointerSpriteFuncs = { 23835c4bbdfSmrg ephyrRealizeCursor, 23935c4bbdfSmrg ephyrUnrealizeCursor, 24035c4bbdfSmrg ephyrSetCursor, 24135c4bbdfSmrg ephyrMoveCursor, 24235c4bbdfSmrg ephyrDeviceCursorInitialize, 24335c4bbdfSmrg ephyrDeviceCursorCleanup 24435c4bbdfSmrg}; 24535c4bbdfSmrg 24635c4bbdfSmrgBool 24735c4bbdfSmrgephyrCursorInit(ScreenPtr screen) 24835c4bbdfSmrg{ 249d9252ffbSmrg if (!dixRegisterPrivateKey(&ephyrCursorPrivateKey, PRIVATE_CURSOR, 25035c4bbdfSmrg sizeof(ephyrCursorRec))) 25135c4bbdfSmrg return FALSE; 25235c4bbdfSmrg 25335c4bbdfSmrg miPointerInitialize(screen, 25435c4bbdfSmrg &EphyrPointerSpriteFuncs, 25535c4bbdfSmrg &ephyrPointerScreenFuncs, FALSE); 25635c4bbdfSmrg 25735c4bbdfSmrg return TRUE; 25835c4bbdfSmrg} 259