summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <ssp@redhat.com>2010-09-27 06:12:30 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-01-26 08:12:17 -0500
commit01dc285614fcd353f689da808fda7997b169e1c8 (patch)
tree5e72d2d1a6093b3ff52c9f990e38923d27039442
parent553a4963fe653ca948db556d684eafb1980a68a7 (diff)
Fix surface bugs
-rw-r--r--src/qxl.h3
-rw-r--r--src/qxl_driver.c5
-rw-r--r--src/qxl_image.c22
-rw-r--r--src/qxl_mem.c27
-rw-r--r--src/qxl_surface.c116
5 files changed, 135 insertions, 38 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 678a0f2..0d20d9d 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -838,7 +838,8 @@ struct qxl_image *qxl_image_create (qxl_screen_t *qxl,
int y,
int width,
int height,
- int stride);
+ int stride,
+ int Bpp);
void qxl_image_destroy (qxl_screen_t *qxl,
struct qxl_image *image);
void qxl_drop_image_cache (qxl_screen_t *qxl);
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index e94c519..e948a6b 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -560,7 +560,8 @@ submit_copy (qxl_screen_t *qxl, const struct qxl_rect *rect)
qxl, qxl_image_create (qxl, qxl->fb, rect->left, rect->top,
rect->right - rect->left,
rect->bottom - rect->top,
- pScrn->displayWidth * qxl->bytes_per_pixel), qxl->main_mem_slot);
+ pScrn->displayWidth * qxl->bytes_per_pixel, qxl->bytes_per_pixel),
+ qxl->main_mem_slot);
drawable->u.copy.src_area = *rect;
translate_rect (&drawable->u.copy.src_area);
drawable->u.copy.rop_descriptor = ROPD_OP_PUT;
@@ -1028,7 +1029,7 @@ qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
if (surface)
{
- ErrorF (" Successfully created surface in video memory\n");
+ /* ErrorF (" Successfully created surface in video memory\n"); */
pixmap = fbCreatePixmap (screen, 0, 0, depth, usage);
diff --git a/src/qxl_image.c b/src/qxl_image.c
index 147cc18..17c2e27 100644
--- a/src/qxl_image.c
+++ b/src/qxl_image.c
@@ -98,14 +98,14 @@ remove_image_info (image_info_t *info)
struct qxl_image *
qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
int x, int y, int width, int height,
- int stride)
+ int stride, int Bpp)
{
unsigned int hash;
image_info_t *info;
- data += y * stride + x * qxl->bytes_per_pixel;
+ data += y * stride + x * Bpp;
- hash = hash_and_copy (data, stride, NULL, -1, qxl->bytes_per_pixel, width, height);
+ hash = hash_and_copy (data, stride, NULL, -1, Bpp, width, height);
info = lookup_image_info (hash, width, height);
if (info)
@@ -149,7 +149,7 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
{
struct qxl_image *image;
struct qxl_data_chunk *chunk;
- int dest_stride = width * qxl->bytes_per_pixel;
+ int dest_stride = width * Bpp;
image_info_t *info;
#if 0
@@ -167,7 +167,7 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
hash_and_copy (data, stride,
chunk->data, dest_stride,
- qxl->bytes_per_pixel, width, height);
+ Bpp, width, height);
/* Image */
image = qxl_allocnf (qxl, sizeof *image);
@@ -179,19 +179,25 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
image->descriptor.width = width;
image->descriptor.height = height;
- if (qxl->bytes_per_pixel == 2)
+ if (Bpp == 2)
{
image->u.bitmap.format = QXL_BITMAP_FMT_16BIT;
}
- else
+ else if (Bpp == 1)
+ {
+ image->u.bitmap.format = QXL_BITMAP_FMT_8BIT;
+ }
+ else if (Bpp == 4)
{
image->u.bitmap.format = QXL_BITMAP_FMT_32BIT;
}
+ else
+ abort();
image->u.bitmap.flags = QXL_BITMAP_TOP_DOWN;
image->u.bitmap.x = width;
image->u.bitmap.y = height;
- image->u.bitmap.stride = width * qxl->bytes_per_pixel;
+ image->u.bitmap.stride = width * Bpp;
image->u.bitmap.palette = 0;
image->u.bitmap.data = physical_address (qxl, chunk, qxl->main_mem_slot);
diff --git a/src/qxl_mem.c b/src/qxl_mem.c
index c4c91b0..24816aa 100644
--- a/src/qxl_mem.c
+++ b/src/qxl_mem.c
@@ -123,6 +123,24 @@ qxl_mem_dump_stats (struct qxl_mem *mem, const char *header)
mem->n_bytes - (mem->total_allocated - mem->total_freed));
}
+void
+sanity_check (struct qxl_mem *mem)
+{
+#if 0
+ struct block *b;
+
+ ErrorF ("sanity check\n");
+
+ for (b = mem->unused; b != NULL; b = b->u.unused.next)
+ {
+ ErrorF (" %p\n", b);
+
+ if (b == (void *)0xffffffffffffffff)
+ abort();
+ }
+#endif
+}
+
void *
qxl_alloc (struct qxl_mem *mem, unsigned long n_bytes)
{
@@ -190,6 +208,8 @@ qxl_alloc (struct qxl_mem *mem, unsigned long n_bytes)
}
mem->total_allocated += n_bytes;
+
+ sanity_check (mem);
return (void *)b->u.used.data;
}
@@ -276,6 +296,9 @@ qxl_free (struct qxl_mem *mem, void *d)
#if 0
printf (" free: no merge with before\n");
#endif
+
+ if (b == (void *)0xffffffffffffffff)
+ abort();
before->u.unused.next = b;
}
@@ -290,6 +313,9 @@ qxl_free (struct qxl_mem *mem, void *d)
if (after)
{
+ if (after == (void *)0xffffffffffffffff)
+ abort();
+
#if 0
printf (" free: after: %p\n", after->u.used.data);
#endif
@@ -320,4 +346,5 @@ qxl_free (struct qxl_mem *mem, void *d)
#if 0
qxl_mem_dump_stats (mem, "after free");
#endif
+ sanity_check (mem);
}
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 15dda6e..ade047e 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -12,9 +12,11 @@ struct qxl_surface_t
RegionRec access_region;
void * address;
+ void * end;
qxl_surface_t * next;
int in_use;
+ int Bpp;
union
{
@@ -143,6 +145,8 @@ qxl_surface_create_primary (qxl_screen_t *qxl,
surface->dev_image = dev_image;
surface->host_image = host_image;
surface->qxl = qxl;
+ surface->Bpp = PIXMAN_FORMAT_BPP (format) / 8;
+
REGION_INIT (NULL, &(surface->access_region), (BoxPtr)NULL, 0);
return surface;
@@ -204,6 +208,12 @@ qxl_surface_create (qxl_screen_t *qxl,
return NULL;
}
+ if (bpp == 8)
+ {
+ ErrorF ("bpp == 8 triggers bugs in spice apparently\n");
+ return NULL;
+ }
+
if (bpp != 8 && bpp != 16 && bpp != 32 && bpp != 24)
{
ErrorF (" Unknown bpp\n");
@@ -233,24 +243,6 @@ retry:
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:
@@ -278,12 +270,37 @@ retry:
break;
}
+ stride = width * PIXMAN_FORMAT_BPP (pformat) / 8;
+ stride = (stride + 3) & ~3;
+
+ /* the final + stride is to work around a bug where the device apparently
+ * scribbles after the end of the image
+ */
+ surface->address = qxl_alloc (qxl->surf_mem, stride * height + stride);
+ surface->end = surface->address + 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);
+
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);
+
+ ErrorF ("stride: %d\n", stride);
+
+ cmd->u.surface_create.physical =
+ physical_address (qxl, surface->address, qxl->vram_mem_slot);
#if 0
ErrorF ("create %d\n", cmd->surface_id);
@@ -298,6 +315,8 @@ retry:
surface->host_image = pixman_image_create_bits (
pformat, width, height, NULL, -1);
+
+ surface->Bpp = PIXMAN_FORMAT_BPP (pformat) / 8;
#if 0
ErrorF (" Allocating %d %lx\n", surface->id, surface->address);
@@ -410,26 +429,45 @@ download_box (qxl_screen_t *qxl, uint8_t *host,
}
}
#endif
+ void sanity_check (struct qxl_mem *mem);
+
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);
+ uint32_t before, after;
#if 0
ErrorF ("Downloading %d %d %d %d\n", x1, y1, x2 - x1, y2 - y1);
#endif
+ sanity_check (surface->qxl->surf_mem);
+
+ before = *((uint32_t *)surface->address - 1);
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);
+ after = *((uint32_t *)surface->address - 1);
+
+ if (surface->id != 0 && before != after)
+ abort();
+
+ sanity_check (surface->qxl->surf_mem);
+
+ pixman_color_t p = { 0xffff, 0x0000, 0xffff, 0xffff };
+ pixman_image_t *pink = pixman_image_create_solid_fill (&p);
+
+ pixman_image_composite (PIXMAN_OP_SRC, pink, NULL, surface->host_image,
+ 0, 0, 0, 0, x1, y1, x2 - x1, y2 - y1);
+
pixman_image_composite (PIXMAN_OP_SRC,
- surface->dev_image,
+ surface->dev_image,
NULL,
surface->host_image,
x1, y1, 0, 0, x1, y1, x2 - x1, y2 - y1);
@@ -445,6 +483,7 @@ qxl_surface_prepare_access (qxl_surface_t *surface,
BoxPtr boxes;
ScreenPtr pScreen = pixmap->drawable.pScreen;
RegionRec new;
+ int stride, height;
REGION_INIT (NULL, &new, (BoxPtr)NULL, 0);
REGION_SUBTRACT (NULL, &new, region, &surface->access_region);
@@ -458,6 +497,15 @@ qxl_surface_prepare_access (qxl_surface_t *surface,
ErrorF ("Preparing access to %d boxes\n", n_boxes);
#endif
+ stride = pixman_image_get_stride (surface->dev_image);
+ height = pixman_image_get_height (surface->dev_image);
+
+#if 0
+ ErrorF ("Flattening %p -> %p (allocated end %p)\n",
+ surface->address,
+ surface->address + stride * height, surface->end);
+#endif
+
if (n_boxes < 25)
{
while (n_boxes--)
@@ -526,7 +574,7 @@ make_drawable (qxl_screen_t *qxl, int surface, uint8_t type,
drawable->type = type;
- drawable->surface_id = 0; /* Only primary for now */
+ drawable->surface_id = surface; /* Only primary for now */
drawable->effect = QXL_EFFECT_OPAQUE;
drawable->self_bitmap = 0;
drawable->self_bitmap_area.top = 0;
@@ -621,10 +669,14 @@ upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
rect.bottom = y2;
#if 0
- /* Paint a green flash before uploading */
- submit_fill (qxl, surface->id, &rect, 0xff00ff00);
#endif
+ /* if (surface->id != 0) */
+ /* { */
+ /* /\* Paint a green flash after uploading *\/ */
+ /* submit_fill (qxl, surface->id, &rect, rand()); */
+ /* } */
+
drawable = make_drawable (qxl, surface->id, QXL_DRAW_COPY, &rect);
drawable->u.copy.src_area = rect;
translate_rect (&drawable->u.copy.src_area);
@@ -639,11 +691,18 @@ upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
stride = pixman_image_get_stride (surface->host_image);
image = qxl_image_create (
- qxl, (const uint8_t *)data, x1, y1, x2 - x1, y2 - y1, stride);
+ qxl, (const uint8_t *)data, x1, y1, x2 - x1, y2 - y1, stride,
+ surface->Bpp);
drawable->u.copy.src_bitmap =
physical_address (qxl, image, qxl->main_mem_slot);
push_drawable (qxl, drawable);
+
+ /* if (surface->id != 0) */
+ /* { */
+ /* /\* Paint a green flash after uploading *\/ */
+ /* submit_fill (qxl, surface->id, &rect, rand()); */
+ /* } */
}
void
@@ -687,6 +746,9 @@ Bool
qxl_surface_prepare_solid (qxl_surface_t *destination,
Pixel fg)
{
+ if (destination->id != 0)
+ return FALSE;
+
destination->u.solid_pixel = fg;
return TRUE;
}
@@ -717,7 +779,7 @@ qxl_surface_prepare_copy (qxl_surface_t *dest,
{
if (source->id != 0)
{
- ErrorF ("bad surface\n");
+ /* ErrorF ("bad surface\n"); */
return FALSE;
}