summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2009-03-04 14:19:01 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2009-03-04 14:19:01 -0500
commit9ddbfa28c34554385223112ae5020282d234297a (patch)
tree628bbbad96c17185f04d9633569f42e196fd9661
parent779fd58b7394fb28d263ea8401bc6f0607007ef1 (diff)
Add hardware cursor support
-rw-r--r--src/qxl.h14
-rw-r--r--src/qxl_cursor.c101
-rw-r--r--src/qxl_driver.c78
-rw-r--r--src/qxl_mem.c2
4 files changed, 148 insertions, 47 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 6e943b4..951da64 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -56,6 +56,7 @@
#include <stdlib.h>
struct qxl_mem;
+typedef struct _qxlScreen qxlScreen;
struct qxl_mem *qxl_mem_create (void *base, unsigned long n_bytes);
@@ -63,6 +64,7 @@ void qxl_mem_dump_stats (struct qxl_mem *mem, const char *header);
void *qxl_alloc (struct qxl_mem *mem, unsigned long n_bytes);
void qxl_free (struct qxl_mem *mem, void *d);
void qxl_mem_free_all (struct qxl_mem *mem);
+void *qxl_allocnf (qxlScreen *qxl, unsigned long size);
#pragma pack(push,1)
@@ -408,12 +410,12 @@ struct qxl_cursor_header {
uint16_t hot_spot_y;
};
-struct qxl_cursorr
+struct qxl_cursor
{
struct qxl_cursor_header header;
uint32_t data_size;
struct qxl_data_chunk chunk;
-} QXLCursor;
+};
struct qxl_cursor_cmd {
union qxl_release_info release_info;
@@ -487,7 +489,7 @@ Bool qxl_ring_pop (struct qxl_ring *ring,
void *element);
void qxl_ring_wait_idle (struct qxl_ring *ring);
-typedef struct _qxlScreen
+struct _qxlScreen
{
/* These are the names QXL uses */
void * ram; /* Video RAM */
@@ -536,8 +538,10 @@ typedef struct _qxlScreen
int16_t cur_x;
int16_t cur_y;
-
+ int16_t hot_x;
+ int16_t hot_y;
+
ScrnInfoPtr pScrn;
-} qxlScreen;
+};
extern void qxlCursorInit(ScreenPtr pScreen);
diff --git a/src/qxl_cursor.c b/src/qxl_cursor.c
index 0acb487..6b00870 100644
--- a/src/qxl_cursor.c
+++ b/src/qxl_cursor.c
@@ -20,7 +20,9 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
+#include <string.h>
#include "qxl.h"
+#include <cursorstr.h>
static inline uint64_t
physical_address (qxlScreen *qxl, void *virtual)
@@ -42,20 +44,28 @@ push_cursor (qxlScreen *qxl, struct qxl_cursor_cmd *cursor)
static struct qxl_cursor_cmd *
qxl_alloc_cursor_cmd(qxlScreen *qxl)
{
- return qxl_alloc(qxl->mem, sizeof(struct qxl_cursor_cmd));
+ struct qxl_cursor_cmd *cmd =
+ qxl_allocnf (qxl, sizeof(struct qxl_cursor_cmd));
+
+ cmd->release_info.id = (uint64_t)cmd | 1;
+
+ return cmd;
}
static void
qxlSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
{
qxlScreen *qxl = pScrn->driverPrivate;
- struct qxl_cursor_cmd *cursor = qxl_alloc_cursor_cmd(qxl);
+ struct qxl_cursor_cmd *cmd = qxl_alloc_cursor_cmd(qxl);
- cursor->type = QXL_CURSOR_MOVE;
- cursor->u.position.x = qxl->cur_x = x;
- cursor->u.position.y = qxl->cur_y = y;
+ 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, cursor);
+ push_cursor(qxl, cmd);
}
static void
@@ -66,6 +76,78 @@ qxlLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *bits)
static void
qxlSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
{
+ /* Should not be called since UseHWCursor returned FALSE */
+}
+
+static void
+qxlLoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+ qxlScreen *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
+qxlUseHWCursor (ScreenPtr pScrn, CursorPtr pCurs)
+{
+ /* Old-school bitmap cursors are not
+ * hardware accelerated for now.
+ */
+ return FALSE;
+}
+
+static Bool
+qxlUseHWCursorARGB (ScreenPtr pScrn, CursorPtr pCurs)
+{
+ return TRUE;
}
static void
@@ -87,13 +169,13 @@ qxlShowCursor(ScrnInfoPtr pScrn)
* QXL_CURSOR_SET?
*/
qxlScreen *qxl = pScrn->driverPrivate;
+
qxlSetCursorPosition(pScrn, qxl->cur_x, qxl->cur_y);
}
hidden void
qxlCursorInit(ScreenPtr pScreen)
{
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
xf86CursorInfoPtr cursor;
cursor = xcalloc(1, sizeof(xf86CursorInfoRec));
@@ -103,8 +185,9 @@ qxlCursorInit(ScreenPtr pScreen)
cursor->MaxWidth = cursor->MaxHeight = 64;
/* cursor->Flags; */
cursor->SetCursorPosition = qxlSetCursorPosition;
- /* cursor->LoadCursorARGB = qxlLoadCursorARGB; */
- /* cursor->UseHWCursorARGB = qxlUseHWCursorARGB; */
+ cursor->LoadCursorARGB = qxlLoadCursorARGB;
+ cursor->UseHWCursor = qxlUseHWCursor;
+ cursor->UseHWCursorARGB = qxlUseHWCursorARGB;
cursor->LoadCursorImage = qxlLoadCursorImage;
cursor->SetCursorColors = qxlSetCursorColors;
cursor->HideCursor = qxlHideCursor;
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index d55a301..235643e 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -61,38 +61,43 @@ garbage_collect (qxlScreen *qxl)
while (qxl_ring_pop (qxl->release_ring, &id))
{
- struct qxl_drawable *drawable = (struct qxl_drawable *)id;
-
- while (drawable)
+ while (id)
{
- struct qxl_image *image;
- struct qxl_data_chunk *chunk;
- struct qxl_drawable *next;
+ /* We assume that there the two low bits of a pointer are
+ * available. If the low one is set, then the command in
+ * question is a cursor command
+ */
+#define POINTER_MASK ((1 << 2) - 1)
- switch (drawable->type)
+ union qxl_release_info *info = (void *)(id & ~POINTER_MASK);
+ struct qxl_cursor_cmd *cmd = (struct qxl_cursor_cmd *)info;
+ struct qxl_drawable *drawable = (struct qxl_drawable *)info;
+ int is_cursor = FALSE;
+
+ if ((id & POINTER_MASK) == 1)
+ is_cursor = TRUE;
+
+ if (is_cursor && cmd->type == QXL_CURSOR_SET)
{
- case QXL_DRAW_FILL:
- break;
-
- case QXL_DRAW_COPY:
- image = virtual_address (qxl, (void *)drawable->u.copy.src_bitmap);
- chunk = virtual_address (qxl, (void *)image->u.bitmap.data);
+ struct qxl_cursor *cursor = (void *)virtual_address (
+ qxl, (void *)cmd->u.set.shape);
+
+ qxl_free (qxl->mem, cursor);
+ }
+ else if (!is_cursor && drawable->type == QXL_DRAW_COPY)
+ {
+ struct qxl_image *image = virtual_address (
+ qxl, (void *)drawable->u.copy.src_bitmap);
+ struct qxl_data_chunk *chunk = virtual_address (
+ qxl, (void *)image->u.bitmap.data);
qxl_free (qxl->mem, image);
qxl_free (qxl->mem, chunk);
- break;
-
- default:
- break;
}
-
- next = (void *)drawable->release_info.next;
-
- qxl_free (qxl->mem, drawable);
-
- drawable = next;
- ++i;
+ id = info->next;
+
+ qxl_free (qxl->mem, info);
}
}
@@ -110,7 +115,7 @@ qxl_sleep (int useconds)
select (0, NULL, NULL, NULL, &t);
}
-static void *
+void *
qxl_allocnf (qxlScreen *qxl, unsigned long size)
{
void *result;
@@ -248,8 +253,8 @@ qxlSwitchMode(int scrnIndex, DisplayModePtr p, int flags)
outb(qxl->io_base + QXL_IO_SET_MODE, m->id);
- /* If this happens out of ScreenInit, we won't have a screen yet. In that case
- * createScreenResources will make things right.
+ /* If this happens out of ScreenInit, we won't have a screen yet. In that
+ * case createScreenResources will make things right.
*/
if (pScreen)
{
@@ -257,11 +262,12 @@ qxlSwitchMode(int scrnIndex, DisplayModePtr p, int flags)
if (pPixmap)
{
- pScreen->ModifyPixmapHeader(pPixmap,
- m->x_res, m->y_res,
- -1, -1,
- qxl->pScrn->displayWidth * ((qxl->pScrn->bitsPerPixel + 7) / 8),
- NULL);
+ pScreen->ModifyPixmapHeader(
+ pPixmap,
+ m->x_res, m->y_res,
+ -1, -1,
+ qxl->pScrn->displayWidth * ((qxl->pScrn->bitsPerPixel + 7) / 8),
+ NULL);
}
}
@@ -283,7 +289,10 @@ push_drawable (qxlScreen *qxl, struct qxl_drawable *drawable)
}
static struct qxl_image *
-make_image (qxlScreen *qxl, const uint8_t *data, int x, int y, int width, int height, int stride)
+make_image (qxlScreen *qxl, const uint8_t *data,
+ int x, int y,
+ int width, int height,
+ int stride)
{
struct qxl_image *image;
struct qxl_data_chunk *chunk;
@@ -298,6 +307,7 @@ make_image (qxlScreen *qxl, const uint8_t *data, int x, int y, int width, int he
/* FIXME: Check integer overflow */
chunk = qxl_allocnf (qxl, sizeof *chunk + height * dest_stride);
+
chunk->data_size = height * dest_stride;
chunk->prev_chunk = 0;
chunk->next_chunk = 0;
@@ -880,6 +890,8 @@ qxlScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
if (!miCreateDefColormap(pScreen))
goto out;
+ qxlCursorInit (pScreen);
+
CHECK_POINT();
qxlSwitchMode(scrnIndex, pScrn->currentMode, 0);
diff --git a/src/qxl_mem.c b/src/qxl_mem.c
index 5400076..acfd24f 100644
--- a/src/qxl_mem.c
+++ b/src/qxl_mem.c
@@ -130,6 +130,8 @@ qxl_alloc (struct qxl_mem *mem, unsigned long n_bytes)
* we can mostly ignore the difference between blocks and allocations
*/
n_bytes += sizeof (unsigned long);
+
+ n_bytes = (n_bytes + 7) & ~((1 << 3) - 1);
if (n_bytes < sizeof (struct block))
n_bytes = sizeof (struct block);