summaryrefslogtreecommitdiff
path: root/src/compat/compat-qxl_cursor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compat/compat-qxl_cursor.c')
-rw-r--r--src/compat/compat-qxl_cursor.c196
1 files changed, 196 insertions, 0 deletions
diff --git a/src/compat/compat-qxl_cursor.c b/src/compat/compat-qxl_cursor.c
new file mode 100644
index 0000000..bb5387e
--- /dev/null
+++ b/src/compat/compat-qxl_cursor.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2009 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <string.h>
+#include "compat-qxl.h"
+#include <cursorstr.h>
+
+static void
+push_cursor (qxl_screen_t *qxl, struct qxl_cursor_cmd *cursor)
+{
+ struct qxl_command cmd;
+
+ /* See comment on push_command() in qxl_driver.c */
+ if (qxl->rom->mode != ~0)
+ {
+ cmd.type = QXL_CMD_CURSOR;
+ cmd.data = physical_address (qxl, cursor);
+
+ qxl_ring_push (qxl->cursor_ring, &cmd);
+ }
+}
+
+static struct qxl_cursor_cmd *
+qxl_alloc_cursor_cmd(qxl_screen_t *qxl)
+{
+ struct qxl_cursor_cmd *cmd =
+ qxl_allocnf (qxl, sizeof(struct qxl_cursor_cmd));
+
+ cmd->release_info.id = pointer_to_u64 (cmd) | 1;
+
+ return cmd;
+}
+
+static void
+qxl_set_cursor_position(ScrnInfoPtr pScrn, int x, int y)
+{
+ qxl_screen_t *qxl = pScrn->driverPrivate;
+ struct qxl_cursor_cmd *cmd = qxl_alloc_cursor_cmd(qxl);
+
+ qxl->cur_x = x;
+ qxl->cur_y = y;
+
+ cmd->type = QXL_CURSOR_MOVE;
+ cmd->u.position.x = qxl->cur_x + qxl->hot_x;
+ cmd->u.position.y = qxl->cur_y + qxl->hot_y;
+
+ push_cursor(qxl, cmd);
+}
+
+static void
+qxl_load_cursor_image(ScrnInfoPtr pScrn, unsigned char *bits)
+{
+}
+
+static void
+qxl_set_cursor_colors(ScrnInfoPtr pScrn, int bg, int fg)
+{
+ /* Should not be called since UseHWCursor returned FALSE */
+}
+
+static void
+qxl_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ qxl_screen_t *qxl = pScrn->driverPrivate;
+ int w = pCurs->bits->width;
+ int h = pCurs->bits->height;
+ int size = w * h * sizeof (CARD32);
+
+ struct qxl_cursor_cmd *cmd = qxl_alloc_cursor_cmd (qxl);
+ struct qxl_cursor *cursor =
+ qxl_allocnf(qxl, sizeof(struct qxl_cursor) + size);
+
+ cursor->header.unique = 0;
+ cursor->header.type = CURSOR_TYPE_ALPHA;
+ cursor->header.width = w;
+ cursor->header.height = h;
+ /* I wonder if we can just tell the client that the hotspot is 0, 0
+ * always? The coordinates we are getting from X are for 0, 0 anyway,
+ * so the question is if the client uses the hotspot for anything else?
+ */
+ cursor->header.hot_spot_x = pCurs->bits->xhot;
+ cursor->header.hot_spot_y = pCurs->bits->yhot;
+
+ cursor->data_size = size;
+
+ cursor->chunk.next_chunk = 0;
+ cursor->chunk.prev_chunk = 0;
+ cursor->chunk.data_size = size;
+
+ memcpy (cursor->chunk.data, pCurs->bits->argb, size);
+
+#if 0
+ int i, j;
+ for (j = 0; j < h; ++j)
+ {
+ for (i = 0; i < w; ++i)
+ {
+ ErrorF ("%c", (pCurs->bits->argb[j * w + i] & 0xff000000) == 0xff000000? '#' : '.');
+ }
+
+ ErrorF ("\n");
+ }
+#endif
+
+ qxl->hot_x = pCurs->bits->xhot;
+ qxl->hot_y = pCurs->bits->yhot;
+
+ cmd->type = QXL_CURSOR_SET;
+ cmd->u.set.position.x = qxl->cur_x + qxl->hot_x;
+ cmd->u.set.position.y = qxl->cur_y + qxl->hot_y;
+ cmd->u.set.shape = physical_address (qxl, cursor);
+ cmd->u.set.visible = TRUE;
+
+ push_cursor(qxl, cmd);
+}
+
+static Bool
+qxl_use_hw_cursor (ScreenPtr pScrn, CursorPtr pCurs)
+{
+ /* Old-school bitmap cursors are not
+ * hardware accelerated for now.
+ */
+ return FALSE;
+}
+
+static Bool
+qxl_use_hw_cursorARGB (ScreenPtr pScrn, CursorPtr pCurs)
+{
+ return TRUE;
+}
+
+static void
+qxl_hide_cursor(ScrnInfoPtr pScrn)
+{
+ qxl_screen_t *qxl = pScrn->driverPrivate;
+ struct qxl_cursor_cmd *cursor = qxl_alloc_cursor_cmd(qxl);
+
+ cursor->type = QXL_CURSOR_HIDE;
+
+ push_cursor(qxl, cursor);
+}
+
+static void
+qxl_show_cursor(ScrnInfoPtr pScrn)
+{
+ /*
+ * slightly hacky, but there's no QXL_CURSOR_SHOW. Could maybe do
+ * QXL_CURSOR_SET?
+ */
+ qxl_screen_t *qxl = pScrn->driverPrivate;
+
+ qxl_set_cursor_position(pScrn, qxl->cur_x, qxl->cur_y);
+}
+
+hidden void
+qxl_cursor_init(ScreenPtr pScreen)
+{
+ xf86CursorInfoPtr cursor;
+
+ cursor = xcalloc(1, sizeof(xf86CursorInfoRec));
+ if (!cursor)
+ return;
+
+ cursor->MaxWidth = cursor->MaxHeight = 64;
+ /* cursor->Flags; */
+ cursor->SetCursorPosition = qxl_set_cursor_position;
+ cursor->LoadCursorARGB = qxl_load_cursor_argb;
+ cursor->UseHWCursor = qxl_use_hw_cursor;
+ cursor->UseHWCursorARGB = qxl_use_hw_cursorARGB;
+ cursor->LoadCursorImage = qxl_load_cursor_image;
+ cursor->SetCursorColors = qxl_set_cursor_colors;
+ cursor->HideCursor = qxl_hide_cursor;
+ cursor->ShowCursor = qxl_show_cursor;
+
+ if (!xf86InitCursor(pScreen, cursor))
+ xfree(cursor);
+}