summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <ssp@redhat.com>2010-07-09 10:27:24 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-09-14 08:03:59 -0400
commit7a5b6cfbccbdd567b35cbf5d199643cb1cf49c64 (patch)
tree3931a46af5e234715284dab7c15c1b06d567a70f
parent7641e2a8245f79dcf43c13fe14205d4856b27906 (diff)
Yeah, I need to get a real commit message written for all of this.
-rw-r--r--src/Makefile.am1
-rw-r--r--src/qxl.h142
-rw-r--r--src/qxl_cursor.c4
-rw-r--r--src/qxl_driver.c936
-rw-r--r--src/qxl_surface.c748
-rw-r--r--src/uxa/uxa-accel.c43
-rw-r--r--src/uxa/uxa-damage.c18
-rw-r--r--src/uxa/uxa-unaccel.c58
-rw-r--r--src/uxa/uxa.c21
9 files changed, 1432 insertions, 539 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index eb4e224..b329eea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -39,6 +39,7 @@ qxl_drv_la_SOURCES = \
qxl.h \
qxl_driver.c \
qxl_image.c \
+ qxl_surface.c \
qxl_ring.c \
qxl_mem.c \
lookup3.c \
diff --git a/src/qxl.h b/src/qxl.h
index 00305e6..40f70a5 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -92,7 +92,8 @@ typedef enum
QXL_CMD_DRAW,
QXL_CMD_UPDATE,
QXL_CMD_CURSOR,
- QXL_CMD_MESSAGE
+ QXL_CMD_MESSAGE,
+ QXL_CMD_SURFACE
} qxl_command_type;
struct qxl_command {
@@ -210,6 +211,18 @@ typedef enum {
QXL_BITMAP_TOP_DOWN = (1 << 2),
} qxl_bitmap_flags;
+typedef enum {
+ QXL_SURFACE_FMT_INVALID,
+ QXL_SURFACE_FMT_1_A,
+ QXL_SURFACE_FMT_8_A = 8,
+ QXL_SURFACE_FMT_16_555 = 16,
+ QXL_SURFACE_FMT_32_xRGB = 32,
+ QXL_SURFACE_FMT_16_565 = 80,
+ QXL_SURFACE_FMT_32_ARGB = 96,
+
+ SPICE_SURFACE_FMT_ENUM_END
+} qxl_surface_fmt;
+
struct qxl_bitmap {
uint8_t format;
uint8_t flags;
@@ -418,6 +431,32 @@ struct qxl_drawable {
} u;
};
+typedef enum {
+ QXL_SURFACE_CMD_CREATE,
+ QXL_SURFACE_CMD_DESTROY
+} qxl_surface_cmd_type;
+
+struct qxl_surface_info
+{
+ uint32_t format;
+ uint32_t width;
+ uint32_t height;
+ int32_t stride;
+ uint64_t physical;
+};
+
+struct qxl_surface_cmd {
+ union qxl_release_info release_info;
+ uint32_t surface_id;
+ uint8_t type;
+ uint32_t flags;
+ union
+ {
+ struct qxl_surface_info surface_create;
+ } u;
+};
+
+
struct qxl_compat_update_cmd {
union qxl_release_info release_info;
struct qxl_rect area;
@@ -572,12 +611,15 @@ typedef struct
uint64_t high_bits;
} qxl_memslot_t;
+typedef struct qxl_surface_t qxl_surface_t;
+
struct _qxl_screen_t
{
/* These are the names QXL uses */
- void * ram; /* Video RAM */
+ void * ram; /* Command RAM */
void * ram_physical;
- void * vram; /* Command RAM */
+ void * vram; /* Surface RAM */
+ void * vram_physical;
struct qxl_rom * rom; /* Parameter RAM */
struct qxl_ring * command_ring;
@@ -589,13 +631,22 @@ struct _qxl_screen_t
int io_base;
void * surface0_area;
long surface0_size;
+ long vram_size;
+ int virtual_x;
+ int virtual_y;
void * fb;
- int bytes_per_pixel;
-
+ int stride;
struct qxl_mode * current_mode;
+ qxl_surface_t * primary;
- struct qxl_mem * mem; /* Context for qxl_alloc/free */
+ int bytes_per_pixel;
+
+ /* Commands */
+ struct qxl_mem * mem; /* Context for qxl_alloc/free */
+
+ /* Surfaces */
+ struct qxl_mem * surf_mem; /* Context for qxl_surf_alloc/free */
EntityInfoPtr entity;
@@ -625,11 +676,14 @@ struct _qxl_screen_t
qxl_memslot_t * mem_slots;
uint8_t n_mem_slots;
+
uint8_t main_mem_slot;
uint8_t slot_id_bits;
uint8_t slot_gen_bits;
uint64_t va_slot_mask;
+ uint8_t vram_mem_slot;
+
union
{
PixmapPtr copy_source;
@@ -670,7 +724,9 @@ virtual_address (qxl_screen_t *qxl, void *physical, uint8_t slot_id)
return (void *)virt;
#if 0
- return (void *) ((unsigned long)physical + ((unsigned long)qxl->ram - (unsigned long)qxl->ram_physical));
+ return (void *) ((unsigned long)physical +
+ ((unsigned long)qxl->ram -
+ (unsigned long)qxl->ram_physical));
#endif
}
@@ -709,6 +765,77 @@ Bool qxl_ring_pop (struct qxl_ring *ring,
void qxl_ring_wait_idle (struct qxl_ring *ring);
+/*
+ * Surface
+ */
+void qxl_surface_init (qxl_screen_t *qxl, int n_surfaces);
+qxl_surface_t * qxl_surface_create_primary (qxl_screen_t *qxl,
+ struct qxl_mode *mode);
+qxl_surface_t * qxl_surface_create (qxl_screen_t *qxl,
+ int width,
+ int height,
+ int bpp);
+/* Call this to ask the device to destroy the surface */
+void qxl_surface_destroy (qxl_surface_t *surface);
+/* Call this when the notification comes back from the device
+ * that the surface has been destroyed
+ */
+void qxl_surface_recycle (uint32_t id);
+
+/* send anything pending to the other side */
+void qxl_surface_flush (qxl_surface_t *surface);
+
+/* access */
+Bool qxl_surface_prepare_access (qxl_surface_t *surface,
+ PixmapPtr pixmap,
+ RegionPtr region,
+ uxa_access_t access);
+void qxl_surface_finish_access (qxl_surface_t *surface,
+ PixmapPtr pixmap);
+
+/* solid */
+Bool qxl_surface_prepare_solid (qxl_surface_t *destination,
+ Pixel fg);
+void qxl_surface_solid (qxl_surface_t *destination,
+ int x1,
+ int y1,
+ int x2,
+ int y2);
+
+/* copy */
+Bool qxl_surface_prepare_copy (qxl_surface_t *source,
+ qxl_surface_t *dest);
+void qxl_surface_copy (qxl_surface_t *dest,
+ int src_x1, int src_y1,
+ int dest_x1, int dest_y1,
+ int width, int height);
+
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec uxa_pixmap_index;
+#else
+extern int uxa_pixmap_index;
+#endif
+
+static inline qxl_surface_t *get_surface (PixmapPtr pixmap)
+{
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
+#else
+ return dixLookupPrivate(&pixmap->devPrivates, &uxa_pixmap_index);
+#endif
+}
+
+static inline void set_surface (PixmapPtr pixmap, qxl_surface_t *surface)
+{
+ dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, surface);
+}
+
+static inline struct qxl_ram_header *
+get_ram_header (qxl_screen_t *qxl)
+{
+ return (struct qxl_ram_header *)
+ ((uint8_t *)qxl->ram + qxl->rom->ram_header_offset);
+}
/*
* Images
@@ -728,6 +855,7 @@ void qxl_drop_image_cache (qxl_screen_t *qxl);
/*
* Malloc
*/
+int qxl_handle_oom (qxl_screen_t *qxl);
struct qxl_mem * qxl_mem_create (void *base,
unsigned long n_bytes);
void qxl_mem_dump_stats (struct qxl_mem *mem,
diff --git a/src/qxl_cursor.c b/src/qxl_cursor.c
index 698b5ed..1e19eba 100644
--- a/src/qxl_cursor.c
+++ b/src/qxl_cursor.c
@@ -62,7 +62,7 @@ qxl_set_cursor_position(ScrnInfoPtr pScrn, int x, int 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);
}
@@ -167,7 +167,7 @@ qxl_show_cursor(ScrnInfoPtr pScrn)
* QXL_CURSOR_SET?
*/
qxl_screen_t *qxl = pScrn->driverPrivate;
-
+
qxl_set_cursor_position(pScrn, qxl->cur_x, qxl->cur_y);
}
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index 18af0e6..bb20522 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -24,7 +24,7 @@
* \author Adam Jackson <ajax@redhat.com>
*
* This is qxl, a driver for the Qumranet paravirtualized graphics device
- * in qemu.
+ * in qemu.
*/
#include <unistd.h>
@@ -49,7 +49,7 @@ garbage_collect (qxl_screen_t *qxl)
{
uint64_t id;
int i = 0;
-
+
while (qxl_ring_pop (qxl->release_ring, &id))
{
while (id)
@@ -63,32 +63,43 @@ garbage_collect (qxl_screen_t *qxl)
union qxl_release_info *info = u64_to_pointer (id & ~POINTER_MASK);
struct qxl_cursor_cmd *cmd = (struct qxl_cursor_cmd *)info;
struct qxl_drawable *drawable = (struct qxl_drawable *)info;
+ struct qxl_surface_cmd *surface_cmd = (struct qxl_surface_cmd *)info;
int is_cursor = FALSE;
+ int is_surface = FALSE;
+ int is_drawable = FALSE;
if ((id & POINTER_MASK) == 1)
is_cursor = TRUE;
+ else if ((id & POINTER_MASK) == 2)
+ is_surface = TRUE;
+ else
+ is_drawable = TRUE;
if (is_cursor && cmd->type == QXL_CURSOR_SET)
{
struct qxl_cursor *cursor = (void *)virtual_address (
qxl, u64_to_pointer (cmd->u.set.shape), qxl->main_mem_slot);
-
+
qxl_free (qxl->mem, cursor);
}
- else if (!is_cursor && drawable->type == QXL_DRAW_COPY)
+ else if (is_drawable && drawable->type == QXL_DRAW_COPY)
{
struct qxl_image *image = virtual_address (
qxl, u64_to_pointer (drawable->u.copy.src_bitmap), qxl->main_mem_slot);
-
+
qxl_image_destroy (qxl, image);
}
+ else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY)
+ {
+ qxl_surface_recycle (surface_cmd->surface_id);
+ }
id = info->next;
qxl_free (qxl->mem, info);
}
}
-
+
return i > 0;
}
@@ -96,23 +107,35 @@ static void
qxl_usleep (int useconds)
{
struct timespec t;
-
+
t.tv_sec = useconds / 1000000;
t.tv_nsec = (useconds - (t.tv_sec * 1000000)) * 1000;
-
+
errno = 0;
while (nanosleep (&t, &t) == -1 && errno == EINTR)
;
}
+int
+qxl_handle_oom (qxl_screen_t *qxl)
+{
+ outb (qxl->io_base + QXL_IO_NOTIFY_OOM, 0);
+
+ // qxl_usleep (10000);
+
+ return garbage_collect (qxl);
+}
+
void *
qxl_allocnf (qxl_screen_t *qxl, unsigned long size)
{
void *result;
int n_attempts = 0;
+#if 0
static int nth_oom = 1;
-
+#endif
+
garbage_collect (qxl);
while (!(result = qxl_alloc (qxl->mem, size)))
@@ -131,13 +154,11 @@ qxl_allocnf (qxl_screen_t *qxl, unsigned long size)
outb (qxl->io_base + QXL_IO_UPDATE_AREA, 0);
+#if 0
ErrorF ("eliminated memory (%d)\n", nth_oom++);
-
- outb (qxl->io_base + QXL_IO_NOTIFY_OOM, 0);
-
- qxl_usleep (10000);
+#endif
- if (garbage_collect (qxl))
+ if (qxl_handle_oom (qxl))
{
n_attempts = 0;
}
@@ -149,7 +170,7 @@ qxl_allocnf (qxl_screen_t *qxl, unsigned long size)
exit (1);
}
}
-
+
return result;
}
@@ -177,9 +198,9 @@ qxl_unmap_memory(qxl_screen_t *qxl, int scrnIndex)
if (qxl->rom)
xf86UnMapVidMem(scrnIndex, qxl->rom, (1 << qxl->pci->size[2]));
#endif
-
+
qxl->ram = qxl->ram_physical = qxl->vram = qxl->rom = NULL;
-
+
qxl->num_modes = 0;
qxl->modes = NULL;
}
@@ -193,16 +214,18 @@ qxl_map_memory(qxl_screen_t *qxl, int scrnIndex)
PCI_DEV_MAP_FLAG_WRITABLE | PCI_DEV_MAP_FLAG_WRITE_COMBINE,
&qxl->ram);
qxl->ram_physical = u64_to_pointer (qxl->pci->regions[0].base_addr);
-
+
pci_device_map_range(qxl->pci, qxl->pci->regions[1].base_addr,
qxl->pci->regions[1].size,
PCI_DEV_MAP_FLAG_WRITABLE,
&qxl->vram);
-
+ qxl->vram_physical = u64_to_pointer (qxl->pci->regions[1].base_addr);
+ qxl->vram_size = qxl->pci->regions[1].size;
+
pci_device_map_range(qxl->pci, qxl->pci->regions[2].base_addr,
qxl->pci->regions[2].size, 0,
(void **)&qxl->rom);
-
+
qxl->io_base = qxl->pci->regions[3].base_addr;
#else
qxl->ram = xf86MapPciMem(scrnIndex, VIDMEM_FRAMEBUFFER,
@@ -213,6 +236,8 @@ qxl_map_memory(qxl_screen_t *qxl, int scrnIndex)
qxl->vram = xf86MapPciMem(scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT,
qxl->pci_tag, qxl->pci->memBase[1],
(1 << qxl->pci->size[1]));
+ qxl->vram_physical = (void *)qxl->pci->memBase[1];
+ qxl->vram_size = (1 << qxl->pci->size[1]);
qxl->rom = xf86MapPciMem(scrnIndex, VIDMEM_MMIO | VIDMEM_MMIO_32BIT,
qxl->pci_tag, qxl->pci->memBase[2],
@@ -222,15 +247,28 @@ qxl_map_memory(qxl_screen_t *qxl, int scrnIndex)
#endif
if (!qxl->ram || !qxl->vram || !qxl->rom)
return FALSE;
+
+ xf86DrvMsg(scrnIndex, X_INFO, "framebuffer at %p (%d KB)\n",
+ qxl->ram, qxl->rom->surface0_area_size / 1024);
+
+ xf86DrvMsg(scrnIndex, X_INFO, "command ram at %p (%d KB)\n",
+ (void *)((unsigned long)qxl->ram + qxl->rom->surface0_area_size),
+ (qxl->rom->num_pages * getpagesize() - qxl->rom->surface0_area_size)/1024);
- xf86DrvMsg(scrnIndex, X_INFO, "ram at %p; vram at %p; rom at %p\n",
- qxl->ram, qxl->vram, qxl->rom);
+ xf86DrvMsg(scrnIndex, X_INFO, "vram at %p (%ld KB)\n",
+ qxl->vram, qxl->vram_size / 1024);
+ xf86DrvMsg(scrnIndex, X_INFO, "rom at %p\n", qxl->rom);
+
qxl->num_modes = *(uint32_t *)((uint8_t *)qxl->rom + qxl->rom->modes_offset);
qxl->modes = (struct qxl_mode *)(((uint8_t *)qxl->rom) + qxl->rom->modes_offset + 4);
qxl->surface0_area = qxl->ram;
qxl->surface0_size = qxl->rom->surface0_area_size;
+ qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->ram + qxl->surface0_size),
+ qxl->rom->num_pages * getpagesize() - qxl->surface0_size);
+ qxl->surf_mem = qxl_mem_create ((void *)((unsigned long)qxl->vram), qxl->vram_size);
+
return TRUE;
}
@@ -239,17 +277,24 @@ qxl_close_screen(int scrnIndex, ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
qxl_screen_t *qxl = pScrn->driverPrivate;
-
+ Bool result;
+
if (pScrn->vtSema)
qxl_unmap_memory(qxl, scrnIndex);
pScrn->vtSema = FALSE;
+ ErrorF ("Freeing %p\n", qxl->fb);
xfree(qxl->fb);
-
+ qxl->fb = NULL;
+
pScreen->CreateScreenResources = qxl->create_screen_resources;
pScreen->CloseScreen = qxl->close_screen;
+
+
- return pScreen->CloseScreen(scrnIndex, pScreen);
+ result = pScreen->CloseScreen(scrnIndex, pScreen);
+
+ return result;
}
static void
@@ -258,47 +303,68 @@ qxl_reset (qxl_screen_t *qxl)
qxl_memslot_t *slot;
uint64_t high_bits;
struct qxl_ram_header *ram_header;
-
- outb(qxl->io_base + QXL_IO_RESET, 0);
- ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
+ outb(qxl->io_base + QXL_IO_RESET, 0);
+ ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
+
+ qxl_surface_init (qxl, qxl->rom->n_surfaces);
+
/* Mem slots */
ErrorF ("slots start: %d, slots end: %d\n",
qxl->rom->slots_start,
qxl->rom->slots_end);
-
- qxl->main_mem_slot = qxl->rom->slots_start;
+
+ /* Main slot */
qxl->n_mem_slots = qxl->rom->slots_end;
qxl->slot_gen_bits = qxl->rom->slot_gen_bits;
qxl->slot_id_bits = qxl->rom->slot_id_bits;
+ qxl->va_slot_mask = (~(uint64_t)0) >> (qxl->slot_id_bits + qxl->slot_gen_bits);
qxl->mem_slots = xnfalloc (qxl->n_mem_slots * sizeof (qxl_memslot_t));
-
+
+ qxl->main_mem_slot = qxl->rom->slots_start;
slot = &qxl->mem_slots[qxl->main_mem_slot];
-
slot->start_phys_addr = (unsigned long)qxl->ram_physical;
slot->end_phys_addr = (unsigned long)slot->start_phys_addr + (unsigned long)qxl->rom->num_pages * getpagesize();
slot->start_virt_addr = (uint64_t)qxl->ram;
slot->end_virt_addr = slot->start_virt_addr + (unsigned long)qxl->rom->num_pages * getpagesize();
-
+
ram_header->mem_slot_start = slot->start_phys_addr;
ram_header->mem_slot_end = slot->end_phys_addr;
-
+
outb (qxl->io_base + QXL_IO_MEMSLOT_ADD, qxl->main_mem_slot);
- ErrorF ("Created memslot from %lx to %lx\n", slot->start_phys_addr, slot->end_phys_addr);
-
- slot->generation = qxl->rom->slot_generation;
+ ErrorF ("Created main memslot from %lx to %lx\n", slot->start_phys_addr, slot->end_phys_addr);
+ slot->generation = qxl->rom->slot_generation;
+
high_bits = qxl->main_mem_slot << qxl->slot_gen_bits;
high_bits |= slot->generation;
high_bits <<= (64 - (qxl->slot_gen_bits + qxl->slot_id_bits));
slot->high_bits = high_bits;
-
- qxl->va_slot_mask = (~(uint64_t)0) >> (qxl->slot_id_bits + qxl->slot_gen_bits);
+ /* Vram slot */
+ qxl->vram_mem_slot = qxl->rom->slots_start + 1;
+ slot = &qxl->mem_slots[qxl->vram_mem_slot];
+ slot->start_phys_addr = (unsigned long)qxl->vram_physical;
+ slot->end_phys_addr = (unsigned long)qxl->vram_physical + (unsigned long)qxl->vram_size;
+ slot->start_virt_addr = (uint64_t)qxl->vram;
+ slot->end_virt_addr = (uint64_t)qxl->vram + (uint64_t)qxl->vram_size;
+
+ ram_header->mem_slot_start = slot->start_phys_addr;
+ ram_header->mem_slot_end = slot->end_phys_addr;
+
+ outb (qxl->io_base + QXL_IO_MEMSLOT_ADD, qxl->vram_mem_slot);
+
+ ErrorF ("Created vram memslot from %lx to %lx\n", slot->start_phys_addr, slot->end_phys_addr);
+
+ slot->generation = qxl->rom->slot_generation;
+ high_bits = qxl->vram_mem_slot << qxl->slot_gen_bits;
+ high_bits |= slot->generation;
+ high_bits <<= (64 - (qxl->slot_gen_bits + qxl->slot_id_bits));
+ slot->high_bits = high_bits;
}
static void
@@ -311,7 +377,8 @@ set_screen_pixmap_header (ScreenPtr pScreen)
if (pPixmap && qxl->current_mode)
{
ErrorF ("new stride: %d (display width: %d, bpp: %d)\n",
- qxl->pScrn->displayWidth * qxl->bytes_per_pixel, qxl->pScrn->displayWidth, qxl->bytes_per_pixel);
+ qxl->pScrn->displayWidth * qxl->bytes_per_pixel,
+ qxl->pScrn->displayWidth, qxl->bytes_per_pixel);
pScreen->ModifyPixmapHeader(
pPixmap,
@@ -330,49 +397,35 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
qxl_screen_t *qxl = xf86Screens[scrnIndex]->driverPrivate;
int mode_index = (int)(unsigned long)p->Private;
struct qxl_mode *m = qxl->modes + mode_index;
- ScreenPtr pScreen = qxl->pScrn->pScreen;
- struct qxl_ram_header *ram_header = (void *)((unsigned long)qxl->ram +
- qxl->rom->ram_header_offset);
- struct qxl_surface_create *create = &(ram_header->create_surface);
-
- if (!m)
- return FALSE;
+ ScreenPtr pScreen;
- /* if (debug) */
- xf86DrvMsg (scrnIndex, X_INFO, "Setting mode %d (%d x %d) (%d x %d) %p\n",
- m->id, m->x_res, m->y_res, p->HDisplay, p->VDisplay, p);
+ if (qxl->primary)
+ qxl_surface_destroy (qxl->primary);
qxl_reset (qxl);
-
- create->width = m->x_res;
- create->height = m->y_res;
- create->stride = - m->stride;
- create->depth = m->bits;
- create->position = 0; /* What is this? The Windows driver doesn't use it */
- create->flags = 0;
- create->type = QXL_SURF_TYPE_PRIMARY;
- create->mem = physical_address (qxl, qxl->ram, qxl->main_mem_slot);
- outb (qxl->io_base + QXL_IO_CREATE_PRIMARY, 0);
-
+ qxl->primary = qxl_surface_create_primary (qxl, m);
+ qxl->current_mode = m;
qxl->bytes_per_pixel = (qxl->pScrn->bitsPerPixel + 7) / 8;
- /* If this happens out of ScreenInit, we won't have a screen yet. In that
- * case createScreenResources will make things right.
- */
+ pScreen = qxl->pScrn->pScreen;
if (pScreen)
{
- set_screen_pixmap_header (pScreen);
+ PixmapPtr root = pScreen->GetScreenPixmap (pScreen);
+
+ set_surface (root, qxl->primary);
}
+ ErrorF ("primary is %p\n", qxl->primary);
if (qxl->mem)
{
- qxl_mem_free_all (qxl->mem);
- qxl_drop_image_cache (qxl);
+ qxl_mem_free_all (qxl->mem);
+ qxl_drop_image_cache (qxl);
}
- qxl->current_mode = m;
-
+ if (qxl->surf_mem)
+ qxl_mem_free_all (qxl->surf_mem);
+
return TRUE;
}
@@ -380,7 +433,7 @@ static void
push_drawable (qxl_screen_t *qxl, struct qxl_drawable *drawable)
{
struct qxl_command cmd;
-
+
/* When someone runs "init 3", the device will be
* switched into VGA mode and there is nothing we
* can do about it. We get no notification.
@@ -394,7 +447,7 @@ push_drawable (qxl_screen_t *qxl, struct qxl_drawable *drawable)
{
cmd.type = QXL_CMD_DRAW;
cmd.data = physical_address (qxl, drawable, qxl->main_mem_slot);
-
+
qxl_ring_push (qxl->command_ring, &cmd);
}
}
@@ -410,13 +463,13 @@ make_drawable (qxl_screen_t *qxl, uint8_t type,
CHECK_POINT();
drawable = qxl_allocnf (qxl, sizeof *drawable);
-
+
CHECK_POINT();
-
+
drawable->release_info.id = pointer_to_u64 (drawable);
-
+
drawable->type = type;
-
+
drawable->surface_id = 0; /* Only primary for now */
drawable->effect = QXL_EFFECT_OPAQUE;
drawable->self_bitmap = 0;
@@ -426,22 +479,23 @@ make_drawable (qxl_screen_t *qxl, uint8_t type,
drawable->self_bitmap_area.right = 0;
/* FIXME: add clipping */
drawable->clip.type = QXL_CLIP_TYPE_NONE;
-
+
/* FIXME: What are you supposed to put in surfaces_dest and surfaces_rects? */
for (i = 0; i < 3; ++i)
drawable->surfaces_dest[i] = -1;
if (rect)
drawable->bbox = *rect;
-
+
drawable->mm_time = qxl->rom->mm_clock;
-
+
CHECK_POINT();
return drawable;
}
-enum ROPDescriptor {
+enum ROPDescriptor
+{
ROPD_INVERS_SRC = (1 << 0),
ROPD_INVERS_BRUSH = (1 << 1),
ROPD_INVERS_DEST = (1 << 2),
@@ -459,13 +513,13 @@ static void
submit_fill (qxl_screen_t *qxl, const struct qxl_rect *rect, uint32_t color)
{
struct qxl_drawable *drawable;
-
+
CHECK_POINT();
drawable = make_drawable (qxl, QXL_DRAW_FILL, rect);
-
+
CHECK_POINT();
-
+
drawable->u.fill.brush.type = QXL_BRUSH_TYPE_SOLID;
drawable->u.fill.brush.u.color = color;
drawable->u.fill.rop_descriptor = ROPD_OP_PUT;
@@ -473,7 +527,7 @@ submit_fill (qxl_screen_t *qxl, const struct qxl_rect *rect, uint32_t color)
drawable->u.fill.mask.pos.x = 0;
drawable->u.fill.mask.pos.y = 0;
drawable->u.fill.mask.bitmap = 0;
-
+
push_drawable (qxl, drawable);
}
@@ -490,7 +544,7 @@ submit_copy (qxl_screen_t *qxl, const struct qxl_rect *rect)
{
struct qxl_drawable *drawable;
ScrnInfoPtr pScrn = qxl->pScrn;
-
+
if (rect->left == rect->right ||
rect->top == rect->bottom)
{
@@ -499,7 +553,7 @@ submit_copy (qxl_screen_t *qxl, const struct qxl_rect *rect)
}
drawable = make_drawable (qxl, QXL_DRAW_COPY, rect);
-
+
drawable->u.copy.src_bitmap = physical_address (
qxl, qxl_image_create (qxl, qxl->fb, rect->left, rect->top,
rect->right - rect->left,
@@ -513,7 +567,7 @@ submit_copy (qxl_screen_t *qxl, const struct qxl_rect *rect)
drawable->u.copy.mask.pos.x = 0;
drawable->u.copy.mask.pos.y = 0;
drawable->u.copy.mask.bitmap = 0;
-
+
push_drawable (qxl, drawable);
}
@@ -521,12 +575,12 @@ static void
paint_shadow (qxl_screen_t *qxl)
{
struct qxl_rect qrect;
-
+
qrect.top = 0;
qrect.bottom = 1200;
qrect.left = 0;
qrect.right = 1600;
-
+
submit_copy (qxl, &qrect);
}
@@ -536,7 +590,7 @@ qxl_sanity_check (qxl_screen_t *qxl)
/* read the mode back from the rom */
if (!qxl->rom || !qxl->pScrn)
return;
-
+
if (in_vga_mode (qxl))
{
ErrorF("QXL device jumped back to VGA mode - resetting mode\n");
@@ -556,11 +610,11 @@ qxl_create_screen_resources(ScreenPtr pScreen)
qxl_screen_t *qxl = pScrn->driverPrivate;
Bool ret;
PixmapPtr pPixmap;
-
+
pScreen->CreateScreenResources = qxl->create_screen_resources;
ret = pScreen->CreateScreenResources (pScreen);
pScreen->CreateScreenResources = qxl_create_screen_resources;
-
+
if (!ret)
return FALSE;
@@ -568,6 +622,8 @@ qxl_create_screen_resources(ScreenPtr pScreen)
set_screen_pixmap_header (pScreen);
+ set_surface (pPixmap, qxl->primary);
+
return TRUE;
}
@@ -576,29 +632,29 @@ get_window_pixmap (DrawablePtr pDrawable, int *xoff, int *yoff)
{
ScreenPtr pScreen = pDrawable->pScreen;
PixmapPtr result;
-
+
if (pDrawable->type != DRAWABLE_WINDOW)
return NULL;
-
+
result = pScreen->GetWindowPixmap ((WindowPtr)pDrawable);
-
+
*xoff = pDrawable->x;
*yoff = pDrawable->y;
-
+
return result;
}
static void
qxl_poly_fill_rect (DrawablePtr pDrawable,
- GCPtr pGC,
- int nrect,
- xRectangle *prect)
+ GCPtr pGC,
+ int nrect,
+ xRectangle *prect)
{
ScrnInfoPtr pScrn = xf86Screens[pDrawable->pScreen->myNum];
qxl_screen_t *qxl = pScrn->driverPrivate;
PixmapPtr pPixmap;
int xoff, yoff;
-
+
if ((pPixmap = get_window_pixmap (pDrawable, &xoff, &yoff)) &&
pGC->fillStyle == FillSolid &&
pGC->alu == GXcopy &&
@@ -611,24 +667,24 @@ qxl_poly_fill_rect (DrawablePtr pDrawable,
REGION_TRANSLATE(pScreen, pReg, xoff, yoff);
REGION_INTERSECT(pScreen, pReg, pClip, pReg);
-
+
pBox = REGION_RECTS (pReg);
nbox = REGION_NUM_RECTS (pReg);
-
+
while (nbox--)
{
struct qxl_rect qrect;
-
+
qrect.left = pBox->x1;
qrect.right = pBox->x2;
qrect.top = pBox->y1;
qrect.bottom = pBox->y2;
-
+
submit_fill (qxl, &qrect, pGC->fgPixel);
-
+
pBox++;
}
-
+
REGION_DESTROY (pScreen, pReg);
}
@@ -654,7 +710,7 @@ qxl_copy_n_to_n (DrawablePtr pSrcDrawable,
int src_xoff, src_yoff;
int dst_xoff, dst_yoff;
PixmapPtr pSrcPixmap, pDstPixmap;
-
+
if ((pSrcPixmap = get_window_pixmap (pSrcDrawable, &src_xoff, &src_yoff)) &&
(pDstPixmap = get_window_pixmap (pDstDrawable, &dst_xoff, &dst_yoff)))
{
@@ -662,9 +718,9 @@ qxl_copy_n_to_n (DrawablePtr pSrcDrawable,
BoxPtr b = pbox;
assert (pSrcPixmap == pDstPixmap);
-
+
/* ErrorF ("Accelerated copy: %d boxes\n", n); */
-
+
/* At this point we know that any pending damage must
* have been caused by whatever copy operation triggered us.
*
@@ -689,7 +745,7 @@ qxl_copy_n_to_n (DrawablePtr pSrcDrawable,
* very big.
*/
}
-
+
while (n--)
{
struct qxl_drawable *drawable;
@@ -699,7 +755,7 @@ qxl_copy_n_to_n (DrawablePtr pSrcDrawable,
qrect.bottom = b->y2;
qrect.left = b->x1;
qrect.right = b->x2;
-
+
/* ErrorF (" Translate %d %d %d %d by %d %d (offsets %d %d)\n", */
/* b->x1, b->y1, b->x2, b->y2, */
/* dx, dy, dst_xoff, dst_yoff); */
@@ -707,21 +763,21 @@ qxl_copy_n_to_n (DrawablePtr pSrcDrawable,
drawable = make_drawable (qxl, QXL_COPY_BITS, &qrect);
drawable->u.copy_bits.src_pos.x = b->x1 + dx;
drawable->u.copy_bits.src_pos.y = b->y1 + dy;
-
+
push_drawable (qxl, drawable);
-
+
b++;
}
}
/* else */
/* ErrorF ("Unaccelerated copy\n"); */
-
+
fbCopyNtoN (pSrcDrawable, pDstDrawable, pGC, pbox, nbox, dx, dy, reverse, upsidedown, bitplane, closure);
}
static RegionPtr
qxl_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
- int srcx, int srcy, int width, int height, int dstx, int dsty)
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
{
ErrorF ("Copy Area\n");
@@ -729,21 +785,21 @@ qxl_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
pDstDrawable->type == DRAWABLE_WINDOW)
{
RegionPtr res;
-
+
/* ErrorF ("accelerated copy %d %d %d %d %d %d\n", */
/* srcx, srcy, width, height, dstx, dsty); */
-
+
res = fbDoCopy (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height, dstx, dsty,
qxl_copy_n_to_n, 0, NULL);
-
+
return res;
}
else
{
/* ErrorF ("Falling back %d %d %d %d %d %d\n", */
/* srcx, srcy, width, height, dstx, dsty); */
-
+
return fbCopyArea (pSrcDrawable, pDstDrawable, pGC,
srcx, srcy, width, height, dstx, dsty);
}
@@ -757,27 +813,27 @@ qxl_fill_region_solid (DrawablePtr pDrawable, RegionPtr pRegion, Pixel pixel)
qxl_screen_t *qxl = pScrn->driverPrivate;
PixmapPtr pPixmap;
int xoff, yoff;
-
+
if ((pPixmap = get_window_pixmap (pDrawable, &xoff, &yoff)))
{
int nbox = REGION_NUM_RECTS (pRegion);
BoxPtr pBox = REGION_RECTS (pRegion);
-
+
while (nbox--)
{
struct qxl_rect qrect;
-
+
qrect.left = pBox->x1;
qrect.right = pBox->x2;
qrect.top = pBox->y1;
qrect.bottom = pBox->y2;
-
+
submit_fill (qxl, &qrect, pixel);
-
+
pBox++;
}
}
-
+
fbFillRegionSolid (pDrawable, pRegion, 0,
fbReplicatePixel (pixel, pDrawable->bitsPerPixel));
}
@@ -790,13 +846,13 @@ qxl_create_gc (GCPtr pGC)
if (!fbCreateGC (pGC))
return FALSE;
-
+
if (!initialized)
{
ops = *pGC->ops;
ops.PolyFillRect = qxl_poly_fill_rect;
ops.CopyArea = qxl_copy_area;
-
+
initialized = TRUE;
}
@@ -804,7 +860,11 @@ qxl_create_gc (GCPtr pGC)
return TRUE;
}
-static int uxa_pixmap_index;
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec uxa_pixmap_index;
+#else
+int uxa_pixmap_index;
+#endif
static Bool
unaccel (void)
@@ -813,58 +873,11 @@ unaccel (void)
}
static void
-download_box (qxl_screen_t *qxl, uint8_t *host,
- int x1, int y1, int x2, int y2)
-{
- struct qxl_ram_header *ram_header = (void *)((unsigned long)qxl->ram +
- qxl->rom->ram_header_offset);
- int stride = - qxl->current_mode->stride;
- int Bpp = qxl->current_mode->bits / 8;
- uint8_t *host_line;
- uint8_t *dev_line;
- int height = y2 - y1;
-
- if (y1 != 0 || x1 != 0 || y2 != 1200 || x2 != 1600)
- ErrorF ("asdf\n");
-
- ram_header->update_area.top = y1;
- ram_header->update_area.bottom = y2;
- ram_header->update_area.left = x1;
- ram_header->update_area.right = x2;
- ram_header->update_surface = 0; /* Only primary for now */
-
- outb (qxl->io_base + QXL_IO_UPDATE_AREA, 0);
-
- usleep (10000);
-
- dev_line = ((uint8_t *)qxl->ram) +
- (qxl->current_mode->y_res - 1) * (-stride) + /* top of frame buffer */
- y1 * stride + /* first line */
- x1 * Bpp;
- host_line = host + y1 * stride + x1 * Bpp;
-
- ErrorF ("stride: %d\n", stride);
-
- while (height--)
- {
- uint8_t *h = host_line;
- uint8_t *d = dev_line;
- int w = (x2 - x1) * Bpp;
-
- host_line += stride;
- dev_line += stride;
-
- while (w--)
- *h++ = *d++;
- }
-}
-
-static void
print_region (const char *header, RegionPtr pRegion)
{
int nbox = REGION_NUM_RECTS (pRegion);
BoxPtr pbox = REGION_RECTS (pRegion);
-
+
ErrorF ("%s \n", header);
while (nbox--)
@@ -872,137 +885,41 @@ print_region (const char *header, RegionPtr pRegion)
ErrorF (" %d %d %d %d (size: %d %d)\n",
pbox->x1, pbox->y1, pbox->x2, pbox->y2,
pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
-
+
pbox++;
}
}
static Bool
-qxl_prepare_access(PixmapPtr pixmap, RegionPtr region, uxa_access_t access)
+qxl_prepare_access (PixmapPtr pixmap, RegionPtr region, uxa_access_t access)
{
- ScreenPtr pScreen = pixmap->drawable.pScreen;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- qxl_screen_t *qxl = pScrn->driverPrivate;
- uint8_t *copy;
- int n_bytes;
- BoxPtr boxes;
- int n_boxes;
- int stride;
-
- stride = qxl->current_mode->stride;
-
- ErrorF ("Stride: %d\n", stride);
-
- n_bytes = stride * pixmap->drawable.height;
-
- copy = malloc (n_bytes);
-
- if (!copy)
- return FALSE;
-
- /* QXL's framebuffer has a negative stride */
- copy += stride * (pixmap->drawable.height - 1);
-
- n_boxes = REGION_NUM_RECTS (region);
- boxes = REGION_RECTS (region);
- while (n_boxes--)
- {
- download_box (qxl, copy, boxes->x1, boxes->y1, boxes->x2, boxes->y2);
- boxes++;
- }
-
- pScreen->ModifyPixmapHeader(
- pixmap, pixmap->drawable.width, pixmap->drawable.height, -1, -1, -1, copy);
-
- /* miModifyPixmapHeader() doesn't seem to actually set a negative
- * stride, so just set it here.
- */
- pixmap->devKind = - stride;
-
- REGION_INIT (pScreen, &(qxl->u.access_region), (BoxPtr)NULL, 0);
- REGION_COPY (pScreen, &(qxl->u.access_region), region);
-
- return TRUE;
+ return qxl_surface_prepare_access (get_surface (pixmap),
+ pixmap, region, access);
}
static void
qxl_finish_access (PixmapPtr pixmap)
{
- ScreenPtr pScreen = pixmap->drawable.pScreen;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- qxl_screen_t *qxl = pScrn->driverPrivate;
- int w = pixmap->drawable.width;
- int h = pixmap->drawable.height;
- int stride = pixmap->devKind;
- int n_boxes;
- BoxPtr boxes;
-
- print_region ("Finishing access", &qxl->u.access_region);
-
- n_boxes = REGION_NUM_RECTS (&qxl->u.access_region);
- boxes = REGION_RECTS (&qxl->u.access_region);
- while (n_boxes--)
- {
- struct qxl_rect rect;
- struct qxl_drawable *drawable;
- struct qxl_image *image;
- int x1, y1, x2, y2;
-
- x1 = boxes->x1;
- y1 = boxes->y1;
- x2 = boxes->x2;
- y2 = boxes->y2;
-
- rect.left = x1;
- rect.right = x2;
- rect.top = y1;
- rect.bottom = y2;
-
- /* Paint a green flash before uploading */
- submit_fill (qxl, &rect, 0xff00ff00);
-
- usleep (50000);
-
- drawable = make_drawable (qxl, QXL_DRAW_COPY, &rect);
- drawable->u.copy.src_area = rect;
- translate_rect (&drawable->u.copy.src_area);
- drawable->u.copy.rop_descriptor = ROPD_OP_PUT;
- drawable->u.copy.scale_mode = 0;
- drawable->u.copy.mask.flags = 0;
- drawable->u.copy.mask.pos.x = 0;
- drawable->u.copy.mask.pos.y = 0;
- drawable->u.copy.mask.bitmap = 0;
-
- image = qxl_image_create (qxl, pixmap->devPrivate.ptr,
- x1, y1, x2 - x1, y2 - y1, stride);
- drawable->u.copy.src_bitmap =
- physical_address (qxl, image, qxl->main_mem_slot);
-
- push_drawable (qxl, drawable);
-
- boxes++;
- }
-
- REGION_UNINIT (pScreen, &qxl->u.access_region);
-
- pScreen->ModifyPixmapHeader(pixmap, w, h, -1, -1, 0, NULL);
+ qxl_surface_finish_access (get_surface (pixmap), pixmap);
}
static Bool
qxl_pixmap_is_offscreen (PixmapPtr pixmap)
{
- ScreenPtr pScreen = pixmap->drawable.pScreen;
- PixmapPtr scr_pixmap = pScreen->GetScreenPixmap(pScreen);
+ return !!get_surface (pixmap);
+}
- if (pixmap == scr_pixmap)
- {
- ErrorF ("%p is offscreen \n", pixmap);
- return TRUE;
- }
- ErrorF ("is not offscreen \n");
+static Bool
+good_alu_and_pm (DrawablePtr drawable, int alu, Pixel planemask)
+{
+ if (!UXA_PM_IS_SOLID (drawable, planemask))
+ return FALSE;
- return FALSE;
+ if (alu != GXcopy)
+ return FALSE;
+
+ return TRUE;
}
/*
@@ -1011,20 +928,7 @@ qxl_pixmap_is_offscreen (PixmapPtr pixmap)
static Bool
qxl_check_solid (DrawablePtr drawable, int alu, Pixel planemask)
{
- if (!UXA_PM_IS_SOLID (drawable, planemask))
- {
- ErrorF ("non solid planemask\n");
- return FALSE;
- }
-
- if (drawable->bitsPerPixel != 16 &&
- drawable->bitsPerPixel != 32)
- {
- ErrorF ("wrong bpp\n");
- return FALSE;
- }
-
- if (alu != GXcopy)
+ if (!good_alu_and_pm (drawable, alu, planemask))
return FALSE;
return TRUE;
@@ -1033,29 +937,18 @@ qxl_check_solid (DrawablePtr drawable, int alu, Pixel planemask)
static Bool
qxl_prepare_solid (PixmapPtr pixmap, int alu, Pixel planemask, Pixel fg)
{
- ScreenPtr pScreen = pixmap->drawable.pScreen;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- qxl_screen_t *qxl = pScrn->driverPrivate;
-
- qxl->u.solid_pixel = fg;
-
- return TRUE;
+ qxl_surface_t *surface;
+
+ if (!(surface = get_surface (pixmap)))
+ return FALSE;
+
+ return qxl_surface_prepare_solid (surface, fg);
}
static void
qxl_solid (PixmapPtr pixmap, int x1, int y1, int x2, int y2)
{
- ScreenPtr pScreen = pixmap->drawable.pScreen;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- qxl_screen_t *qxl = pScrn->driverPrivate;
- struct qxl_rect qrect;
-
- qrect.top = y1;
- qrect.bottom = y2;
- qrect.left = x1;
- qrect.right = x2;
-
- submit_fill (qxl, &qrect, qxl->u.solid_pixel);
+ qxl_surface_solid (get_surface (pixmap), x1, y1, x2, y2);
}
static void
@@ -1070,30 +963,17 @@ static Bool
qxl_check_copy (PixmapPtr source, PixmapPtr dest,
int alu, Pixel planemask)
{
- if (!UXA_PM_IS_SOLID (&source->drawable, planemask))
- {
- ErrorF ("non solid planemask\n");
+ if (!good_alu_and_pm ((DrawablePtr)source, alu, planemask))
return FALSE;
- }
if (source->drawable.bitsPerPixel != dest->drawable.bitsPerPixel)
{
- ErrorF ("differing bitsperpixel\n");
+ ErrorF ("differing bitsperpixel - this shouldn't happen\n");
return FALSE;
}
-
- if (source->drawable.bitsPerPixel != 16 && source->drawable.bitsPerPixel != 32)
- {
- ErrorF ("bad bpp\n");
- return FALSE;
- }
-
- /* FIXME: support other rops */
- if (alu != GXcopy)
- {
- ErrorF ("not gxcopy\n");
+
+ if (!get_surface (source) || !get_surface (dest))
return FALSE;
- }
return TRUE;
}
@@ -1103,13 +983,7 @@ qxl_prepare_copy (PixmapPtr source, PixmapPtr dest,
int xdir, int ydir, int alu,
Pixel planemask)
{
- ScreenPtr pScreen = source->drawable.pScreen;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- qxl_screen_t *qxl = pScrn->driverPrivate;
-
- qxl->u.copy_source = source;
-
- return TRUE;
+ return qxl_surface_prepare_copy (get_surface (dest), get_surface (source));
}
static Bool
@@ -1118,29 +992,11 @@ qxl_copy (PixmapPtr dest,
int dest_x1, int dest_y1,
int width, int height)
{
- ScreenPtr pScreen = dest->drawable.pScreen;
- ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- qxl_screen_t *qxl = pScrn->driverPrivate;
- struct qxl_drawable *drawable;
- struct qxl_rect qrect;
-
- assert (qxl->u.copy_source == pScreen->GetScreenPixmap (pScreen));
-
- qrect.top = dest_y1;
- qrect.bottom = dest_y1 + height;
- qrect.left = dest_x1;
- qrect.right = dest_x1 + width;
+ qxl_surface_copy (get_surface (dest),
+ src_x1, src_y1,
+ dest_x1, dest_y1,
+ width, height);
-/* ErrorF (" Translate %d %d %d %d by %d %d (offsets %d %d)\n", */
-/* b->x1, b->y1, b->x2, b->y2, */
-/* dx, dy, dst_xoff, dst_yoff); */
-
- drawable = make_drawable (qxl, QXL_COPY_BITS, &qrect);
- drawable->u.copy_bits.src_pos.x = src_x1;
- drawable->u.copy_bits.src_pos.y = src_y1;
-
- push_drawable (qxl, drawable);
-
return TRUE;
}
@@ -1149,74 +1005,135 @@ qxl_done_copy (PixmapPtr dest)
{
}
-static Bool
-setup_uxa (qxl_screen_t *qxl, ScreenPtr screen)
+static void
+qxl_set_screen_pixmap (PixmapPtr pixmap)
{
- ScrnInfoPtr scrn = xf86Screens[screen->myNum];
-
- if (!dixRequestPrivate(&uxa_pixmap_index, 0))
- return FALSE;
-
- qxl->uxa = uxa_driver_alloc();
- if (qxl->uxa == NULL)
- return FALSE;
-
- memset(qxl->uxa, 0, sizeof(*qxl->uxa));
-
- qxl->uxa->uxa_major = 1;
- qxl->uxa->uxa_minor = 0;
+ ErrorF ("asdf\n");
- /* Solid fill */
- qxl->uxa->check_solid = unaccel; // qxl_check_solid;
- qxl->uxa->prepare_solid = unaccel; // qxl_prepare_solid;
- qxl->uxa->solid = unaccel; // qxl_solid;
- qxl->uxa->done_solid = unaccel; // qxl_done_solid;
-
- /* Copy */
- qxl->uxa->check_copy = unaccel; // qxl_check_copy;
- qxl->uxa->prepare_copy = unaccel; // qxl_prepare_copy;
- qxl->uxa->copy = unaccel; // qxl_copy;
- qxl->uxa->done_copy = unaccel; // qxl_done_copy;
+ pixmap->drawable.pScreen->devPrivate = pixmap;
+}
- /* Composite */
- qxl->uxa->check_composite = unaccel;
- qxl->uxa->check_composite_target = unaccel;
- qxl->uxa->check_composite_texture = unaccel;
- qxl->uxa->prepare_composite = unaccel;
- qxl->uxa->composite = unaccel;
- qxl->uxa->done_composite = unaccel;
+static PixmapPtr
+qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ PixmapPtr pixmap;
+ qxl_screen_t *qxl = scrn->driverPrivate;
+ qxl_surface_t *surface;
+
+ if (w > 32767 || h > 32767)
+ return NULL;
- /* PutImage */
- qxl->uxa->put_image = unaccel;
+#if 0
+ ErrorF ("Create pixmap: %d %d @ %d (usage: %d)\n", w, h, depth, usage);
+#endif
+
+ surface = qxl_surface_create (qxl, w, h, depth);
+
+ if (surface)
+ {
+ ErrorF (" Successfully created surface in video memory\n");
+
+ pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
+
+ set_surface (pixmap, surface);
+ }
+ else
+ {
+#if 0
+ ErrorF (" Couldn't allocate %d x %d @ %d surface in video memory\n",
+ w, h, depth);
+#endif
- /* Prepare access */
- qxl->uxa->prepare_access = qxl_prepare_access;
- qxl->uxa->finish_access = qxl_finish_access;
+ pixmap = fbCreatePixmap (screen, w, h, depth, usage);
+ }
+
+ return pixmap;
+}
- qxl->uxa->pixmap_is_offscreen = qxl_pixmap_is_offscreen;
+static Bool
+qxl_destroy_pixmap (PixmapPtr pixmap)
+{
+ qxl_surface_t *surface;
-#if 0
- screen->CreatePixmap = qxl_create_pixmap;
- screen->DestroyPixmap = qxl_destroy_pixmap;
-#endif
+ if (pixmap->refcnt == 1 && (surface = get_surface (pixmap)))
+ {
+ qxl_surface_destroy (surface);
+ set_surface (pixmap, NULL);
+ }
+
+ fbDestroyPixmap (pixmap);
+ return TRUE;
+}
- if (!uxa_driver_init(screen, qxl->uxa)) {
- xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "UXA initialization failed\n");
- xfree(qxl->uxa);
- return FALSE;
- }
+static Bool
+setup_uxa (qxl_screen_t *qxl, ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+
+ if (!dixRequestPrivate(&uxa_pixmap_index, 0))
+ return FALSE;
+
+ qxl->uxa = uxa_driver_alloc();
+ if (qxl->uxa == NULL)
+ return FALSE;
+
+ memset(qxl->uxa, 0, sizeof(*qxl->uxa));
+
+ qxl->uxa->uxa_major = 1;
+ qxl->uxa->uxa_minor = 0;
+
+ /* Solid fill */
+ qxl->uxa->check_solid = qxl_check_solid;
+ qxl->uxa->prepare_solid = qxl_prepare_solid;
+ qxl->uxa->solid = qxl_solid;
+ qxl->uxa->done_solid = qxl_done_solid;
+
+ /* Copy */
+ qxl->uxa->check_copy = qxl_check_copy;
+ qxl->uxa->prepare_copy = qxl_prepare_copy;
+ qxl->uxa->copy = qxl_copy;
+ qxl->uxa->done_copy = qxl_done_copy;
+
+ /* Composite */
+ qxl->uxa->check_composite = unaccel;
+ qxl->uxa->check_composite_target = unaccel;
+ qxl->uxa->check_composite_texture = unaccel;
+ qxl->uxa->prepare_composite = unaccel;
+ qxl->uxa->composite = unaccel;
+ qxl->uxa->done_composite = unaccel;
+
+ /* PutImage */
+ qxl->uxa->put_image = unaccel;
+
+ /* Prepare access */
+ qxl->uxa->prepare_access = qxl_prepare_access;
+ qxl->uxa->finish_access = qxl_finish_access;
+
+ qxl->uxa->pixmap_is_offscreen = qxl_pixmap_is_offscreen;
+ screen->SetScreenPixmap = qxl_set_screen_pixmap;
+ screen->CreatePixmap = qxl_create_pixmap;
+ screen->DestroyPixmap = qxl_destroy_pixmap;
+
+ if (!uxa_driver_init(screen, qxl->uxa))
+ {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "UXA initialization failed\n");
+ xfree(qxl->uxa);
+ return FALSE;
+ }
+
#if 0
- uxa_set_fallback_debug(screen, FALSE);
+ uxa_set_fallback_debug(screen, FALSE);
#endif
-
+
#if 0
- if (!uxa_driver_init (screen, qxl->uxa))
- return FALSE;
+ if (!uxa_driver_init (screen, qxl->uxa))
+ return FALSE;
#endif
-
- return TRUE;
+
+ return TRUE;
}
static Bool
@@ -1227,17 +1144,17 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
struct qxl_rom *rom;
struct qxl_ram_header *ram_header;
VisualPtr visual;
-
+
CHECK_POINT();
-
+
qxl->pScrn = pScrn;
if (!qxl_map_memory(qxl, scrnIndex))
return FALSE;
-
+
rom = qxl->rom;
ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
-
+
printf ("ram_header at %d\n", qxl->rom->ram_header_offset);
printf ("surf0 size: %d\n", qxl->rom->surface0_area_size);
@@ -1250,13 +1167,19 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
goto out;
if (!miSetPixmapDepths())
goto out;
-
+
+ qxl->virtual_x = pScrn->virtualX;
+ qxl->virtual_y = pScrn->virtualY;
+ qxl->stride = pScrn->virtualX * 4;
+
pScrn->displayWidth = pScrn->virtualX;
-
- qxl->fb = xcalloc(pScrn->virtualY * pScrn->displayWidth, 4);
+
+ qxl->fb = xcalloc (pScrn->virtualY * pScrn->displayWidth, 4);
if (!qxl->fb)
goto out;
-
+
+ ErrorF ("allocated %d x %d %p\n", pScrn->virtualX, pScrn->virtualY, qxl->fb);
+
if (!fbScreenInit(pScreen, qxl->fb,
pScrn->virtualX, pScrn->virtualY,
pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth,
@@ -1264,7 +1187,7 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
{
goto out;
}
-
+
visual = pScreen->visuals + pScreen->numVisuals;
while (--visual >= pScreen->visuals)
{
@@ -1278,25 +1201,17 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
visual->blueMask = pScrn->mask.blue;
}
}
-
fbPictureInit(pScreen, NULL, 0);
-
+
qxl->uxa = uxa_driver_alloc ();
-
- setup_uxa (qxl, pScreen);
- qxl->create_screen_resources = pScreen->CreateScreenResources;
- pScreen->CreateScreenResources = qxl_create_screen_resources;
-
/* Set up resources */
qxl_reset (qxl);
- qxl->mem = qxl_mem_create ((void *)((unsigned long)qxl->ram + qxl->surface0_size),
- rom->num_pages * getpagesize() - qxl->surface0_size);
qxl->io_pages = (void *)((unsigned long)qxl->ram);
qxl->io_pages_physical = (void *)((unsigned long)qxl->ram_physical);
-
+
qxl->command_ring = qxl_ring_create (&(ram_header->cmd_ring_hdr),
sizeof (struct qxl_command),
32, qxl->io_base + QXL_IO_NOTIFY_CMD);
@@ -1307,25 +1222,38 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
sizeof (uint64_t),
8, 0);
+ qxl_surface_init (qxl, qxl->rom->n_surfaces);
+
/* xf86DPMSInit(pScreen, xf86DPMSSet, 0); */
-
+
pScreen->SaveScreen = qxl_blank_screen;
-
+
+ setup_uxa (qxl, pScreen);
+
+ qxl->create_screen_resources = pScreen->CreateScreenResources;
+ pScreen->CreateScreenResources = qxl_create_screen_resources;
+
+ qxl->close_screen = pScreen->CloseScreen;
+ pScreen->CloseScreen = qxl_close_screen;
+
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
-
+
if (!miCreateDefColormap(pScreen))
goto out;
-
+
qxl_cursor_init (pScreen);
CHECK_POINT();
+ pScreen->width = pScrn->currentMode->HDisplay;
+ pScreen->height = pScrn->currentMode->VDisplay;
+
qxl_switch_mode(scrnIndex, pScrn->currentMode, 0);
-
+
CHECK_POINT();
return TRUE;
-
+
out:
return FALSE;
}
@@ -1335,9 +1263,9 @@ qxl_enter_vt(int scrnIndex, int flags)
{
ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
qxl_screen_t *qxl = pScrn->driverPrivate;
-
+
qxl_save_state(qxl);
-
+
qxl_switch_mode(scrnIndex, pScrn->currentMode, 0);
return TRUE;
}
@@ -1346,7 +1274,7 @@ static void
qxl_leave_vt(int scrnIndex, int flags)
{
qxl_screen_t *qxl = xf86Screens[scrnIndex]->driverPrivate;
-
+
qxl_restore_state(qxl);
}
@@ -1356,10 +1284,10 @@ qxl_color_setup(ScrnInfoPtr pScrn)
int scrnIndex = pScrn->scrnIndex;
Gamma gzeros = { 0.0, 0.0, 0.0 };
rgb rzeros = { 0, 0, 0 };
-
+
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
return FALSE;
-
+
if (pScrn->depth != 15 && pScrn->depth != 24)
{
xf86DrvMsg(scrnIndex, X_ERROR, "Depth %d is not supported\n",
@@ -1367,16 +1295,16 @@ qxl_color_setup(ScrnInfoPtr pScrn)
return FALSE;
}
xf86PrintDepthBpp(pScrn);
-
+
if (!xf86SetWeight(pScrn, rzeros, rzeros))
return FALSE;
-
+
if (!xf86SetDefaultVisual(pScrn, -1))
return FALSE;
-
+
if (!xf86SetGamma(pScrn, gzeros))
return FALSE;
-
+
return TRUE;
}
@@ -1384,11 +1312,11 @@ static void
print_modes (qxl_screen_t *qxl, int scrnIndex)
{
int i;
-
+
for (i = 0; i < qxl->num_modes; ++i)
{
struct qxl_mode *m = qxl->modes + i;
-
+
xf86DrvMsg (scrnIndex, X_INFO,
"%d: %dx%d, %d bits, stride %d, %dmm x %dmm, orientation %d\n",
m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili,
@@ -1402,40 +1330,42 @@ qxl_check_device(ScrnInfoPtr pScrn, qxl_screen_t *qxl)
int scrnIndex = pScrn->scrnIndex;
struct qxl_rom *rom = qxl->rom;
struct qxl_ram_header *ram_header = (void *)((unsigned long)qxl->ram + rom->ram_header_offset);
-
+
CHECK_POINT();
if (rom->magic != 0x4f525851) { /* "QXRO" little-endian */
xf86DrvMsg(scrnIndex, X_ERROR, "Bad ROM signature %x\n", rom->magic);
return FALSE;
}
-
+
xf86DrvMsg(scrnIndex, X_INFO, "Device version %d.%d\n",
rom->id, rom->update_id);
-
+
xf86DrvMsg(scrnIndex, X_INFO, "Compression level %d, log level %d\n",
rom->compression_level,
rom->log_level);
-
+
xf86DrvMsg(scrnIndex, X_INFO, "%d io pages at 0x%lx\n",
rom->num_pages, (unsigned long)qxl->ram);
-
+
xf86DrvMsg(scrnIndex, X_INFO, "RAM header offset: 0x%x\n", rom->ram_header_offset);
-
+
if (ram_header->magic != 0x41525851) { /* "QXRA" little-endian */
xf86DrvMsg(scrnIndex, X_ERROR, "Bad RAM signature %x at %p\n",
ram_header->magic,
&ram_header->magic);
return FALSE;
}
-
+
xf86DrvMsg(scrnIndex, X_INFO, "Correct RAM signature %x\n",
ram_header->magic);
-
+
pScrn->videoRam = (rom->num_pages * 4096) / 1024;
-
+
xf86DrvMsg(scrnIndex, X_INFO, "%d KB of video RAM\n", pScrn->videoRam);
+ xf86DrvMsg(scrnIndex, X_INFO, "%d surfaces\n", rom->n_surfaces);
+
return TRUE;
}
@@ -1444,13 +1374,13 @@ qxl_find_native_mode(ScrnInfoPtr pScrn, DisplayModePtr p)
{
int i;
qxl_screen_t *qxl = pScrn->driverPrivate;
-
+
CHECK_POINT();
for (i = 0; i < qxl->num_modes; i++)
{
struct qxl_mode *m = qxl->modes + i;
-
+
if (m->x_res == p->HDisplay &&
m->y_res == p->VDisplay &&
m->bits == pScrn->bitsPerPixel)
@@ -1469,7 +1399,7 @@ qxl_find_native_mode(ScrnInfoPtr pScrn, DisplayModePtr p)
}
}
}
-
+
return -1;
}
@@ -1481,7 +1411,7 @@ qxl_valid_mode(int scrn, DisplayModePtr p, Bool flag, int pass)
qxl_screen_t *qxl = pScrn->driverPrivate;
int bpp = pScrn->bitsPerPixel;
int mode_idx;
-
+
/* FIXME: I don't think this is necessary now that we report the
* correct amount of video ram?
*/
@@ -1490,7 +1420,7 @@ qxl_valid_mode(int scrn, DisplayModePtr p, Bool flag, int pass)
xf86DrvMsg(scrnIndex, X_INFO, "rejecting mode %d x %d: insufficient memory\n", p->HDisplay, p->VDisplay);
return MODE_MEM;
}
-
+
mode_idx = qxl_find_native_mode (pScrn, p);
if (mode_idx == -1)
{
@@ -1498,7 +1428,7 @@ qxl_valid_mode(int scrn, DisplayModePtr p, Bool flag, int pass)
return MODE_NOMODE;
}
p->Private = (void *)(unsigned long)mode_idx;
-
+
xf86DrvMsg (scrnIndex, X_INFO, "accepting %d x %d\n", p->HDisplay, p->VDisplay);
return MODE_OK;
@@ -1511,7 +1441,7 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
qxl_screen_t *qxl = NULL;
ClockRangePtr clockRanges = NULL;
int *linePitches = NULL;
-
+
CHECK_POINT();
/* zaphod mode is for suckers and i choose not to implement it */
@@ -1519,7 +1449,7 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(scrnIndex, X_ERROR, "No Zaphod mode for you\n");
return FALSE;
}
-
+
if (!pScrn->driverPrivate)
pScrn->driverPrivate = xnfcalloc(sizeof(qxl_screen_t), 1);
qxl = pScrn->driverPrivate;
@@ -1529,23 +1459,23 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
#ifndef XSERVER_LIBPCIACCESS
qxl->pci_tag = pciTag(qxl->pci->bus, qxl->pci->device, qxl->pci->func);
#endif
-
+
pScrn->monitor = pScrn->confScreen->monitor;
-
+
if (!qxl_color_setup(pScrn))
goto out;
-
+
/* option parsing and card differentiation */
xf86CollectOptions(pScrn, NULL);
if (!qxl_map_memory(qxl, scrnIndex))
goto out;
-
+
if (!qxl_check_device(pScrn, qxl))
goto out;
-
+
/* ddc stuff here */
-
+
clockRanges = xnfcalloc(sizeof(ClockRange), 1);
clockRanges->next = NULL;
clockRanges->minClock = 10000;
@@ -1554,7 +1484,7 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
clockRanges->interlaceAllowed = clockRanges->doubleScanAllowed = 0;
clockRanges->ClockMulFactor = clockRanges->ClockDivFactor = 1;
pScrn->progClock = TRUE;
-
+
/* override QXL monitor stuff */
if (pScrn->monitor->nHsync <= 0) {
pScrn->monitor->hsync[0].lo = 31.5;
@@ -1566,12 +1496,12 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
pScrn->monitor->vrefresh[0].hi = 70;
pScrn->monitor->nVrefresh = 1;
}
-
+
if (pScrn->display->virtualX == 0 && pScrn->display->virtualY == 0) {
pScrn->display->virtualX = 1024;
pScrn->display->virtualY = 768;
}
-
+
if (0 >= xf86ValidateModes(pScrn, pScrn->monitor->Modes,
pScrn->display->modes, clockRanges, linePitches,
128, 2048, 128 * 4, 128, 2048,
@@ -1579,36 +1509,36 @@ qxl_pre_init(ScrnInfoPtr pScrn, int flags)
pScrn->display->virtualY,
128 * 1024 * 1024, LOOKUP_BEST_REFRESH))
goto out;
-
+
CHECK_POINT();
xf86PruneDriverModes(pScrn);
pScrn->currentMode = pScrn->modes;
xf86PrintModes(pScrn);
xf86SetDpi(pScrn, 0, 0);
-
+
if (!xf86LoadSubModule(pScrn, "fb") ||
!xf86LoadSubModule(pScrn, "ramdac"))
{
goto out;
}
-
+
print_modes (qxl, scrnIndex);
-
+
/* hate */
qxl_unmap_memory(qxl, scrnIndex);
-
+
CHECK_POINT();
xf86DrvMsg(scrnIndex, X_INFO, "PreInit complete\n");
return TRUE;
-
+
out:
if (clockRanges)
xfree(clockRanges);
if (qxl)
xfree(qxl);
-
+
return FALSE;
}
@@ -1627,7 +1557,7 @@ static const struct pci_id_match qxl_device_match[] = {
PCI_VENDOR_RED_HAT, PCI_CHIP_QXL_01FF, PCI_MATCH_ANY, PCI_MATCH_ANY,
0x00030000, 0x00ffffff, CHIP_QXL_1
},
-
+
{ 0 },
};
#endif
@@ -1673,37 +1603,37 @@ qxl_probe(DriverPtr drv, int flags)
int numDevSections;
int *usedChips;
GDevPtr *devSections;
-
+
if ((numDevSections = xf86MatchDevice(QXL_NAME, &devSections)) <= 0)
return FALSE;
-
+
if (!xf86GetPciVideoInfo())
return FALSE;
-
+
numUsed = xf86MatchPciInstances(QXL_NAME, PCI_VENDOR_RED_HAT,
qxlChips, qxlPciChips,
devSections, numDevSections,
drv, &usedChips);
-
+
xfree(devSections);
-
+
if (numUsed < 0) {
xfree(usedChips);
return FALSE;
}
-
+
if (flags & PROBE_DETECT) {
xfree(usedChips);
return TRUE;
}
-
+
for (i = 0; i < numUsed; i++) {
ScrnInfoPtr pScrn = NULL;
if ((pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], qxlPciChips,
0, 0, 0, 0, 0)))
qxl_init_scrn(pScrn);
}
-
+
xfree(usedChips);
return TRUE;
}
@@ -1716,17 +1646,17 @@ qxl_pci_probe(DriverPtr drv, int entity, struct pci_device *dev, intptr_t match)
qxl_screen_t *qxl;
ScrnInfoPtr pScrn = xf86ConfigPciEntity(NULL, 0, entity, NULL, NULL,
NULL, NULL, NULL, NULL);
-
+
if (!pScrn)
return FALSE;
-
+
if (!pScrn->driverPrivate)
pScrn->driverPrivate = xnfcalloc(sizeof(qxl_screen_t), 1);
qxl = pScrn->driverPrivate;
qxl->pci = dev;
-
+
qxl_init_scrn(pScrn);
-
+
return TRUE;
}
@@ -1753,7 +1683,7 @@ static pointer
qxl_setup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool loaded = FALSE;
-
+
if (!loaded) {
loaded = TRUE;
xf86AddDriver(&qxl_driver, module, HaveDriverFuncs);
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
new file mode 100644
index 0000000..3b177fe
--- /dev/null
+++ b/src/qxl_surface.c
@@ -0,0 +1,748 @@
+#include "qxl.h"
+
+struct qxl_surface_t
+{
+ qxl_screen_t * qxl;
+
+ uint32_t id;
+
+ pixman_image_t * dev_image;
+ pixman_image_t * host_image;
+
+ RegionRec access_region;
+
+ void * address;
+
+ qxl_surface_t * next;
+ int in_use;
+
+ union
+ {
+ qxl_surface_t *copy_src;
+ Pixel solid_pixel;
+ } u;
+};
+
+static qxl_surface_t *all_surfaces;
+static qxl_surface_t *free_surfaces;
+
+#if 0
+void
+qxl_surface_free_all (qxl_screen_t *qxl)
+{
+ for (i = 0; i < qxl->rom->n_surfaces; ++i)
+ {
+ qxl_surface_t *surface = &(all_surfaces[i]);
+ if (surface->in_use)
+ {
+
+ }
+ }
+}
+#endif
+
+void
+qxl_surface_init (qxl_screen_t *qxl, int n_surfaces)
+{
+ int i;
+
+ if (!all_surfaces)
+ all_surfaces = calloc (n_surfaces, sizeof (qxl_surface_t));
+
+ for (i = 0; i < n_surfaces; ++i)
+ {
+ all_surfaces[i].id = i;
+ all_surfaces[i].qxl = qxl;
+ all_surfaces[i].dev_image = NULL;
+ all_surfaces[i].host_image = NULL;
+
+ REGION_INIT (NULL, &(all_surfaces[i].access_region), (BoxPtr)NULL, 0);
+
+ if (i) /* surface 0 is the primary surface */
+ {
+ all_surfaces[i].next = free_surfaces;
+ free_surfaces = &(all_surfaces[i]);
+ all_surfaces[i].in_use = FALSE;
+ }
+ }
+}
+
+static qxl_surface_t *
+surface_new (void)
+{
+ qxl_surface_t *result = NULL;
+
+ if (free_surfaces)
+ {
+ result = free_surfaces;
+ free_surfaces = free_surfaces->next;
+ }
+
+ result->next = NULL;
+ result->in_use = TRUE;
+
+ return result;
+}
+
+static void
+surface_free (qxl_surface_t *surface)
+{
+ surface->next = free_surfaces;
+ free_surfaces = surface;
+}
+
+qxl_surface_t *
+qxl_surface_create_primary (qxl_screen_t *qxl,
+ struct qxl_mode *mode)
+{
+ struct qxl_ram_header *ram_header =
+ (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset);
+ struct qxl_surface_create *create = &(ram_header->create_surface);
+ pixman_format_code_t format;
+ uint8_t *dev_addr;
+ pixman_image_t *dev_image, *host_image;
+ qxl_surface_t *surface;
+
+ if (mode->bits == 16)
+ {
+ format = PIXMAN_x1r5g5b5;
+ }
+ else if (mode->bits == 32)
+ {
+ format = PIXMAN_x8r8g8b8;
+ }
+ else
+ {
+ xf86DrvMsg (qxl->pScrn->scrnIndex, X_ERROR,
+ "Unknown bit depth %d\n", mode->bits);
+ return NULL;
+ }
+
+ create->width = mode->x_res;
+ create->height = mode->y_res;
+ create->stride = - mode->stride;
+ create->depth = mode->bits;
+ create->position = 0; /* What is this? The Windows driver doesn't use it */
+ create->flags = 0;
+ create->type = QXL_SURF_TYPE_PRIMARY;
+ create->mem = physical_address (qxl, qxl->ram, qxl->main_mem_slot);
+
+ outb (qxl->io_base + QXL_IO_CREATE_PRIMARY, 0);
+
+ dev_addr = (uint8_t *)qxl->ram + mode->stride * (mode->y_res - 1);
+
+ dev_image = pixman_image_create_bits (format, mode->x_res, mode->y_res,
+ (uint32_t *)dev_addr, -mode->stride);
+
+ host_image = pixman_image_create_bits (format,
+ qxl->virtual_x, qxl->virtual_y,
+ qxl->fb, qxl->stride);
+
+ surface = malloc (sizeof *surface);
+ surface->id = 0;
+ surface->dev_image = dev_image;
+ surface->host_image = host_image;
+ surface->qxl = qxl;
+ REGION_INIT (NULL, &(surface->access_region), (BoxPtr)NULL, 0);
+
+ return surface;
+}
+
+static struct qxl_surface_cmd *
+make_surface_cmd (qxl_screen_t *qxl, uint32_t id, qxl_surface_cmd_type type)
+{
+ struct qxl_surface_cmd *cmd;
+
+ cmd = qxl_allocnf (qxl, sizeof *cmd);
+
+ cmd->release_info.id = pointer_to_u64 (cmd) | 2;
+ cmd->type = type;
+ cmd->flags = 0;
+ cmd->surface_id = id;
+
+ return cmd;
+}
+
+static void
+push_surface_cmd (qxl_screen_t *qxl, struct qxl_surface_cmd *cmd)
+{
+ struct qxl_command command;
+
+ if (!in_vga_mode (qxl))
+ {
+ command.type = QXL_CMD_SURFACE;
+ command.data = physical_address (qxl, cmd, qxl->main_mem_slot);
+
+ qxl_ring_push (qxl->command_ring, &command);
+ }
+}
+
+qxl_surface_t *
+qxl_surface_create (qxl_screen_t *qxl,
+ int width,
+ int height,
+ int bpp)
+{
+ qxl_surface_t *surface;
+ struct qxl_surface_cmd *cmd;
+ qxl_bitmap_format format;
+ pixman_format_code_t pformat;
+ int stride;
+ uint32_t *dev_addr;
+
+ /* This just doesn't work yet */
+ return NULL;
+
+#if 0
+ ErrorF (" qxl_surface: attempting to allocate %d x %d @ %d\n", width, height, bpp);
+#endif
+
+ if ((bpp & 3) != 0)
+ {
+ ErrorF (" Bad bpp: %d (%d)\n", bpp, bpp & 7);
+ return NULL;
+ }
+
+ if (bpp != 8 && bpp != 16 && bpp != 32 && bpp != 24)
+ {
+ ErrorF (" Unknown bpp\n");
+ return NULL;
+ }
+
+retry:
+ surface = surface_new();
+ if (!surface)
+ {
+ if (!qxl_handle_oom (qxl))
+ {
+ ErrorF (" Out of surfaces\n");
+ return NULL;
+ }
+ else
+ goto retry;
+ }
+
+#if 0
+ ErrorF (" Surface allocated: %u\n", surface->id);
+#endif
+
+ if (width == 0 || height == 0)
+ {
+ ErrorF (" Zero width or height\n");
+ return NULL;
+ }
+
+ stride = width * bpp / 8;
+ stride = (stride + 3) & ~3;
+
+ surface->address = qxl_alloc (qxl->surf_mem, stride * height);
+#if 0
+ ErrorF ("%d alloc address %lx from %p\n", surface->id, surface->address, qxl->surf_mem);
+#endif
+
+ if (!surface->address)
+ {
+ ErrorF (" Not enough vmem allocating %u\n", surface->id);
+
+ surface_free (surface);
+ return NULL;
+ }
+
+ cmd = make_surface_cmd (qxl, surface->id, QXL_SURFACE_CMD_CREATE);
+
+ switch (bpp)
+ {
+ case 8:
+ format = QXL_SURFACE_FMT_8_A;
+ pformat = PIXMAN_a8;
+ break;
+
+ case 16:
+ format = QXL_SURFACE_FMT_16_565;
+ pformat = PIXMAN_r5g6b5;
+ break;
+
+ case 24:
+ format = QXL_SURFACE_FMT_32_xRGB;
+ pformat = PIXMAN_a8r8g8b8;
+ break;
+
+ case 32:
+ format = QXL_SURFACE_FMT_32_ARGB;
+ pformat = PIXMAN_a8r8g8b8;
+ break;
+ }
+
+ cmd->u.surface_create.format = format;
+ cmd->u.surface_create.width = width;
+ cmd->u.surface_create.height = height;
+ cmd->u.surface_create.stride = - stride;
+ cmd->u.surface_create.physical = physical_address (
+ qxl, surface->address, qxl->vram_mem_slot);
+
+#if 0
+ ErrorF ("create %d\n", cmd->surface_id);
+#endif
+
+ push_surface_cmd (qxl, cmd);
+
+ dev_addr = (uint32_t *)((uint8_t *)surface->address + stride * (height - 1));
+
+ surface->dev_image = pixman_image_create_bits (
+ pformat, width, height, dev_addr, - stride);
+
+ surface->host_image = pixman_image_create_bits (
+ pformat, width, height, NULL, -1);
+
+#if 0
+ ErrorF (" Allocating %d %lx\n", surface->id, surface->address);
+#endif
+
+ return surface;
+}
+
+void
+qxl_surface_destroy (qxl_surface_t *surface)
+{
+ qxl_screen_t *qxl = surface->qxl;
+
+#if 0
+ ErrorF ("About to free %d\n", surface->id);
+#endif
+
+ if (surface->dev_image)
+ pixman_image_unref (surface->dev_image);
+ if (surface->host_image)
+ pixman_image_unref (surface->host_image);
+
+ if (surface->id != 0)
+ {
+ struct qxl_surface_cmd *cmd;
+#if 0
+ ErrorF ("%d free address %lx from %p\n", surface->id, surface->address, surface->qxl->surf_mem);
+#endif
+ cmd = make_surface_cmd (qxl, surface->id, QXL_SURFACE_CMD_DESTROY);
+
+#if 0
+ ErrorF (" pushing destroy command %lx\n", cmd->release_info.id);
+#endif
+#if 0
+ ErrorF ("destroy %d\n", cmd->surface_id);
+#endif
+
+ push_surface_cmd (qxl, cmd);
+ }
+}
+
+void
+qxl_surface_recycle (uint32_t id)
+{
+ qxl_surface_t *surface = all_surfaces + id;
+
+#if 0
+ ErrorF ("recycle %d\n", id);
+#endif
+
+ qxl_free (surface->qxl->surf_mem, surface->address);
+ surface_free (surface);
+}
+
+/* send anything pending to the other side */
+void
+qxl_surface_flush (qxl_surface_t *surface)
+{
+ ;
+}
+
+
+/* access */
+#if 0
+static void
+download_box (qxl_screen_t *qxl, uint8_t *host,
+ int x1, int y1, int x2, int y2)
+{
+ struct qxl_ram_header *ram_header = (void *)((unsigned long)qxl->ram +
+ qxl->rom->ram_header_offset);
+ int stride = - qxl->current_mode->stride;
+ int Bpp = qxl->current_mode->bits / 8;
+ uint8_t *host_line;
+ uint8_t *dev_line;
+ int height = y2 - y1;
+
+#if 0
+ ErrorF ("Downloading %d %d %d %d\n", x1, y1, x2, y2);
+#endif
+
+ ram_header->update_area.top = y1;
+ ram_header->update_area.bottom = y2;
+ ram_header->update_area.left = x1;
+ ram_header->update_area.right = x2;
+ ram_header->update_surface = 0; /* Only primary for now */
+
+ outb (qxl->io_base + QXL_IO_UPDATE_AREA, 0);
+
+ dev_line = ((uint8_t *)qxl->ram) +
+ (qxl->current_mode->y_res - 1) * (-stride) + /* top of frame buffer */
+ y1 * stride + /* first line */
+ x1 * Bpp;
+ host_line = host + y1 * stride + x1 * Bpp;
+
+#if 0
+ ErrorF ("stride: %d\n", stride);
+#endif
+
+ while (height--)
+ {
+ uint8_t *h = host_line;
+ uint8_t *d = dev_line;
+ int w = (x2 - x1) * Bpp;
+
+ host_line += stride;
+ dev_line += stride;
+
+ while (w--)
+ *h++ = *d++;
+ }
+}
+#endif
+
+static void
+download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
+{
+ struct qxl_ram_header *ram_header = get_ram_header (surface->qxl);
+
+#if 0
+ ErrorF ("Downloading %d %d %d %d\n", x1, y1, x2 - x1, y2 - y1);
+#endif
+
+ ram_header->update_area.top = y1;
+ ram_header->update_area.bottom = y2;
+ ram_header->update_area.left = x1;
+ ram_header->update_area.right = x2;
+ ram_header->update_surface = surface->id;
+
+ outb (surface->qxl->io_base + QXL_IO_UPDATE_AREA, 0);
+
+ pixman_image_composite (PIXMAN_OP_SRC,
+ surface->dev_image,
+ NULL,
+ surface->host_image,
+ x1, y1, 0, 0, x1, y1, x2 - x1, y2 - y1);
+}
+
+Bool
+qxl_surface_prepare_access (qxl_surface_t *surface,
+ PixmapPtr pixmap,
+ RegionPtr region,
+ uxa_access_t access)
+{
+ int n_boxes;
+ BoxPtr boxes;
+ ScreenPtr pScreen = pixmap->drawable.pScreen;
+ RegionRec new;
+
+ REGION_INIT (NULL, &new, (BoxPtr)NULL, 0);
+ REGION_SUBTRACT (NULL, &new, region, &surface->access_region);
+
+ region = &new;
+
+ n_boxes = REGION_NUM_RECTS (region);
+ boxes = REGION_RECTS (region);
+
+#if 0
+ ErrorF ("Preparing access to %d boxes\n", n_boxes);
+#endif
+
+ if (n_boxes < 25)
+ {
+ while (n_boxes--)
+ {
+ download_box (surface, boxes->x1, boxes->y1, boxes->x2, boxes->y2);
+
+ boxes++;
+ }
+ }
+ else
+ {
+#if 0
+ ErrorF ("Downloading extents (%d > %d)\n", n_boxes, 25);
+#endif
+
+ download_box (surface, new.extents.x1, new.extents.y1, new.extents.x2, new.extents.y2);
+ }
+
+ REGION_UNION (pScreen,
+ &(surface->access_region),
+ &(surface->access_region),
+ region);
+
+ REGION_UNINIT (NULL, &new);
+
+ pScreen->ModifyPixmapHeader(
+ pixmap,
+#if 0
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+#endif
+ pixman_image_get_width (surface->host_image),
+ pixman_image_get_height (surface->host_image),
+ -1, -1, -1,
+ pixman_image_get_data (surface->host_image));
+
+ pixmap->devKind = pixman_image_get_stride (surface->host_image);
+
+#if 0
+ ErrorF ("stride %d\n", pixmap->devKind);
+ ErrorF ("height %d\n", pixmap->drawable.height);
+#endif
+
+ return TRUE;
+}
+
+static void
+translate_rect (struct qxl_rect *rect)
+{
+ rect->right -= rect->left;
+ rect->bottom -= rect->top;
+ rect->left = rect->top = 0;
+}
+
+static struct qxl_drawable *
+make_drawable (qxl_screen_t *qxl, int surface, uint8_t type,
+ const struct qxl_rect *rect
+ /* , pRegion clip */)
+{
+ struct qxl_drawable *drawable;
+ int i;
+
+ drawable = qxl_allocnf (qxl, sizeof *drawable);
+
+ drawable->release_info.id = pointer_to_u64 (drawable);
+
+ drawable->type = type;
+
+ drawable->surface_id = 0; /* Only primary for now */
+ drawable->effect = QXL_EFFECT_OPAQUE;
+ drawable->self_bitmap = 0;
+ drawable->self_bitmap_area.top = 0;
+ drawable->self_bitmap_area.left = 0;
+ drawable->self_bitmap_area.bottom = 0;
+ drawable->self_bitmap_area.right = 0;
+ /* FIXME: add clipping */
+ drawable->clip.type = QXL_CLIP_TYPE_NONE;
+
+ /* FIXME: What are you supposed to put in surfaces_dest and surfaces_rects? */
+ for (i = 0; i < 3; ++i)
+ drawable->surfaces_dest[i] = -1;
+
+ if (rect)
+ drawable->bbox = *rect;
+
+ drawable->mm_time = qxl->rom->mm_clock;
+
+ return drawable;
+}
+
+static void
+push_drawable (qxl_screen_t *qxl, struct qxl_drawable *drawable)
+{
+ struct qxl_command cmd;
+
+ /* When someone runs "init 3", the device will be
+ * switched into VGA mode and there is nothing we
+ * can do about it. We get no notification.
+ *
+ * However, if commands are submitted when the device
+ * is in VGA mode, they will be queued up, and then
+ * the next time a mode set set, an assertion in the
+ * device will take down the entire virtual machine.
+ */
+ if (!in_vga_mode (qxl))
+ {
+ cmd.type = QXL_CMD_DRAW;
+ cmd.data = physical_address (qxl, drawable, qxl->main_mem_slot);
+
+ qxl_ring_push (qxl->command_ring, &cmd);
+ }
+}
+
+enum ROPDescriptor
+{
+ ROPD_INVERS_SRC = (1 << 0),
+ ROPD_INVERS_BRUSH = (1 << 1),
+ ROPD_INVERS_DEST = (1 << 2),
+ ROPD_OP_PUT = (1 << 3),
+ ROPD_OP_OR = (1 << 4),
+ ROPD_OP_AND = (1 << 5),
+ ROPD_OP_XOR = (1 << 6),
+ ROPD_OP_BLACKNESS = (1 << 7),
+ ROPD_OP_WHITENESS = (1 << 8),
+ ROPD_OP_INVERS = (1 << 9),
+ ROPD_INVERS_RES = (1 <<10),
+};
+
+static void
+submit_fill (qxl_screen_t *qxl, int id,
+ const struct qxl_rect *rect, uint32_t color)
+{
+ struct qxl_drawable *drawable;
+
+ drawable = make_drawable (qxl, id, QXL_DRAW_FILL, rect);
+
+ drawable->u.fill.brush.type = QXL_BRUSH_TYPE_SOLID;
+ drawable->u.fill.brush.u.color = color;
+ drawable->u.fill.rop_descriptor = ROPD_OP_PUT;
+ drawable->u.fill.mask.flags = 0;
+ drawable->u.fill.mask.pos.x = 0;
+ drawable->u.fill.mask.pos.y = 0;
+ drawable->u.fill.mask.bitmap = 0;
+
+ push_drawable (qxl, drawable);
+}
+
+static void
+upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
+{
+ struct qxl_rect rect;
+ struct qxl_drawable *drawable;
+ struct qxl_image *image;
+ qxl_screen_t *qxl = surface->qxl;
+ uint32_t *data;
+ int stride;
+
+ rect.left = x1;
+ rect.right = x2;
+ rect.top = y1;
+ rect.bottom = y2;
+
+#if 0
+ /* Paint a green flash before uploading */
+ submit_fill (qxl, surface->id, &rect, 0xff00ff00);
+#endif
+
+ drawable = make_drawable (qxl, surface->id, QXL_DRAW_COPY, &rect);
+ drawable->u.copy.src_area = rect;
+ translate_rect (&drawable->u.copy.src_area);
+ drawable->u.copy.rop_descriptor = ROPD_OP_PUT;
+ drawable->u.copy.scale_mode = 0;
+ drawable->u.copy.mask.flags = 0;
+ drawable->u.copy.mask.pos.x = 0;
+ drawable->u.copy.mask.pos.y = 0;
+ drawable->u.copy.mask.bitmap = 0;
+
+ data = pixman_image_get_data (surface->host_image);
+ stride = pixman_image_get_stride (surface->host_image);
+
+ image = qxl_image_create (
+ qxl, (const uint8_t *)data, x1, y1, x2 - x1, y2 - y1, stride);
+ drawable->u.copy.src_bitmap =
+ physical_address (qxl, image, qxl->main_mem_slot);
+
+ push_drawable (qxl, drawable);
+}
+
+void
+qxl_surface_finish_access (qxl_surface_t *surface, PixmapPtr pixmap)
+{
+ ScreenPtr pScreen = pixmap->drawable.pScreen;
+ int w = pixmap->drawable.width;
+ int h = pixmap->drawable.height;
+ int n_boxes;
+ BoxPtr boxes;
+
+ n_boxes = REGION_NUM_RECTS (&surface->access_region);
+ boxes = REGION_RECTS (&surface->access_region);
+
+ if (n_boxes < 25)
+ {
+ while (n_boxes--)
+ {
+ upload_box (surface, boxes->x1, boxes->y1, boxes->x2, boxes->y2);
+
+ boxes++;
+ }
+ }
+ else
+ {
+ upload_box (surface,
+ surface->access_region.extents.x1,
+ surface->access_region.extents.y1,
+ surface->access_region.extents.x2,
+ surface->access_region.extents.y2);
+ }
+
+ REGION_EMPTY (pScreen, &surface->access_region);
+
+ pScreen->ModifyPixmapHeader(pixmap, w, h, -1, -1, 0, NULL);
+}
+
+
+/* solid */
+Bool
+qxl_surface_prepare_solid (qxl_surface_t *destination,
+ Pixel fg)
+{
+ destination->u.solid_pixel = fg;
+ return TRUE;
+}
+
+void
+qxl_surface_solid (qxl_surface_t *destination,
+ int x1,
+ int y1,
+ int x2,
+ int y2)
+{
+ qxl_screen_t *qxl = destination->qxl;
+ struct qxl_rect qrect;
+
+ qrect.top = y1;
+ qrect.bottom = y2;
+ qrect.left = x1;
+ qrect.right = x2;
+
+ submit_fill (qxl, destination->id, &qrect, destination->u.solid_pixel);
+}
+
+
+/* copy */
+Bool
+qxl_surface_prepare_copy (qxl_surface_t *dest,
+ qxl_surface_t *source)
+{
+ if (source->id != 0)
+ {
+ ErrorF ("bad surface\n");
+ return FALSE;
+ }
+
+ dest->u.copy_src = source;
+ return TRUE;
+}
+
+void
+qxl_surface_copy (qxl_surface_t *dest,
+ int src_x1, int src_y1,
+ int dest_x1, int dest_y1,
+ int width, int height)
+{
+ qxl_screen_t *qxl = dest->qxl;
+ struct qxl_drawable *drawable;
+ struct qxl_rect qrect;
+
+ qrect.top = dest_y1;
+ qrect.bottom = dest_y1 + height;
+ qrect.left = dest_x1;
+ qrect.right = dest_x1 + width;
+
+/* ErrorF (" Translate %d %d %d %d by %d %d (offsets %d %d)\n", */
+/* b->x1, b->y1, b->x2, b->y2, */
+/* dx, dy, dst_xoff, dst_yoff); */
+
+ drawable = make_drawable (qxl, dest->id, QXL_COPY_BITS, &qrect);
+ drawable->u.copy_bits.src_pos.x = src_x1;
+ drawable->u.copy_bits.src_pos.y = src_y1;
+
+ push_drawable (qxl, drawable);
+}
+
diff --git a/src/uxa/uxa-accel.c b/src/uxa/uxa-accel.c
index 73d1059..49870ed 100644
--- a/src/uxa/uxa-accel.c
+++ b/src/uxa/uxa-accel.c
@@ -509,7 +509,9 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
int src_off_x, src_off_y;
int dst_off_x, dst_off_y;
PixmapPtr pSrcPixmap, pDstPixmap;
-
+ RegionRec src_region;
+ RegionRec dst_region;
+
pSrcPixmap = uxa_get_drawable_pixmap(pSrcDrawable);
pDstPixmap = uxa_get_drawable_pixmap(pDstDrawable);
if (!pSrcPixmap || !pDstPixmap)
@@ -597,18 +599,34 @@ uxa_copy_n_to_n(DrawablePtr pSrcDrawable,
return;
fallback:
+#if 0
+ ErrorF ("falling back: %d boxes\n", nbox);
+#endif
+
+ pixman_region_init_rects (&dst_region, pbox, nbox);
+ REGION_INIT (NULL, &src_region, (BoxPtr)NULL, 0);
+ REGION_COPY (NULL, &src_region, &dst_region);
+ REGION_TRANSLATE (NULL, &src_region, dx, dy);
+
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
uxa_drawable_location(pSrcDrawable),
uxa_drawable_location(pDstDrawable)));
- if (uxa_prepare_access(pDstDrawable, NULL, UXA_ACCESS_RW)) {
- if (uxa_prepare_access(pSrcDrawable, NULL, UXA_ACCESS_RO)) {
- fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
- dx, dy, reverse, upsidedown, bitplane,
- closure);
- uxa_finish_access(pSrcDrawable);
- }
- uxa_finish_access(pDstDrawable);
+ if (uxa_prepare_access(pDstDrawable, &dst_region, UXA_ACCESS_RW))
+ {
+ if (uxa_prepare_access(pSrcDrawable, &src_region, UXA_ACCESS_RO))
+ {
+ fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
+ dx, dy, reverse, upsidedown, bitplane,
+ closure);
+
+ uxa_finish_access(pSrcDrawable);
+ }
+
+ uxa_finish_access(pDstDrawable);
}
+
+ REGION_UNINIT (NULL, &src_region);
+ REGION_UNINIT (NULL, &dst_region);
}
RegionPtr
@@ -1212,6 +1230,7 @@ uxa_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
PixmapPtr pPix = uxa_get_drawable_pixmap(pDrawable);
int xoff, yoff;
Bool ok;
+ RegionRec region;
uxa_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff);
@@ -1248,10 +1267,14 @@ fallback:
UXA_FALLBACK(("from %p (%c)\n", pDrawable,
uxa_drawable_location(pDrawable)));
- if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RO)) {
+ REGION_INIT(screen, &region, &Box, 1);
+
+ if (uxa_prepare_access(pDrawable, &region, UXA_ACCESS_RO)) {
fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
uxa_finish_access(pDrawable);
}
+ REGION_UNINIT(screen, &region);
+
return;
}
diff --git a/src/uxa/uxa-damage.c b/src/uxa/uxa-damage.c
index 63ad0ea..7d52fb1 100644
--- a/src/uxa/uxa-damage.c
+++ b/src/uxa/uxa-damage.c
@@ -92,7 +92,6 @@ trim_region (RegionPtr pRegion,
int subWindowMode)
{
RegionRec pixClip;
- int draw_x, draw_y;
#ifdef COMPOSITE
int screen_x = 0, screen_y = 0;
#endif
@@ -135,6 +134,9 @@ trim_region (RegionPtr pRegion,
/* If subWindowMode is set to an invalid value, don't perform
* any drawable-based clipping. */
}
+
+ int draw_x = 0;
+ int draw_y = 0;
/* Clip against border or pixmap bounds */
if (pDrawable->type == DRAWABLE_WINDOW)
@@ -145,6 +147,20 @@ trim_region (RegionPtr pRegion,
else
{
BoxRec box;
+
+ draw_x = pDrawable->x;
+ draw_y = pDrawable->y;
+#ifdef COMPOSITE
+ /*
+ * Need to move everyone to screen coordinates
+ * XXX what about off-screen pixmaps with non-zero x/y?
+ */
+ if (!WindowDrawable(pDrawable->type))
+ {
+ draw_x += ((PixmapPtr) pDrawable)->screen_x;
+ draw_y += ((PixmapPtr) pDrawable)->screen_y;
+ }
+#endif
box.x1 = draw_x;
box.y1 = draw_y;
diff --git a/src/uxa/uxa-unaccel.c b/src/uxa/uxa-unaccel.c
index 84e9d8b..2c068a0 100644
--- a/src/uxa/uxa-unaccel.c
+++ b/src/uxa/uxa-unaccel.c
@@ -78,10 +78,15 @@ uxa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
DDXPointPtr ppt, int *pwidth, int fSorted)
{
ScreenPtr screen = pDrawable->pScreen;
+ RegionRec region;
+
+ REGION_INIT (screen, &region, (BoxPtr)NULL, 0);
+ uxa_damage_fill_spans (&region, pDrawable, pGC, nspans,
+ ppt, pwidth, fSorted);
UXA_FALLBACK(("to %p (%c)\n", pDrawable,
uxa_drawable_location(pDrawable)));
- if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) {
+ if (uxa_prepare_access(pDrawable, &region, UXA_ACCESS_RW)) {
if (uxa_prepare_access_gc(pGC)) {
fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
fSorted);
@@ -89,6 +94,8 @@ uxa_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
}
uxa_finish_access(pDrawable);
}
+
+ REGION_UNINIT (screen, &region);
}
void
@@ -127,7 +134,13 @@ uxa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
{
ScreenPtr screen = pSrc->pScreen;
RegionPtr ret = NULL;
- RegionRec region;
+ RegionRec src_region;
+ RegionRec dst_region;
+ BoxRec src_box = { srcx, srcy, srcx + w, srcy + h };
+ BoxRec dst_box = { dstx, dsty, dstx + w, dsty + h };
+
+ REGION_INIT (screen, &src_region, &src_box, 1);
+ REGION_INIT (screen, &dst_region, &dst_box, 1);
/* FIXME: Hmm, it's not totally clear what to do in this case. In fact,
* all cases where more than one drawable can get prepare_access() called
@@ -137,8 +150,8 @@ uxa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
uxa_drawable_location(pSrc),
uxa_drawable_location(pDst)));
- if (uxa_prepare_access(pDst, &region, UXA_ACCESS_RW)) {
- if (uxa_prepare_access(pSrc, &region, UXA_ACCESS_RO)) {
+ if (uxa_prepare_access(pDst, &dst_region, UXA_ACCESS_RW)) {
+ if (uxa_prepare_access(pSrc, &src_region, UXA_ACCESS_RO)) {
ret =
fbCopyArea(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
dsty);
@@ -146,6 +159,10 @@ uxa_check_copy_area(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
}
uxa_finish_access(pDst);
}
+
+ REGION_UNINIT (screen, &src_region);
+ REGION_UNINIT (screen, &dst_region);
+
return ret;
}
@@ -215,12 +232,16 @@ uxa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
int nsegInit, xSegment * pSegInit)
{
ScreenPtr screen = pDrawable->pScreen;
+ RegionRec region;
+
+ REGION_INIT (screen, &region, (BoxPtr)NULL, 0);
+ uxa_damage_poly_segment (&region, pDrawable, pGC, nsegInit, pSegInit);
UXA_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
uxa_drawable_location(pDrawable), pGC->lineWidth,
nsegInit));
if (pGC->lineWidth == 0) {
- if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) {
+ if (uxa_prepare_access(pDrawable, &region, UXA_ACCESS_RW)) {
if (uxa_prepare_access_gc(pGC)) {
fbPolySegment(pDrawable, pGC, nsegInit,
pSegInit);
@@ -228,10 +249,14 @@ uxa_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
}
uxa_finish_access(pDrawable);
}
- return;
+ goto out;
}
+
/* fb calls mi functions in the lineWidth != 0 case. */
fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
+
+out:
+ REGION_UNINIT (screen, &region);
}
void
@@ -341,11 +366,15 @@ uxa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
DrawablePtr pDrawable, int w, int h, int x, int y)
{
ScreenPtr screen = pDrawable->pScreen;
+ RegionRec region;
+
+ REGION_INIT (screen, &region, (BoxPtr)NULL, 0);
+ uxa_damage_push_pixels (&region, pGC, pBitmap, pDrawable, w, h, x, y);
UXA_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
uxa_drawable_location(&pBitmap->drawable),
uxa_drawable_location(pDrawable)));
- if (uxa_prepare_access(pDrawable, NULL, UXA_ACCESS_RW)) {
+ if (uxa_prepare_access(pDrawable, &region, UXA_ACCESS_RW)) {
if (uxa_prepare_access(&pBitmap->drawable, NULL, UXA_ACCESS_RO)) {
if (uxa_prepare_access_gc(pGC)) {
fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
@@ -356,6 +385,8 @@ uxa_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
}
uxa_finish_access(pDrawable);
}
+
+ REGION_UNINIT (screen, &region);
}
void
@@ -384,10 +415,21 @@ uxa_check_composite(CARD8 op,
CARD16 width, CARD16 height)
{
ScreenPtr screen = pDst->pDrawable->pScreen;
+ RegionRec region;
UXA_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
- if (uxa_prepare_access(pDst->pDrawable, NULL, UXA_ACCESS_RW)) {
+ REGION_INIT (screen, &region, (BoxPtr)NULL, 0);
+ uxa_damage_composite (&region, op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst,
+ width, height);
+
+#if 0
+ ErrorF ("destination: %p\n", pDst->pDrawable);
+ ErrorF ("source: %p\n", pSrc->pDrawable);
+ ErrorF ("mask: %p\n", pMask? pMask->pDrawable : NULL);
+#endif
+ if (uxa_prepare_access(pDst->pDrawable, &region, UXA_ACCESS_RW)) {
if (pSrc->pDrawable == NULL ||
uxa_prepare_access(pSrc->pDrawable, NULL, UXA_ACCESS_RO)) {
if (!pMask || pMask->pDrawable == NULL ||
diff --git a/src/uxa/uxa.c b/src/uxa/uxa.c
index 71fe482..bfc700d 100644
--- a/src/uxa/uxa.c
+++ b/src/uxa/uxa.c
@@ -149,17 +149,22 @@ Bool uxa_prepare_access(DrawablePtr pDrawable, RegionPtr region, uxa_access_t ac
if (!offscreen)
return TRUE;
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pPixmap->drawable.width;
+ box.y2 = pPixmap->drawable.height;
+
+ REGION_INIT (pScreen, &region_rec, &box, 1);
if (!region)
- {
region = &region_rec;
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = pPixmap->drawable.width;
- box.y2 = pPixmap->drawable.height;
-
- REGION_INIT (pScreen, &region_rec, &box, 1);
- }
+#if 0
+ /* Confine to the size of the drawable pixmap. The original
+ * drawable may be bigger than the underlying one. For example,
+ * the root window might be bigger than the screen pixmap.
+ */
+ REGION_INTERSECT (pScreen, region, region, &region_rec);
+#endif
result = TRUE;