From 7a5b6cfbccbdd567b35cbf5d199643cb1cf49c64 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Date: Fri, 9 Jul 2010 10:27:24 -0400 Subject: Yeah, I need to get a real commit message written for all of this. --- src/Makefile.am | 1 + src/qxl.h | 142 +++++++- src/qxl_cursor.c | 4 +- src/qxl_driver.c | 956 +++++++++++++++++++++++--------------------------- src/qxl_surface.c | 748 +++++++++++++++++++++++++++++++++++++++ src/uxa/uxa-accel.c | 43 ++- src/uxa/uxa-damage.c | 18 +- src/uxa/uxa-unaccel.c | 58 ++- src/uxa/uxa.c | 21 +- 9 files changed, 1442 insertions(+), 549 deletions(-) create mode 100644 src/qxl_surface.c 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 * * This is qxl, a driver for the Qumranet paravirtualized graphics device - * in qemu. + * in qemu. */ #include @@ -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) @@ -812,59 +872,12 @@ unaccel (void) return FALSE; } -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,159 +885,50 @@ 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; + return qxl_surface_prepare_access (get_surface (pixmap), + pixmap, region, access); +} - stride = qxl->current_mode->stride; +static void +qxl_finish_access (PixmapPtr pixmap) +{ + qxl_surface_finish_access (get_surface (pixmap), pixmap); +} - ErrorF ("Stride: %d\n", stride); - - n_bytes = stride * pixmap->drawable.height; +static Bool +qxl_pixmap_is_offscreen (PixmapPtr pixmap) +{ + return !!get_surface (pixmap); +} - copy = malloc (n_bytes); - if (!copy) +static Bool +good_alu_and_pm (DrawablePtr drawable, int alu, Pixel planemask) +{ + if (!UXA_PM_IS_SOLID (drawable, planemask)) 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); + if (alu != GXcopy) + return FALSE; return TRUE; } -static void -qxl_finish_access (PixmapPtr pixmap) +/* + * Solid fill + */ +static Bool +qxl_check_solid (DrawablePtr drawable, int alu, Pixel planemask) { - 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); -} - -static Bool -qxl_pixmap_is_offscreen (PixmapPtr pixmap) -{ - ScreenPtr pScreen = pixmap->drawable.pScreen; - PixmapPtr scr_pixmap = pScreen->GetScreenPixmap(pScreen); - - if (pixmap == scr_pixmap) - { - ErrorF ("%p is offscreen \n", pixmap); - return TRUE; - } - - ErrorF ("is not offscreen \n"); - - return FALSE; -} - -/* - * Solid fill - */ -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; - -/* 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); */ + qxl_surface_copy (get_surface (dest), + src_x1, src_y1, + dest_x1, dest_y1, + width, height); - 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; + ErrorF ("asdf\n"); - 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 = 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, ®ion, &Box, 1); + + if (uxa_prepare_access(pDrawable, ®ion, UXA_ACCESS_RO)) { fbGetImage(pDrawable, x, y, w, h, format, planeMask, d); uxa_finish_access(pDrawable); } + REGION_UNINIT(screen, ®ion); + 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, ®ion, (BoxPtr)NULL, 0); + uxa_damage_fill_spans (®ion, 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, ®ion, 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, ®ion); } 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, ®ion, UXA_ACCESS_RW)) { - if (uxa_prepare_access(pSrc, ®ion, 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, ®ion, (BoxPtr)NULL, 0); + uxa_damage_poly_segment (®ion, 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, ®ion, 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, ®ion); } 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, ®ion, (BoxPtr)NULL, 0); + uxa_damage_push_pixels (®ion, 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, ®ion, 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, ®ion); } 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, ®ion, (BoxPtr)NULL, 0); + uxa_damage_composite (®ion, 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, ®ion, 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, ®ion_rec, &box, 1); if (!region) - { region = ®ion_rec; - box.x1 = 0; - box.y1 = 0; - box.x2 = pPixmap->drawable.width; - box.y2 = pPixmap->drawable.height; - - REGION_INIT (pScreen, ®ion_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, ®ion_rec); +#endif result = TRUE; -- cgit v1.2.3