diff options
author | Søren Sandmann Pedersen <ssp@redhat.com> | 2009-03-04 14:19:01 -0500 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2009-03-04 14:19:01 -0500 |
commit | 9ddbfa28c34554385223112ae5020282d234297a (patch) | |
tree | 628bbbad96c17185f04d9633569f42e196fd9661 | |
parent | 779fd58b7394fb28d263ea8401bc6f0607007ef1 (diff) |
Add hardware cursor support
-rw-r--r-- | src/qxl.h | 14 | ||||
-rw-r--r-- | src/qxl_cursor.c | 101 | ||||
-rw-r--r-- | src/qxl_driver.c | 78 | ||||
-rw-r--r-- | src/qxl_mem.c | 2 |
4 files changed, 148 insertions, 47 deletions
@@ -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); |