Make images ref counted. Memory management.
authorSoren Sandmann Pedersen <ssp@dhcp83-218.boston.redhat.com>
Wed, 9 May 2007 15:00:06 +0000 (11:00 -0400)
committerSoren Sandmann Pedersen <ssp@dhcp83-218.boston.redhat.com>
Wed, 9 May 2007 15:00:06 +0000 (11:00 -0400)
pixman/pixman-compose.c
pixman/pixman-image.c
pixman/pixman-private.h
pixman/pixman-region.c
pixman/pixman.h

index cd6308e..632197e 100644 (file)
@@ -3836,7 +3836,7 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
     if (pict->common.filter == PIXMAN_FILTER_NEAREST || pict->common.filter == PIXMAN_FILTER_FAST)
     {
         if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) {
-            if (pixman_region_n_rects (pict->common.clip_region) == 1) {
+            if (pixman_region_n_rects (&pict->common.clip_region) == 1) {
                for (i = 0; i < width; ++i) {
                    if (!mask || mask[i] & maskBits)
                    {
@@ -3872,7 +3872,7 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                                y = MOD(v.vector[1]>>16, pict->height);
                                x = MOD(v.vector[0]>>16, pict->width);
                            }
-                           if (pixman_region_contains_point (pict->common.clip_region, x, y, &box))
+                           if (pixman_region_contains_point (&pict->common.clip_region, x, y, &box))
                                WRITE(buffer + i, fetch(bits + y*stride, x, indexed));
                            else
                                WRITE(buffer + i, 0);
@@ -3885,8 +3885,8 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                 }
             }
         } else {
-            if (pixman_region_n_rects(pict->common.clip_region) == 1) {
-                box = pict->common.clip_region->extents;
+            if (pixman_region_n_rects(&pict->common.clip_region) == 1) {
+                box = pict->common.clip_region.extents;
                 for (i = 0; i < width; ++i) {
                    if (!mask || mask[i] & maskBits)
                    {
@@ -3922,7 +3922,7 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                                y = v.vector[1]>>16;
                                x = v.vector[0]>>16;
                            }
-                           if (pixman_region_contains_point (pict->common.clip_region, x, y, &box))
+                           if (pixman_region_contains_point (&pict->common.clip_region, x, y, &box))
                                WRITE(buffer + i, fetch(bits + y*stride, x, indexed));
                            else
                                WRITE(buffer + i, 0);
@@ -3945,7 +3945,7 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
         unit.vector[1] -= unit.vector[2] / 2;
        
         if (pict->common.repeat == PIXMAN_REPEAT_NORMAL) {
-            if (pixman_region_n_rects(pict->common.clip_region) == 1) {
+            if (pixman_region_n_rects(&pict->common.clip_region) == 1) {
                 for (i = 0; i < width; ++i) {
                     if (!mask || mask[i] & maskBits)
                    {
@@ -4048,14 +4048,14 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                            
                            b = bits + y1*stride;
                            
-                           tl = pixman_region_contains_point(pict->common.clip_region, x1, y1, &box)
+                           tl = pixman_region_contains_point(&pict->common.clip_region, x1, y1, &box)
                                ? fetch(b, x1, indexed) : 0;
-                           tr = pixman_region_contains_point(pict->common.clip_region, x2, y1, &box)
+                           tr = pixman_region_contains_point(&pict->common.clip_region, x2, y1, &box)
                                ? fetch(b, x2, indexed) : 0;
                            b = bits + (y2)*stride;
-                           bl = pixman_region_contains_point(pict->common.clip_region, x1, y2, &box)
+                           bl = pixman_region_contains_point(&pict->common.clip_region, x1, y2, &box)
                                ? fetch(b, x1, indexed) : 0;
-                           br = pixman_region_contains_point(pict->common.clip_region, x2, y2, &box)
+                           br = pixman_region_contains_point(&pict->common.clip_region, x2, y2, &box)
                                ? fetch(b, x2, indexed) : 0;
                            
                            ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
@@ -4080,8 +4080,8 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                 }
             }
         } else {
-            if (pixman_region_n_rects(pict->common.clip_region) == 1) {
-                box = pict->common.clip_region->extents;
+            if (pixman_region_n_rects(&pict->common.clip_region) == 1) {
+                box = pict->common.clip_region.extents;
                 for (i = 0; i < width; ++i) {
                    if (!mask || mask[i] & maskBits)
                    {
@@ -4183,14 +4183,14 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                            b = bits + (y1)*stride;
                            x_off = x1;
                            
-                           tl = pixman_region_contains_point(pict->common.clip_region, x1, y1, &box)
+                           tl = pixman_region_contains_point(&pict->common.clip_region, x1, y1, &box)
                                ? fetch(b, x_off, indexed) : 0;
-                           tr = pixman_region_contains_point(pict->common.clip_region, x2, y1, &box)
+                           tr = pixman_region_contains_point(&pict->common.clip_region, x2, y1, &box)
                                ? fetch(b, x_off + 1, indexed) : 0;
                            b += stride;
-                           bl = pixman_region_contains_point(pict->common.clip_region, x1, y2, &box)
+                           bl = pixman_region_contains_point(&pict->common.clip_region, x1, y2, &box)
                                ? fetch(b, x_off, indexed) : 0;
-                           br = pixman_region_contains_point(pict->common.clip_region, x2, y2, &box)
+                           br = pixman_region_contains_point(&pict->common.clip_region, x2, y2, &box)
                                ? fetch(b, x_off + 1, indexed) : 0;
                            
                            ft = FbGet8(tl,0) * idistx + FbGet8(tr,0) * distx;
@@ -4252,7 +4252,7 @@ static void fbFetchTransformed(bits_image_t * pict, int x, int y, int width, uin
                        for (x = x1; x < x2; x++) {
                            if (*p) {
                                int tx = (pict->common.repeat == PIXMAN_REPEAT_NORMAL) ? MOD (x, pict->width) : x;
-                               if (pixman_region_contains_point (pict->common.clip_region, tx, ty, &box)) {
+                               if (pixman_region_contains_point (&pict->common.clip_region, tx, ty, &box)) {
                                    uint32_t *b = bits + (ty)*stride;
                                    uint32_t c = fetch(b, tx, indexed);
                                    
index 3b441b5..dd26b39 100644 (file)
@@ -34,22 +34,8 @@ enum
 };
 
 static void
-init_common (image_common_t *common)
-{
-    common->transform = NULL;
-    common->clip_region = NULL;
-    common->repeat = PIXMAN_REPEAT_NONE;
-    common->filter = PIXMAN_FILTER_NEAREST;
-    common->filter_params = NULL;
-    common->n_filter_params = 0;
-    common->alpha_map = NULL;
-    common->component_alpha = FALSE;
-}
-
-static void
 init_source_image (source_image_t *image)
 {
-    init_common (&image->common);
     image->class = SOURCE_IMAGE_CLASS_UNKNOWN;
 }
 
@@ -90,14 +76,57 @@ color_to_uint32 (const pixman_color_t *color)
 static pixman_image_t *
 allocate_image (void)
 {
-    return malloc (sizeof (pixman_image_t *));
+    pixman_image_t *image = malloc (sizeof (pixman_image_t *));
+
+    if (image)
+    {
+       image_common_t *common = &image->common;
+       
+       pixman_region_init (&common->clip_region);
+       common->transform = NULL;
+       common->repeat = PIXMAN_REPEAT_NONE;
+       common->filter = PIXMAN_FILTER_NEAREST;
+       common->filter_params = NULL;
+       common->n_filter_params = 0;
+       common->alpha_map = NULL;
+       common->component_alpha = FALSE;
+       common->ref_count = 1;
+    }
+
+    return image;
+}
+
+/* Ref Counting */
+pixman_image_t *
+pixman_image_ref                    (pixman_image_t       *image)
+{
+    image->common.ref_count++;
+
+    return image;
 }
 
-/* Destructor */
 void
-pixman_image_destroy (pixman_image_t *image)
+pixman_image_unref                  (pixman_image_t       *image)
 {
-    
+    image->common.ref_count--;
+
+    if (image->common.ref_count == 0)
+    {
+       image_common_t *common = (image_common_t *)image;
+
+       pixman_region_fini (&common->clip_region);
+
+       if (common->transform)
+           free (common->transform);
+
+       if (common->filter_params)
+           free (common->filter_params);
+
+       if (common->alpha_map)
+           pixman_image_unref ((pixman_image_t *)common->alpha_map);
+
+       free (image);
+    }
 }
 
 /* Constructors */
@@ -238,8 +267,6 @@ pixman_image_create_bits (pixman_format_code_t  format,
     if (!image)
        return NULL;
     
-    init_common (&image->common);
-    
     image->type = BITS;
     image->bits.format = format;
     image->bits.width = width;
@@ -255,14 +282,18 @@ void
 pixman_image_set_clip_region (pixman_image_t    *image,
                              pixman_region16_t *region)
 {
-    image->common.clip_region = region;
+    image_common_t *common = (image_common_t *)image;
+
+    pixman_region_copy (&common->clip_region, region);
 }
 
 void
 pixman_image_set_transform         (pixman_image_t       *image,
-                                   pixman_transform_t   *transform)
+                                   const pixman_transform_t   *transform)
 {
-    image->common.transform = transform;
+    image->common.transform = malloc (sizeof (pixman_transform_t));
+    if (image->common.transform)
+       *(image->common.transform) = *transform;
 }
 
 void
@@ -274,18 +305,22 @@ pixman_image_set_repeat            (pixman_image_t       *image,
 
 void
 pixman_image_set_filter            (pixman_image_t       *image,
-                                   pixman_filter_t       filter)
+                                   pixman_filter_t       filter,
+                                   const pixman_fixed_t *params,
+                                   int                   n_params)
 {
-    image->common.filter = filter;
-}
+    image_common_t *common = (image_common_t *)image;
+    
+    if (params != common->filter_params)
+    {
+       if (common->filter_params)
+           free (common->filter_params);
 
-void
-pixman_image_set_filter_params     (pixman_image_t       *image,
-                                   pixman_fixed_t       *params,
-                                   int                   n_params)
-{
-    image->common.filter_params = params;
-    image->common.n_filter_params = n_params;
+       common->filter_params = malloc (n_params * sizeof (pixman_fixed_t));
+       memcpy (common->filter_params, params, n_params * sizeof (pixman_fixed_t));
+    }
+    
+    common->n_filter_params = n_params;
 }
 
 void
@@ -294,15 +329,20 @@ pixman_image_set_alpha_map         (pixman_image_t       *image,
                                    int16_t               x,
                                    int16_t               y)
 {
-    if (alpha_map && alpha_map->type != BITS)
+    image_common_t *common = (image_common_t *)image;
+    
+    return_if_fail (!alpha_map || alpha_map->type == BITS);
+
+    if (common->alpha_map != (bits_image_t *)alpha_map)
     {
-       image->common.alpha_map = NULL;
-       return;
+       if (common->alpha_map)
+           pixman_image_unref ((pixman_image_t *)common->alpha_map);
+
+       common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
     }
-    
-    image->common.alpha_map = (bits_image_t *)alpha_map;
-    image->common.alpha_origin.x = x;
-    image->common.alpha_origin.y = y;
+
+    common->alpha_origin.x = x;
+    common->alpha_origin.y = y;
 }
 
 void
index 87b9965..4299b58 100644 (file)
@@ -12,7 +12,7 @@
 
 #if DEBUG
 
-#define return_if_fail(expr) {                                                 \
+#define return_if_fail(expr)                                                   \
        do                                                                      \
        {                                                                       \
            if (!(expr))                                                        \
@@ -114,7 +114,8 @@ struct point
 struct image_common
 {
     image_type_t       type;
-    pixman_region16_t  *clip_region;
+    int32_t            ref_count;
+    pixman_region16_t   clip_region;
     pixman_transform_t *transform;
     pixman_repeat_t    repeat;
     pixman_filter_t    filter;
index ec4da71..38d6510 100644 (file)
@@ -411,7 +411,7 @@ pixman_rect_alloc (pixman_region16_t * region, int n)
 }
 
 pixman_bool_t
-pixman_region_copy(pixman_region16_t *dst, pixman_region16_t *src)
+pixman_region_copy (pixman_region16_t *dst, pixman_region16_t *src)
 {
     good(dst);
     good(src);
index 1a2dc5c..8cab2df 100644 (file)
@@ -380,63 +380,70 @@ typedef enum {
 } pixman_format_code_t;
 
 /* Constructors */
-pixman_image_t *pixman_image_create_solid_fill       (pixman_color_t       *color,
-                                                     int                  *error);
-pixman_image_t *pixman_image_create_linear_gradient  (pixman_point_fixed_t *p1,
-                                                     pixman_point_fixed_t *p2, 
+pixman_image_t *pixman_image_create_solid_fill       (pixman_color_t               *color,
+                                                     int                          *error);
+pixman_image_t *pixman_image_create_linear_gradient  (pixman_point_fixed_t         *p1,
+                                                     pixman_point_fixed_t         *p2,
                                                      const pixman_gradient_stop_t *stops,
-                                                     int                   n_stops);
-pixman_image_t *pixman_image_create_radial_gradient  (pixman_point_fixed_t *inner,
-                                                     pixman_point_fixed_t *outer,
-                                                     pixman_fixed_t        inner_radius,
-                                                     pixman_fixed_t        outer_radius,
+                                                     int                           n_stops);
+pixman_image_t *pixman_image_create_radial_gradient  (pixman_point_fixed_t         *inner,
+                                                     pixman_point_fixed_t         *outer,
+                                                     pixman_fixed_t                inner_radius,
+                                                     pixman_fixed_t                outer_radius,
                                                      const pixman_gradient_stop_t *stops,
-                                                     int                   n_stops);
-pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t *center,
-                                                     pixman_fixed_t        angle,
+                                                     int                           n_stops);
+pixman_image_t *pixman_image_create_conical_gradient (pixman_point_fixed_t         *center,
+                                                     pixman_fixed_t                angle,
                                                      const pixman_gradient_stop_t *stops,
-                                                     int                   n_stops);
-pixman_image_t *pixman_image_create_bits             (pixman_format_code_t  format,
-                                                     int                   width,
-                                                     int                   height,
-                                                     uint32_t             *bits,
-                                                     int                   rowstride_bytes);
+                                                     int                           n_stops);
+pixman_image_t *pixman_image_create_bits             (pixman_format_code_t          format,
+                                                     int                           width,
+                                                     int                           height,
+                                                     uint32_t                     *bits,
+                                                     int                           rowstride_bytes);
 
 /* Destructor */
-void           pixman_image_destroy                 (pixman_image_t       *image);
+pixman_image_t *pixman_image_ref                     (pixman_image_t               *image);
+void            pixman_image_unref                   (pixman_image_t               *image);
+
 
 /* Set properties */
-void            pixman_image_set_clip_region         (pixman_image_t       *image,
-                                                     pixman_region16_t    *region);
-void            pixman_image_set_transform           (pixman_image_t       *image,
-                                                     pixman_transform_t   *transform);
-void            pixman_image_set_repeat              (pixman_image_t       *image,
-                                                     pixman_repeat_t       repeat);
-void            pixman_image_set_filter              (pixman_image_t       *image,
-                                                     pixman_filter_t       filter);
-void            pixman_image_set_filter_params       (pixman_image_t       *image,
-                                                     pixman_fixed_t       *params,
-                                                     int                   n_params);
-void            pixman_image_set_alpha_map           (pixman_image_t       *image,
-                                                     pixman_image_t       *alpha_map,
-                                                     int16_t               x,
-                                                     int16_t               y);
-void            pixman_image_set_component_alpha     (pixman_image_t       *image,
-                                                     pixman_bool_t         component_alpha);
+void            pixman_image_set_clip_region         (pixman_image_t               *image,
+                                                     pixman_region16_t            *region);
+void            pixman_image_set_transform           (pixman_image_t               *image,
+                                                     const pixman_transform_t     *transform);
+void            pixman_image_set_repeat              (pixman_image_t               *image,
+                                                     pixman_repeat_t               repeat);
+void            pixman_image_set_filter              (pixman_image_t               *image,
+                                                     pixman_filter_t               filter,
+                                                     const pixman_fixed_t         *filter_params,
+                                                     int                           n_filter_params);
+void            pixman_image_set_filter_params       (pixman_image_t               *image,
+                                                     pixman_fixed_t               *params,
+                                                     int                           n_params);
+void            pixman_image_set_alpha_map           (pixman_image_t               *image,
+                                                     pixman_image_t               *alpha_map,
+                                                     int16_t                       x,
+                                                     int16_t                       y);
+void            pixman_image_set_component_alpha     (pixman_image_t               *image,
+                                                     pixman_bool_t                 component_alpha);
+
 
 /* Composite */
-void            pixman_image_composite               (pixman_op_t           op,
-                                                     pixman_image_t       *src,
-                                                     pixman_image_t       *mask,
-                                                     pixman_image_t       *dest,
-                                                     int                   src_x,
-                                                     int                   src_y,
-                                                     int                   mask_x,
-                                                     int                   mask_y,
-                                                     int                   dest_x,
-                                                     int                   dest_y,
-                                                     int                   width,
-                                                     int                   height);
+void            pixman_image_composite               (pixman_op_t                   op,
+                                                     pixman_image_t               *src,
+                                                     pixman_image_t               *mask,
+                                                     pixman_image_t               *dest,
+                                                     int                           src_x,
+                                                     int                           src_y,
+                                                     int                           mask_x,
+                                                     int                           mask_y,
+                                                     int                           dest_x,
+                                                     int                           dest_y,
+                                                     int                           width,
+                                                     int                           height);
+
+