1/* 2 * Copyright 2009, 2010 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 * on the rights to use, copy, modify, merge, publish, distribute, sub 8 * license, and/or sell copies of the Software, and to permit persons to whom 9 * the 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 NON-INFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23/** \file qxl_cursor.c 24 * \author Søren Sandmann <sandmann@redhat.com> 25 */ 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif 29 30#include <string.h> 31#include "qxl.h" 32#include <cursorstr.h> 33 34static void 35push_cursor (qxl_screen_t *qxl, struct qxl_bo *cursor_bo) 36{ 37 qxl->bo_funcs->write_command (qxl, QXL_CMD_CURSOR, cursor_bo); 38} 39 40static struct qxl_bo * 41qxl_alloc_cursor_cmd(qxl_screen_t *qxl) 42{ 43 struct qxl_bo *bo = qxl->bo_funcs->cmd_alloc (qxl, sizeof(struct QXLCursorCmd), "cursor command"); 44 struct QXLCursorCmd *cmd = qxl->bo_funcs->bo_map(bo); 45 46 cmd->release_info.id = pointer_to_u64 (bo) | 1; 47 48 qxl->bo_funcs->bo_unmap(bo); 49 return bo; 50} 51 52static void 53qxl_set_cursor_position(ScrnInfoPtr pScrn, int x, int y) 54{ 55 qxl_screen_t *qxl = pScrn->driverPrivate; 56 struct qxl_bo *cmd_bo = qxl_alloc_cursor_cmd(qxl); 57 struct QXLCursorCmd *cmd = qxl->bo_funcs->bo_map(cmd_bo); 58 59 qxl->cur_x = x; 60 qxl->cur_y = y; 61 62 cmd->type = QXL_CURSOR_MOVE; 63 cmd->u.position.x = qxl->cur_x + qxl->hot_x; 64 cmd->u.position.y = qxl->cur_y + qxl->hot_y; 65 66 qxl->bo_funcs->bo_unmap(cmd_bo); 67 push_cursor(qxl, cmd_bo); 68} 69 70static void 71qxl_load_cursor_image(ScrnInfoPtr pScrn, unsigned char *bits) 72{ 73} 74 75static void 76qxl_set_cursor_colors(ScrnInfoPtr pScrn, int bg, int fg) 77{ 78 /* Should not be called since UseHWCursor returned FALSE */ 79} 80 81static void 82qxl_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs) 83{ 84 qxl_screen_t *qxl = pScrn->driverPrivate; 85 int w = pCurs->bits->width; 86 int h = pCurs->bits->height; 87 int size = w * h * sizeof (CARD32); 88 89 struct qxl_bo *cmd_bo = qxl_alloc_cursor_cmd(qxl); 90 struct QXLCursorCmd *cmd; 91 struct qxl_bo *cursor_bo = qxl->bo_funcs->bo_alloc(qxl, sizeof(struct QXLCursor) + size, "cursor data"); 92 struct QXLCursor *cursor = qxl->bo_funcs->bo_map(cursor_bo); 93 94 cursor->header.unique = 0; 95 cursor->header.type = SPICE_CURSOR_TYPE_ALPHA; 96 cursor->header.width = w; 97 cursor->header.height = h; 98 /* I wonder if we can just tell the client that the hotspot is 0, 0 99 * always? The coordinates we are getting from X are for 0, 0 anyway, 100 * so the question is if the client uses the hotspot for anything else? 101 */ 102 cursor->header.hot_spot_x = pCurs->bits->xhot; 103 cursor->header.hot_spot_y = pCurs->bits->yhot; 104 105 cursor->data_size = size; 106 107 cursor->chunk.next_chunk = 0; 108 cursor->chunk.prev_chunk = 0; 109 cursor->chunk.data_size = size; 110 111 memcpy (cursor->chunk.data, pCurs->bits->argb, size); 112 113#if 0 114 int i, j; 115 for (j = 0; j < h; ++j) 116 { 117 for (i = 0; i < w; ++i) 118 { 119 ErrorF ("%c", (pCurs->bits->argb[j * w + i] & 0xff000000) == 0xff000000? '#' : '.'); 120 } 121 122 ErrorF ("\n"); 123 } 124#endif 125 126 qxl->bo_funcs->bo_unmap(cursor_bo); 127 128 qxl->hot_x = pCurs->bits->xhot; 129 qxl->hot_y = pCurs->bits->yhot; 130 131 cmd = qxl->bo_funcs->bo_map(cmd_bo); 132 cmd->type = QXL_CURSOR_SET; 133 cmd->u.set.position.x = qxl->cur_x + qxl->hot_x; 134 cmd->u.set.position.y = qxl->cur_y + qxl->hot_y; 135 qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(struct QXLCursorCmd, u.set.shape), cmd_bo, cursor_bo); 136 137 cmd->u.set.visible = TRUE; 138 qxl->bo_funcs->bo_unmap(cmd_bo); 139 140 push_cursor(qxl, cmd_bo); 141 qxl->bo_funcs->bo_decref(qxl, cursor_bo); 142} 143 144static Bool 145qxl_use_hw_cursor (ScreenPtr pScrn, CursorPtr pCurs) 146{ 147 /* Old-school bitmap cursors are not 148 * hardware accelerated for now. 149 */ 150 return FALSE; 151} 152 153static Bool 154qxl_use_hw_cursorARGB (ScreenPtr pScrn, CursorPtr pCurs) 155{ 156 return TRUE; 157} 158 159static void 160qxl_hide_cursor(ScrnInfoPtr pScrn) 161{ 162 qxl_screen_t *qxl = pScrn->driverPrivate; 163 struct qxl_bo *cmd_bo = qxl_alloc_cursor_cmd(qxl); 164 struct QXLCursorCmd *cursor = qxl->bo_funcs->bo_map(cmd_bo); 165 166 cursor->type = QXL_CURSOR_HIDE; 167 168 qxl->bo_funcs->bo_unmap(cmd_bo); 169 push_cursor(qxl, cmd_bo); 170} 171 172static void 173qxl_show_cursor(ScrnInfoPtr pScrn) 174{ 175 /* 176 * slightly hacky, but there's no QXL_CURSOR_SHOW. Could maybe do 177 * QXL_CURSOR_SET? 178 */ 179 qxl_screen_t *qxl = pScrn->driverPrivate; 180 181 qxl_set_cursor_position(pScrn, qxl->cur_x, qxl->cur_y); 182} 183 184hidden void 185qxl_cursor_init(ScreenPtr pScreen) 186{ 187 xf86CursorInfoPtr cursor; 188 189 cursor = calloc(1, sizeof(xf86CursorInfoRec)); 190 if (!cursor) 191 return; 192 193 cursor->MaxWidth = cursor->MaxHeight = 64; 194 /* cursor->Flags; */ 195 cursor->SetCursorPosition = qxl_set_cursor_position; 196 cursor->LoadCursorARGB = qxl_load_cursor_argb; 197 cursor->UseHWCursor = qxl_use_hw_cursor; 198 cursor->UseHWCursorARGB = qxl_use_hw_cursorARGB; 199 cursor->LoadCursorImage = qxl_load_cursor_image; 200 cursor->SetCursorColors = qxl_set_cursor_colors; 201 cursor->HideCursor = qxl_hide_cursor; 202 cursor->ShowCursor = qxl_show_cursor; 203 204 if (!xf86InitCursor(pScreen, cursor)) 205 free(cursor); 206} 207