Sequencer: initial implementation of multithreaded effects
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 8 Aug 2012 16:46:45 +0000 (16:46 +0000)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 8 Aug 2012 16:46:45 +0000 (16:46 +0000)
Added a framework to run effects in several threads. Port most
of effects to this new framework.

Still some work to be done here (some effects are not so easy to port)

source/blender/blenkernel/BKE_sequencer.h
source/blender/blenkernel/intern/seqeffects.c
source/blender/blenkernel/intern/sequencer.c
source/blender/makesrna/intern/rna_sequencer.c

index 8a051e5..78e65fe 100644 (file)
@@ -110,6 +110,8 @@ enum {
 };
 
 struct SeqEffectHandle {
+       int multithreaded;
+
        /* constructors & destructor */
        /* init is _only_ called on first creation */
        void (*init)(struct Sequence *seq);
@@ -147,6 +149,12 @@ struct SeqEffectHandle {
        
        struct ImBuf * (*execute)(SeqRenderData context, struct Sequence *seq, float cfra, float facf0, float facf1,
                                  struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3);
+
+       struct ImBuf * (*init_execution)(SeqRenderData context, struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3);
+
+       void (*execute_slice)(SeqRenderData context, struct Sequence *seq, float cfra, float facf0, float facf1,
+                             struct ImBuf *ibuf1, struct ImBuf *ibuf2, struct ImBuf *ibuf3,
+                              int start_line, int total_lines, struct ImBuf *out);
 };
 
 /* ********************* prototypes *************** */
index a6688a4..938d114 100644 (file)
 
 #include "RNA_access.h"
 
-/* **** XXX **** */
+static void slize_get_byte_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
+                                   const ImBuf *ibuf3, const ImBuf *out, int start_line, unsigned char **rect1,
+                                   unsigned char **rect2, unsigned char **rect3, unsigned char **rect_out)
+{
+       int offset = 4 * start_line * context->rectx;
+
+       *rect1 = (unsigned char*) ibuf1->rect + offset;
+       *rect_out = (unsigned char*) out->rect + offset;
+
+       if (ibuf2)
+               *rect2 = (unsigned char*) ibuf2->rect + offset;
+
+       if (ibuf3)
+               *rect3 = (unsigned char*) ibuf3->rect + offset;
+}
+
+static void slize_get_float_buffers(const SeqRenderData *context, const ImBuf *ibuf1, const ImBuf *ibuf2,
+                                    const ImBuf *ibuf3, const ImBuf *out, int start_line,
+                                    float **rect1, float **rect2, float **rect3, float **rect_out)
+{
+       int offset = 4 * start_line * context->rectx;
+
+       *rect1 = ibuf1->rect_float + offset;
+       *rect_out = out->rect_float + offset;
+
+       if (ibuf2)
+               *rect2 = ibuf2->rect_float + offset;
+
+       if (ibuf3)
+               *rect3 = ibuf3->rect_float + offset;
+}
 
 /*********************** Glow effect *************************/
 
@@ -249,25 +279,24 @@ static void do_alphaover_effect_float(float facf0, float facf1, int x, int y,  f
        }
 }
 
-static ImBuf *do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0,
-                                                                 float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static void do_alphaover_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0,
+                                float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
+                                int start_line, int total_lines, ImBuf *out)
 {
-       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        if (out->rect_float) {
-               do_alphaover_effect_float(
-                       facf0, facf1, context.rectx, context.recty,
-                       ibuf1->rect_float, ibuf2->rect_float,
-                       out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_alphaover_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_alphaover_effect_byte(
-                       facf0, facf1, context.rectx, context.recty,
-                       (char *) ibuf1->rect, (char *) ibuf2->rect,
-                       (char *) out->rect);
-       }
+               unsigned char *rect1, *rect2, *rect_out;
 
-       return out;
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_alphaover_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+       }
 }
 
 /*********************** Alpha Under *************************/
@@ -412,20 +441,24 @@ static void do_alphaunder_effect_float(float facf0, float facf1, int x, int y,
        }
 }
 
-static ImBuf *do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
-                                   float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static void do_alphaunder_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+                                 float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
+                                 int start_line, int total_lines, ImBuf *out)
 {
-       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        if (out->rect_float) {
-               do_alphaunder_effect_float(facf0, facf1, context.rectx, context.recty, ibuf1->rect_float,
-                                          ibuf2->rect_float, out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_alphaunder_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_alphaunder_effect_byte(facf0, facf1, context.rectx, context.recty,
-                                         (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+               unsigned char *rect1, *rect2, *rect_out;
+
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_alphaunder_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
        }
-       return out;
 }
 
 /*********************** Cross *************************/
@@ -518,22 +551,24 @@ static void do_cross_effect_float(float facf0, float facf1, int x, int y, float
        }
 }
 
-/* careful: also used by speed effect! */
-
-static ImBuf *do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
-                              float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static void do_cross_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+                            float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
+                            int start_line, int total_lines, ImBuf *out)
 {
-       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        if (out->rect_float) {
-               do_cross_effect_float(facf0, facf1, context.rectx, context.recty,
-                                     ibuf1->rect_float, ibuf2->rect_float, out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_cross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_cross_effect_byte(facf0, facf1, context.rectx, context.recty,
-                                    (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+               unsigned char *rect1, *rect2, *rect_out;
+
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_cross_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
        }
-       return out;
 }
 
 /*********************** Gamma Cross *************************/
@@ -757,24 +792,32 @@ static void do_gammacross_effect_float(float facf0, float UNUSED(facf1), int x,
        }
 }
 
-static ImBuf *do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
-                                   float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static struct ImBuf *gammacross_init_execution(SeqRenderData context, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
 {
        ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        build_gammatabs();
 
+       return out;
+}
+
+static void do_gammacross_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+                                 float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3),
+                                 int start_line, int total_lines, ImBuf *out)
+{
        if (out->rect_float) {
-               do_gammacross_effect_float(facf0, facf1, context.rectx, context.recty, ibuf1->rect_float,
-                                          ibuf2->rect_float, out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_gammacross_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_gammacross_effect_byte(facf0, facf1, context.rectx, context.recty,
-                                         (unsigned char *) ibuf1->rect, (unsigned char *) ibuf2->rect,
-                                         (unsigned char *) out->rect);
-       }
+               unsigned char *rect1, *rect2, *rect_out;
 
-       return out;
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_gammacross_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
+       }
 }
 
 /*********************** Add *************************/
@@ -864,21 +907,23 @@ static void do_add_effect_float(float facf0, float facf1, int x, int y, float *r
        }
 }
 
-static ImBuf *do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
-                            ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static void do_add_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
+                          ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
 {
-       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        if (out->rect_float) {
-               do_add_effect_float(facf0, facf1, context.rectx, context.recty, ibuf1->rect_float,
-                                   ibuf2->rect_float, out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_add_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_add_effect_byte(facf0, facf1, context.rectx, context.recty, (unsigned char *) ibuf1->rect,
-                                  (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
-       }
+               unsigned char *rect1, *rect2, *rect_out;
 
-       return out;
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_add_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
+       }
 }
 
 /*********************** Sub *************************/
@@ -966,21 +1011,23 @@ static void do_sub_effect_float(float facf0, float facf1, int x, int y, float *r
        }
 }
 
-static ImBuf *do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
-                            ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static void do_sub_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
+                          ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
 {
-       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        if (out->rect_float) {
-               do_sub_effect_float(facf0, facf1, context.rectx, context.recty, ibuf1->rect_float,
-                                   ibuf2->rect_float, out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_sub_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_sub_effect_byte(facf0, facf1, context.rectx, context.recty, (char *) ibuf1->rect,
-                                  (char *) ibuf2->rect, (char *) out->rect);
-       }
+               unsigned char *rect1, *rect2, *rect_out;
 
-       return out;
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_sub_effect_byte(facf0, facf1, context.rectx, total_lines, (char *) rect1, (char *) rect2, (char *) rect_out);
+       }
 }
 
 /*********************** Drop *************************/
@@ -1161,21 +1208,23 @@ static void do_mul_effect_float(float facf0, float facf1, int x, int y, float *r
        }
 }
 
-static ImBuf *do_mul_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
-                            ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static void do_mul_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
+                          ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
 {
-       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-
        if (out->rect_float) {
-               do_mul_effect_float(facf0, facf1, context.rectx, context.recty, ibuf1->rect_float,
-                                   ibuf2->rect_float, out->rect_float);
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_mul_effect_float(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
        }
        else {
-               do_mul_effect_byte(facf0, facf1, context.rectx, context.recty, (unsigned char *) ibuf1->rect,
-                                  (unsigned char *) ibuf2->rect, (unsigned char *) out->rect);
-       }
+               unsigned char *rect1, *rect2, *rect_out;
 
-       return out;
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_mul_effect_byte(facf0, facf1, context.rectx, total_lines, rect1, rect2, rect_out);
+       }
 }
 
 /*********************** Wipe *************************/
@@ -2672,6 +2721,48 @@ void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, int forc
        }
 }
 
+static ImBuf *do_speed_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra),
+                              float facf0, float facf1, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+{
+       ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
+
+       if (out->rect_float) {
+               do_cross_effect_float(facf0, facf1, context.rectx, context.recty,
+                                     ibuf1->rect_float, ibuf2->rect_float, out->rect_float);
+       }
+       else {
+               do_cross_effect_byte(facf0, facf1, context.rectx, context.recty,
+                                    (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
+       }
+       return out;
+}
+
+/*********************** overdrop *************************/
+
+static void do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
+                               ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *UNUSED(ibuf3), int start_line, int total_lines, ImBuf *out)
+{
+       int x = context.rectx;
+       int y = total_lines;
+
+       if (out->rect_float) {
+               float *rect1, *rect2, *rect_out;
+
+               slize_get_float_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
+               do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
+       }
+       else {
+               unsigned char *rect1, *rect2, *rect_out;
+
+               slize_get_byte_buffers(&context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
+
+               do_drop_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
+               do_alphaover_effect_byte(facf0, facf1, x, y, (char *) rect1, (char *) rect2, (char *) rect_out);
+       }
+}
+
 /*********************** sequence effect factory *************************/
 
 static void init_noop(Sequence *UNUSED(seq))
@@ -2736,21 +2827,9 @@ static void get_default_fac_fade(Sequence *seq, float cfra, float *facf0, float
        *facf1 /= seq->len;
 }
 
-static ImBuf *do_overdrop_effect(SeqRenderData context, Sequence *UNUSED(seq), float UNUSED(cfra), float facf0, float facf1,
-                                 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+static struct ImBuf *init_execution(SeqRenderData context, ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
 {
        ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
-       int x = context.rectx;
-       int y = context.recty;
-
-       if (out->rect_float) {
-               do_drop_effect_float(facf0, facf1, x, y, ibuf1->rect_float, ibuf2->rect_float, out->rect_float);
-               do_alphaover_effect_float(facf0, facf1, x, y, ibuf1->rect_float, ibuf2->rect_float, out->rect_float);
-       }
-       else {
-               do_drop_effect_byte(facf0, facf1, x, y, (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
-               do_alphaover_effect_byte(facf0, facf1, x, y, (char *) ibuf1->rect, (char *) ibuf2->rect, (char *) out->rect);
-       }
 
        return out;
 }
@@ -2760,6 +2839,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
        struct SeqEffectHandle rval;
        int sequence_type = seq_type;
 
+       rval.multithreaded = FALSE;
        rval.init = init_noop;
        rval.num_inputs = num_inputs_default;
        rval.load = load_noop;
@@ -2768,44 +2848,55 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
        rval.get_default_fac = get_default_fac_noop;
        rval.store_icu_yrange = store_icu_yrange_noop;
        rval.execute = NULL;
+       rval.init_execution = init_execution;
+       rval.execute_slice = NULL;
        rval.copy = NULL;
 
        switch (sequence_type) {
                case SEQ_TYPE_CROSS:
-                       rval.execute = do_cross_effect;
+                       rval.multithreaded = TRUE;
+                       rval.execute_slice = do_cross_effect;
                        rval.early_out = early_out_fade;
                        rval.get_default_fac = get_default_fac_fade;
                        break;
                case SEQ_TYPE_GAMCROSS:
+                       rval.multithreaded = TRUE;
                        rval.init = init_gammacross;
                        rval.load = load_gammacross;
                        rval.free = free_gammacross;
                        rval.early_out = early_out_fade;
                        rval.get_default_fac = get_default_fac_fade;
-                       rval.execute = do_gammacross_effect;
+                       rval.init_execution = gammacross_init_execution;
+                       rval.execute_slice = do_gammacross_effect;
                        break;
                case SEQ_TYPE_ADD:
-                       rval.execute = do_add_effect;
+                       rval.multithreaded = TRUE;
+                       rval.execute_slice = do_add_effect;
                        rval.early_out = early_out_mul_input2;
                        break;
                case SEQ_TYPE_SUB:
-                       rval.execute = do_sub_effect;
+                       rval.multithreaded = TRUE;
+                       rval.execute_slice = do_sub_effect;
                        rval.early_out = early_out_mul_input2;
                        break;
                case SEQ_TYPE_MUL:
-                       rval.execute = do_mul_effect;
+                       rval.multithreaded = TRUE;
+                       rval.execute_slice = do_mul_effect;
                        rval.early_out = early_out_mul_input2;
                        break;
                case SEQ_TYPE_ALPHAOVER:
+                       rval.multithreaded = TRUE;
                        rval.init = init_alpha_over_or_under;
-                       rval.execute = do_alphaover_effect;
+                       rval.execute_slice = do_alphaover_effect;
                        break;
                case SEQ_TYPE_OVERDROP:
-                       rval.execute = do_overdrop_effect;
+                       rval.multithreaded = TRUE;
+                       rval.execute_slice = do_overdrop_effect;
                        break;
                case SEQ_TYPE_ALPHAUNDER:
+                       rval.multithreaded = TRUE;
                        rval.init = init_alpha_over_or_under;
-                       rval.execute = do_alphaunder_effect;
+                       rval.execute_slice = do_alphaunder_effect;
                        break;
                case SEQ_TYPE_WIPE:
                        rval.init = init_wipe_effect;
@@ -2836,7 +2927,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
                        rval.load = load_speed_effect;
                        rval.free = free_speed_effect;
                        rval.copy = copy_speed_effect;
-                       rval.execute = do_cross_effect;
+                       rval.execute = do_speed_effect;
                        rval.early_out = early_out_speed;
                        rval.store_icu_yrange = store_icu_yrange_speed;
                        break;
@@ -2865,7 +2956,7 @@ static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
 
 struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq)
 {
-       struct SeqEffectHandle rval = {NULL};
+       struct SeqEffectHandle rval = {FALSE, NULL};
 
        if (seq->type & SEQ_TYPE_EFFECT) {
                rval = get_sequence_effect_impl(seq->type);
@@ -2880,7 +2971,7 @@ struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq)
 
 struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq)
 {
-       struct SeqEffectHandle rval = {NULL};
+       struct SeqEffectHandle rval = {FALSE, NULL};
 
        if (seq->blend_mode != 0) {
                rval = get_sequence_effect_impl(seq->blend_mode);
@@ -2898,7 +2989,7 @@ int BKE_sequence_effect_get_num_inputs(int seq_type)
        struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
 
        int cnt = rval.num_inputs();
-       if (rval.execute) {
+       if (rval.execute || (rval.execute_slice && rval.init_execution)) {
                return cnt;
        }
        return 0;
index 0fc26a8..61b242d 100644 (file)
@@ -1808,6 +1808,83 @@ static void copy_to_ibuf_still(SeqRenderData context, Sequence *seq, float nr, I
 
 /*********************** strip rendering functions  *************************/
 
+typedef struct RenderEffectInitData {
+       struct SeqEffectHandle *sh;
+       SeqRenderData context;
+       Sequence *seq;
+       float cfra, facf0, facf1;
+       ImBuf *ibuf1, *ibuf2, *ibuf3;
+
+       ImBuf *out;
+} RenderEffectInitData;
+
+typedef struct RenderEffectThread {
+       struct SeqEffectHandle *sh;
+       SeqRenderData context;
+       Sequence *seq;
+       float cfra, facf0, facf1;
+       ImBuf *ibuf1, *ibuf2, *ibuf3;
+
+       ImBuf *out;
+       int start_line, tot_line;
+} RenderEffectThread;
+
+static void render_effect_execute_init_handle(void *handle_v, int start_line, int tot_line, void *init_data_v)
+{
+       RenderEffectThread *handle = (RenderEffectThread *) handle_v;
+       RenderEffectInitData *init_data = (RenderEffectInitData *) init_data_v;
+
+       handle->sh = init_data->sh;
+       handle->context = init_data->context;
+       handle->seq = init_data->seq;
+       handle->cfra = init_data->cfra;
+       handle->facf0 = init_data->facf0;
+       handle->facf1 = init_data->facf1;
+       handle->ibuf1 = init_data->ibuf1;
+       handle->ibuf2 = init_data->ibuf2;
+       handle->ibuf3 = init_data->ibuf3;
+       handle->out = init_data->out;
+
+       handle->start_line = start_line;
+       handle->tot_line = tot_line;
+}
+
+static void *render_effect_execute_do_thread(void *thread_data_v)
+{
+       RenderEffectThread *thread_data = (RenderEffectThread *) thread_data_v;
+
+       thread_data->sh->execute_slice(thread_data->context, thread_data->seq, thread_data->cfra,
+                                      thread_data->facf0, thread_data->facf1, thread_data->ibuf1,
+                                      thread_data->ibuf2, thread_data->ibuf3, thread_data->start_line,
+                                      thread_data->tot_line, thread_data->out);
+
+       return NULL;
+}
+
+static ImBuf *seq_render_effect_execute_threaded(struct SeqEffectHandle *sh, SeqRenderData context, Sequence *seq,
+                                                 float cfra, float facf0, float facf1,
+                                                 ImBuf *ibuf1, ImBuf *ibuf2, ImBuf *ibuf3)
+{
+       RenderEffectInitData init_data;
+       ImBuf *out = sh->init_execution(context, ibuf1, ibuf2, ibuf3);
+
+       init_data.sh = sh;
+       init_data.context = context;
+       init_data.seq = seq;
+       init_data.cfra = cfra;
+       init_data.facf0 = facf0;
+       init_data.facf1 = facf1;
+       init_data.ibuf1 = ibuf1;
+       init_data.ibuf2 = ibuf2;
+       init_data.ibuf3 = ibuf3;
+       init_data.out = out;
+
+       IMB_processor_apply_threaded(out->y, sizeof(RenderEffectThread), &init_data,
+                                 render_effect_execute_init_handle, render_effect_execute_do_thread);
+
+       return out;
+}
+
 static ImBuf *seq_render_effect_strip_impl(SeqRenderData context, Sequence *seq, float cfra)
 {
        float fac, facf;
@@ -1823,7 +1900,7 @@ static ImBuf *seq_render_effect_strip_impl(SeqRenderData context, Sequence *seq,
 
        input[0] = seq->seq1; input[1] = seq->seq2; input[2] = seq->seq3;
 
-       if (!sh.execute) {
+       if (!sh.execute && !(sh.execute_slice && sh.init_execution)) {
                /* effect not supported in this version... */
                out = IMB_allocImBuf(context.rectx, context.recty, 32, IB_rect);
                return out;
@@ -1861,7 +1938,10 @@ static ImBuf *seq_render_effect_strip_impl(SeqRenderData context, Sequence *seq,
                        }
 
                        if (ibuf[0] && ibuf[1]) {
-                               out = sh.execute(context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
+                               if (sh.multithreaded)
+                                       out = seq_render_effect_execute_threaded(&sh, context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
+                               else
+                                       out = sh.execute(context, seq, cfra, fac, facf, ibuf[0], ibuf[1], ibuf[2]);
                        }
                        break;
                case EARLY_USE_INPUT_1:
@@ -2488,14 +2568,16 @@ static ImBuf *seq_render_strip_stack(SeqRenderData context, ListBase *seqbasep,
                        int swap_input = seq_must_swap_input_in_blend_mode(seq);
 
                        if (swap_input) {
-                               out = sh.execute(context, seq, cfra, 
-                                                facf, facf,
-                                                ibuf2, ibuf1, NULL);
+                               if (sh.multithreaded)
+                                       out = seq_render_effect_execute_threaded(&sh, context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL);
+                               else
+                                       out = sh.execute(context, seq, cfra, facf, facf, ibuf2, ibuf1, NULL);
                        }
                        else {
-                               out = sh.execute(context, seq, cfra, 
-                                                facf, facf,
-                                                ibuf1, ibuf2, NULL);
+                               if (sh.multithreaded)
+                                       out = seq_render_effect_execute_threaded(&sh, context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL);
+                               else
+                                       out = sh.execute(context, seq, cfra, facf, facf, ibuf1, ibuf2, NULL);
                        }
                
                        IMB_freeImBuf(ibuf1);
index d49ea26..8c0c87e 100644 (file)
@@ -1208,6 +1208,7 @@ static void rna_def_sequence(BlenderRNA *brna)
        
        prop = RNA_def_property(srna, "effect_fader", PROP_FLOAT, PROP_NONE);
        RNA_def_property_range(prop, 0.0f, 1.0f);
+       RNA_def_property_ui_range(prop, 0.0f, 1.0f, 0.1, 3);
        RNA_def_property_float_sdna(prop, NULL, "effect_fader");
        RNA_def_property_ui_text(prop, "Effect fader position", "");
        RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, "rna_Sequence_update");