summaryrefslogtreecommitdiff
path: root/src/qxl_surface.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/qxl_surface.c')
-rw-r--r--src/qxl_surface.c116
1 files changed, 89 insertions, 27 deletions
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;
}