summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2012-10-02 15:08:53 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2012-10-02 15:08:53 -0400
commit77b0f810ae08a4dcddad31893ed993f7f03c2e87 (patch)
treecd5be6f3859f2c368f41fbd5ae743557b4f3ee9f
parent179bf69ffaf55854be017e742ac8aff12e11ee97 (diff)
Notes about memory management
-rw-r--r--fragments.c110
1 files changed, 76 insertions, 34 deletions
diff --git a/fragments.c b/fragments.c
index 670e97f..dd0f867 100644
--- a/fragments.c
+++ b/fragments.c
@@ -1,6 +1,26 @@
#include <stdlib.h>
#include <pixman.h>
+/*
+
+ Memory management:
+
+ For traps we don't want to copy them, so the image should take ownership.
+ Maybe the cairo->pixman conversion should just take place inside the image?
+ Maybe it doesn't matter that much.
+ Maybe polygon images will make the question irrelevant.
+
+ For pimages, have the image take a ref would be more convenient.
+
+ For initializing with a region, it would be convenient, but not essential,
+ if we can avoid copying the region parameter.
+
+ Structures internal to the images and fragments are of course managed and
+ owned by the structures in question.
+
+*/
+
+
typedef struct fragment_t fragment_t;
typedef struct image_t image_t;
typedef struct command_buffer_t command_buffer_t;
@@ -23,7 +43,7 @@ struct fragment_t
pixman_bool_t broken;
pixman_region32_t region;
fragment_t * next;
-
+
/* State - should this be a separate structure? */
state_t state;
pixman_bool_t alpha_only;
@@ -61,12 +81,12 @@ static fragment_t *
fragment_new (int width, int height)
{
fragment_t *result = malloc (sizeof *result);
-
+
if (!result)
return (fragment_t *)&broken_fragment;
-
+
pixman_region32_init_rect (&result->region, 0, 0, width, height);
-
+
return result;
}
@@ -81,7 +101,7 @@ fragment_set_blank (fragment_t *fragment)
{
if (fragment->broken)
return;
-
+
fragment->state = BLANK;
}
@@ -90,13 +110,13 @@ fragment_set_pixman (fragment_t *fragment, pixman_image_t *image)
{
if (fragment->broken)
return;
-
+
fragment->state = PIXMAN;
fragment->u.image = image;
}
-/* Split @fragment into two parts: one that intersects with other,
- * and one that doesn't.
+/* Split @fragment into two parts: one that intersects @source
+ * and one that doesn't. Both may be NULL. @dest is freed or reused.
*/
static void
fragment_intersect (fragment_t *dest, fragment_t *source,
@@ -104,13 +124,13 @@ fragment_intersect (fragment_t *dest, fragment_t *source,
fragment_t **remains)
{
*intersection = NULL;
-
+
if (dest->broken)
{
*remains = NULL;
return;
}
-
+
*remains = dest;
if (source->broken)
@@ -118,9 +138,9 @@ fragment_intersect (fragment_t *dest, fragment_t *source,
*intersection = NULL;
return;
}
-
+
*intersection = fragment_new (0, 0);
-
+
if ((*intersection)->broken)
{
*intersection = NULL;
@@ -135,7 +155,7 @@ fragment_intersect (fragment_t *dest, fragment_t *source,
*intersection = NULL;
return;
}
-
+
if (!pixman_region32_subtract (&(dest->region), &(dest->region),
&(*intersection)->region))
{
@@ -145,13 +165,13 @@ fragment_intersect (fragment_t *dest, fragment_t *source,
*intersection = NULL;
return;
}
-
+
if (!pixman_region32_not_empty (&(*intersection)->region))
{
fragment_free (*intersection);
*intersection = NULL;
}
-
+
if (!pixman_region32_not_empty (&dest->region))
{
fragment_free (dest);
@@ -163,13 +183,32 @@ static void
fragment_composite (fragment_t *result, pixman_op_t op,
fragment_t *dest, fragment_t *src)
{
+ if ((op == PIXMAN_OP_ADD && dest->state == BLANK) ||
+ (op == PIXMAN_OP_IN && is_opaque (dest)))
+ {
+ op = PIXMAN_OP_SRC;
+ }
+
switch (op)
{
+ case PIXMAN_OP_SRC:
+ copy_state (result, src);
+ break;
+
case PIXMAN_OP_IN:
if (dest->state == BLANK || src->state == BLANK)
result->state == BLANK;
- else if (is_opaque (dest))
- copy_state (result, src);
+ break;
+
+ case PIXMAN_OP_OUT_REVERSE:
+ if (is_opaque (src))
+ result->state == BLANK;
+ else if (src->state == BLANK)
+ copy_state (result, dest->state);
+ break;
+
+ default:
+ /* FIXME: add command to composite the images */
break;
}
}
@@ -178,14 +217,14 @@ static image_t *
allocate_image (int width, int height)
{
image_t *image = malloc (sizeof *image);
-
+
if (!image)
return (image_t *)&broken;
image->width = width;
image->height = height;
image->fragments = fragment_new (width, height);
-
+
return image;
}
@@ -193,11 +232,11 @@ static image_t *
image_new_blank (int width, int height)
{
image_t *image;
-
+
image = allocate_image (width, height);
if (image->broken)
return image;
-
+
fragment_set_blank (image->fragments);
return image;
}
@@ -205,6 +244,9 @@ image_new_blank (int width, int height)
void
image_free (image_t *image)
{
+ if (image->broken)
+ return;
+
/* FIXME */
}
@@ -212,11 +254,11 @@ static image_t *
image_new_pixman (int width, int height, pixman_image_t *pimage)
{
image_t *image;
-
+
image = allocate_image (width, height);
if (image->broken)
return image;
-
+
fragment_set_pixman (image->fragments, pimage);
return image;
}
@@ -225,37 +267,37 @@ static void
image_composite (image_t *dest, pixman_op_t op, image_t *src, image_t *mask)
{
fragment_t *sfrag;
-
+
if (dest->broken || src->broken || (mask && mask->broken))
return;
if (mask)
{
image_t *tmp = allocate_image (dest->width, dest->height);
-
+
image_composite (tmp, PIXMAN_OP_SRC, mask, NULL);
image_composite (tmp, PIXMAN_OP_IN, src, NULL);
image_composite (dest, op, tmp, NULL);
-
+
image_free (tmp);
return;
}
-
+
sfrag = src->fragments;
while (sfrag)
{
fragment_t *new_fragments = NULL;
fragment_t *dfrag;
-
+
dfrag = dest->fragments;
while (dfrag != NULL)
{
fragment_t *intersection, *remains;
fragment_t *next = dfrag->next;
-
+
fragment_intersect (dfrag, sfrag, &intersection, &remains);
-
+
if (intersection)
{
fragment_composite (intersect, op, dfrag, sfrag);
@@ -263,18 +305,18 @@ image_composite (image_t *dest, pixman_op_t op, image_t *src, image_t *mask)
intersection->next = new_fragments;
new_fragments = intersection;
}
-
+
if (remains)
{
remains->next = new_fragments;
new_fragments = remains;
}
-
+
dfrag = next;
}
-
+
sfrag = sfrag->next;
}
-
+
dest->fragments = new_fragments;
}