svn merge ^/trunk/blender -r49107:49118
[blender.git] / source / blender / blenkernel / intern / mask.c
index 6fe838666c5f2285e5f1c3b8133805922a4ef8de..e39bb7a02e1656150ce8577c956da042f7d0deb1 100644 (file)
 
 #include "raskter.h"
 
+#ifdef USE_MANGO_MASK_CACHE_HACK
+
+#include "BLI_threads.h"
+
+typedef struct MaskRasterCache {
+       float *buffer;
+       int width, height;
+       short do_aspect_correct;
+       short do_mask_aa;
+       short do_feather;
+
+       ListBase layers;
+} MaskRasterCache;
+#endif
+
 static MaskSplinePoint *mask_spline_point_next(MaskSpline *spline, MaskSplinePoint *points_array, MaskSplinePoint *point)
 {
        if (point == &points_array[spline->tot_point - 1]) {
@@ -1453,6 +1468,7 @@ void BKE_mask_layer_free(MaskLayer *masklay)
        MEM_freeN(masklay);
 }
 
+
 void BKE_mask_layer_free_list(ListBase *masklayers)
 {
        MaskLayer *masklay = masklayers->first;
@@ -1465,11 +1481,44 @@ void BKE_mask_layer_free_list(ListBase *masklayers)
 
                masklay = masklay_next;
        }
+
 }
 
+#ifdef USE_MANGO_MASK_CACHE_HACK
+void BKE_mask_raster_cache_free(Mask *mask)
+{
+       MaskRasterCache *cache = mask->raster_cache;
+
+       if (cache) {
+               MaskLayer *layer;
+
+               layer = cache->layers.first;
+               while (layer) {
+                       MaskLayer *layer_next = layer->next;
+
+                       BKE_mask_layer_free(layer);
+                       layer = layer_next;
+               }
+
+               MEM_freeN(cache->buffer);
+               MEM_freeN(cache);
+
+               mask->raster_cache = NULL;
+       }
+}
+#endif
+
 void BKE_mask_free(Mask *mask)
 {
        BKE_mask_layer_free_list(&mask->masklayers);
+
+#ifdef USE_MANGO_MASK_CACHE_HACK
+       if (mask->raster_cache) {
+               BKE_mask_raster_cache_free(mask);
+
+               mask->raster_cache = NULL;
+       }
+#endif
 }
 
 void BKE_mask_unlink(Main *bmain, Mask *mask)
@@ -2482,16 +2531,157 @@ int BKE_mask_get_duration(Mask *mask)
        return MAX2(1, mask->efra - mask->sfra);
 }
 
+#ifdef USE_MANGO_MASK_CACHE_HACK
+static int mask_point_compare(MaskSplinePoint *point_a, MaskSplinePoint *point_b)
+{
+       if (point_a->tot_uw != point_b->tot_uw) {
+               return FALSE;
+       }
+
+       if (memcmp(&point_a->bezt, &point_b->bezt, sizeof(BezTriple))) {
+               return FALSE;
+       }
+
+       if (memcmp(&point_a->uw, &point_b->uw, 2 * point_a->tot_uw * sizeof(float))) {
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static int mask_points_compare(MaskSplinePoint *points_a, MaskSplinePoint *points_b, int tot_point)
+{
+       MaskSplinePoint *point_a = points_a;
+       MaskSplinePoint *point_b = points_b;
+       int a = tot_point;
+
+       /* deform points can be NULL */
+       if (point_a == NULL || point_b == NULL) {
+               return ((point_a == NULL) && (point_b == NULL));
+       }
+
+       while (a--) {
+               if (!mask_point_compare(point_a, point_b)) {
+                       return FALSE;
+               }
+
+               point_a++;
+               point_b++;
+       }
+
+       return TRUE;
+}
+
+static int mask_spline_compare(MaskSpline *spline_a, MaskSpline *spline_b)
+{
+       if (spline_a->flag != spline_b->flag ||
+           spline_a->tot_point != spline_b->tot_point ||
+           spline_a->weight_interp != spline_b->weight_interp)
+       {
+               return FALSE;
+       }
+
+       if (!mask_points_compare(spline_a->points, spline_b->points, spline_a->tot_point)) {
+               return FALSE;
+       }
+
+       return mask_points_compare(spline_a->points_deform, spline_b->points_deform, spline_a->tot_point);
+}
+
+static int mask_splines_compare(ListBase *base_a, ListBase *base_b)
+{
+       MaskSpline *spline_a, *spline_b;
+
+       for (spline_a = base_a->first, spline_b = base_b->first;
+            spline_a && spline_b;
+            spline_a = spline_a->next, spline_b = spline_b->next)
+       {
+               if (!mask_spline_compare(spline_a, spline_b)) {
+                       return FALSE;
+               }
+       }
+
+       if (spline_a || spline_b)
+               return FALSE;
+
+       return TRUE;
+}
+
+static int mask_layer_compare(MaskLayer *layer_a, MaskLayer *layer_b)
+{
+       if (layer_a->alpha != layer_b->alpha ||
+           layer_a->blend != layer_b->blend ||
+           layer_a->blend_flag != layer_b->blend_flag ||
+           layer_a->flag != layer_b->flag ||
+           layer_a->restrictflag != layer_b->restrictflag)
+       {
+               return FALSE;
+       }
+
+       if (strcmp(layer_a->name, layer_b->name))
+               return FALSE;
+
+       return mask_splines_compare(&layer_a->splines, &layer_b->splines);
+}
+
+static int mask_layers_compare(ListBase *base_a, ListBase *base_b)
+{
+       MaskLayer *layer_a, *layer_b;
+
+       for (layer_a = base_a->first, layer_b = base_b->first;
+            layer_a && layer_b;
+            layer_a = layer_a->next, layer_b = layer_b->next)
+       {
+               if (!mask_layer_compare(layer_a, layer_b)) {
+                       return FALSE;
+               }
+       }
+
+       if (layer_a || layer_b)
+               return FALSE;
+
+       return TRUE;
+}
+#endif
+
 /* rasterization */
-void BKE_mask_rasterize_layers(ListBase *masklayers, int width, int height, float *buffer,
+
+/* XXX: mask is only passed here to access rasterization cache
+ *      this MUST be removed as soon as tile-based rasterization would be here
+ */
+void BKE_mask_rasterize_layers(Mask *mask, ListBase *masklayers, int width, int height, float *buffer,
                                const short do_aspect_correct, const short do_mask_aa,
                                const short do_feather)
 {
+       MaskRasterCache *cache = mask->raster_cache;
        MaskLayer *masklay;
 
        /* temp blending buffer */
        const int buffer_size = width * height;
-       float *buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__);
+       float *buffer_tmp;
+
+#ifdef USE_MANGO_MASK_CACHE_HACK
+       BLI_lock_thread(LOCK_CUSTOM1);
+
+       if (cache &&
+           cache->width == width &&
+           cache->height == height &&
+           cache->do_aspect_correct == do_aspect_correct &&
+           cache->do_mask_aa == do_mask_aa &&
+           cache->do_feather == do_feather &&
+           mask_layers_compare(&cache->layers, &mask->masklayers))
+       {
+               memcpy(buffer, cache->buffer, sizeof(float) * buffer_size);
+
+               BLI_unlock_thread(LOCK_CUSTOM1);
+
+               return;
+       }
+
+       BLI_unlock_thread(LOCK_CUSTOM1);
+#endif
+
+       buffer_tmp = MEM_mallocN(sizeof(float) * buffer_size, __func__);
 
        for (masklay = masklayers->first; masklay; masklay = masklay->next) {
                MaskSpline *spline;
@@ -2617,6 +2807,30 @@ void BKE_mask_rasterize_layers(ListBase *masklayers, int width, int height, floa
                clamp_vn_vn(buffer, buffer_size);
        }
        MEM_freeN(buffer_tmp);
+
+#ifdef USE_MANGO_MASK_CACHE_HACK
+       BLI_lock_thread(LOCK_CUSTOM1);
+
+       BKE_mask_raster_cache_free(mask);
+
+       cache = MEM_callocN(sizeof(MaskRasterCache), "mask raster cache");
+
+       cache->buffer = MEM_mallocN(sizeof(float) * buffer_size, "mask raster cache buffer");
+
+       BKE_mask_layer_copy_list(&cache->layers, masklayers);
+
+       memcpy(cache->buffer, buffer, sizeof(float) * buffer_size);
+
+       cache->width = width;
+       cache->height = height;
+       cache->do_aspect_correct = do_aspect_correct;
+       cache->do_mask_aa = do_mask_aa;
+       cache->do_feather = do_feather;
+
+       mask->raster_cache = cache;
+
+       BLI_unlock_thread(LOCK_CUSTOM1);
+#endif
 }
 
 #ifdef __PLX_RASKTER_MT__
@@ -2695,5 +2909,5 @@ void BKE_mask_rasterize(Mask *mask, int width, int height, float *buffer,
                         const short do_aspect_correct, const short do_mask_aa,
                         const short do_feather)
 {
-       BKE_mask_rasterize_layers(&mask->masklayers, width, height, buffer, do_aspect_correct, do_mask_aa, do_feather);
+       BKE_mask_rasterize_layers(mask, &mask->masklayers, width, height, buffer, do_aspect_correct, do_mask_aa, do_feather);
 }