summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <ssp@redhat.com>2010-09-28 09:26:34 -0400
committerSøren Sandmann <ssp@redhat.com>2010-09-28 09:26:34 -0400
commitdd72990159822b69a6ee25efe78058c5fdbdc579 (patch)
tree9fefcda735ad3ce3e53c42b6030aabfecebff858
parent4c59498c7f719105e680a5039241bd184b22e6b2 (diff)
Initial (buggy) support for copy area from offscreens
-rw-r--r--src/qxl.h5
-rw-r--r--src/qxl_driver.c10
-rw-r--r--src/qxl_surface.c94
3 files changed, 80 insertions, 29 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 0d20d9d..a4ecce6 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -169,6 +169,10 @@ typedef enum {
QXL_IMAGE_TYPE_LZ_RGB,
QXL_IMAGE_TYPE_GLZ_RGB,
QXL_IMAGE_TYPE_FROM_CACHE,
+ QXL_IMAGE_TYPE_SURFACE,
+ QXL_IMAGE_TYPE_JPEG,
+ QXL_IMAGE_TYPE_FROM_CACHE_LOSSLESS,
+ QXL_IMAGE_TYPE_JPEG_ALPHA
} qxl_image_type;
typedef enum {
@@ -238,6 +242,7 @@ struct qxl_image {
union
{
struct qxl_bitmap bitmap;
+ uint32_t surface_id;
} u;
};
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index e948a6b..fd47b7f 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -87,7 +87,15 @@ garbage_collect (qxl_screen_t *qxl)
struct qxl_image *image = virtual_address (
qxl, u64_to_pointer (drawable->u.copy.src_bitmap), qxl->main_mem_slot);
- qxl_image_destroy (qxl, image);
+ if (image->descriptor.type == QXL_IMAGE_TYPE_SURFACE)
+ {
+ qxl_surface_unref (image->u.surface_id);
+ qxl_free (qxl->mem, image);
+ }
+ else
+ {
+ qxl_image_destroy (qxl, image);
+ }
}
else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY)
{
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 5a58a31..456bf23 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -17,6 +17,7 @@ struct qxl_surface_t
qxl_surface_t * next;
int in_use;
int Bpp;
+ int ref_count;
union
{
@@ -82,6 +83,7 @@ surface_new (void)
result->next = NULL;
result->in_use = TRUE;
+ result->ref_count = 1;
return result;
}
@@ -197,7 +199,7 @@ qxl_surface_create (qxl_screen_t *qxl,
if (++count < 200)
return NULL;
-
+
#if 0
ErrorF (" qxl_surface: attempting to allocate %d x %d @ %d\n", width, height, bpp);
#endif
@@ -236,6 +238,7 @@ retry:
#if 0
ErrorF (" Surface allocated: %u\n", surface->id);
#endif
+ ErrorF ("Allocated %d\n", surface->id);
if (width == 0 || height == 0)
{
@@ -334,38 +337,45 @@ qxl_surface_destroy (qxl_surface_t *surface)
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)
+ if (--surface->ref_count == 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 (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 (" pushing destroy command %lx\n", cmd->release_info.id);
+ 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 ("destroy %d\n", cmd->surface_id);
+ ErrorF (" pushing destroy command %lx\n", cmd->release_info.id);
#endif
-
- push_surface_cmd (qxl, cmd);
+ ErrorF ("destroy %d\n", cmd->surface_id);
+
+ push_surface_cmd (qxl, cmd);
+ }
}
}
void
+qxl_surface_unref (uint32_t id)
+{
+ qxl_surface_t *surface = all_surfaces + id;
+
+ qxl_surface_destroy (surface);
+}
+
+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);
@@ -746,7 +756,7 @@ Bool
qxl_surface_prepare_solid (qxl_surface_t *destination,
Pixel fg)
{
- destination->u.solid_pixel = fg ^ (rand() >> 16);
+ destination->u.solid_pixel = fg; // ^ (rand() >> 16);
return TRUE;
}
@@ -775,9 +785,6 @@ Bool
qxl_surface_prepare_copy (qxl_surface_t *dest,
qxl_surface_t *source)
{
- if (source->id != 0)
- return FALSE;
-
dest->u.copy_src = source;
return TRUE;
}
@@ -797,13 +804,44 @@ qxl_surface_copy (qxl_surface_t *dest,
qrect.left = dest_x1;
qrect.right = dest_x1 + width;
+ if (dest->id == dest->u.copy_src->id)
+ {
/* 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;
-
+
+ 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;
+ }
+ else
+ {
+ struct qxl_image *image = qxl_allocnf (qxl, sizeof *image);
+
+ ErrorF ("Copy %d to %d\n", dest->u.copy_src->id, dest->id);
+
+ dest->u.copy_src->ref_count++;
+
+ image->descriptor.id = 0;
+ image->descriptor.type = QXL_IMAGE_TYPE_SURFACE;
+ image->descriptor.width = 0;
+ image->descriptor.height = 0;
+ image->u.surface_id = dest->u.copy_src->id;
+
+ drawable = make_drawable (qxl, dest->id, QXL_DRAW_COPY, &qrect);
+
+ drawable->u.copy.src_bitmap = physical_address (qxl, image, qxl->main_mem_slot);
+ drawable->u.copy.src_area.left = src_x1;
+ drawable->u.copy.src_area.top = src_y1;
+ drawable->u.copy.src_area.right = src_x1 + width;
+ drawable->u.copy.src_area.bottom = src_y1 + height;
+ 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;
+ }
+
push_drawable (qxl, drawable);
}