Commit: 3816502b7ca0728405d8dff8d074e3189740648a
Author: Brecht Van Lommel
Date:   Mon Jun 11 20:00:03 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB3816502b7ca0728405d8dff8d074e3189740648a

Drivers: ensure Python expressions are cached with copy-on-write.

Store the compiled expressions on the original driver.

Ref T55442.

===================================================================

M       source/blender/blenkernel/BKE_fcurve.h
M       source/blender/blenkernel/intern/anim_sys.c
M       source/blender/blenkernel/intern/fcurve.c
M       source/blender/editors/animation/keyframing.c
M       source/blender/python/BPY_extern.h
M       source/blender/python/intern/bpy_driver.c
M       source/blender/python/intern/bpy_driver.h

===================================================================

diff --git a/source/blender/blenkernel/BKE_fcurve.h 
b/source/blender/blenkernel/BKE_fcurve.h
index 09f5ecce050..dbe325b2056 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -108,7 +108,8 @@ bool  driver_get_variable_property(
         struct ChannelDriver *driver, struct DriverTarget *dtar,
         struct PointerRNA *r_ptr, struct PropertyRNA **r_prop, int *r_index);
 
-float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver 
*driver, const float evaltime);
+float evaluate_driver(struct PathResolvedRNA *anim_rna, struct ChannelDriver 
*driver,
+                      struct ChannelDriver *driver_orig, const float evaltime);
 
 /* ************** F-Curve Modifiers *************** */
 
@@ -282,7 +283,8 @@ void correct_bezpart(float v1[2], float v2[2], float v3[2], 
float v4[2]);
 
 /* evaluate fcurve */
 float evaluate_fcurve(struct FCurve *fcu, float evaltime);
-float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve 
*fcu, float evaltime);
+float evaluate_fcurve_driver(struct PathResolvedRNA *anim_rna, struct FCurve 
*fcu,
+                             struct ChannelDriver *driver_orig, float 
evaltime);
 /* evaluate fcurve and store value */
 float calculate_fcurve(struct PathResolvedRNA *anim_rna, struct FCurve *fcu, 
float evaltime);
 
diff --git a/source/blender/blenkernel/intern/anim_sys.c 
b/source/blender/blenkernel/intern/anim_sys.c
index e5a68fa7476..0867170611f 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -3017,7 +3017,7 @@ void BKE_animsys_eval_driver(Depsgraph *depsgraph,
                        PathResolvedRNA anim_rna;
                        if (animsys_store_rna_setting(&id_ptr, NULL, 
fcu->rna_path, fcu->array_index, &anim_rna)) {
                                const float ctime = DEG_get_ctime(depsgraph);
-                               const float curval = 
calculate_fcurve(&anim_rna, fcu, ctime);
+                               const float curval = 
evaluate_fcurve_driver(&anim_rna, fcu, driver_orig, ctime);
                                ok = animsys_write_rna_setting(&anim_rna, 
curval);
                                if (ok && DEG_is_active(depsgraph)) {
                                        animsys_write_orig_anim_rna(&id_ptr, 
NULL, fcu, curval);
diff --git a/source/blender/blenkernel/intern/fcurve.c 
b/source/blender/blenkernel/intern/fcurve.c
index 0de04e31be9..0ffc9054ddd 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1922,13 +1922,14 @@ float driver_get_variable_value(ChannelDriver *driver, 
DriverVar *dvar)
 /* Evaluate an Channel-Driver to get a 'time' value to use instead of 
"evaltime"
  *     - "evaltime" is the frame at which F-Curve is being evaluated
  *  - has to return a float value
+ *  - driver_orig is where we cache Python expressions, in case of COW
  */
-float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, const 
float evaltime)
+float evaluate_driver(PathResolvedRNA *anim_rna, ChannelDriver *driver, 
ChannelDriver *driver_orig, const float evaltime)
 {
        DriverVar *dvar;
        
        /* check if driver can be evaluated */
-       if (driver->flag & DRIVER_FLAG_INVALID)
+       if (driver_orig->flag & DRIVER_FLAG_INVALID)
                return 0.0f;
        
        switch (driver->type) {
@@ -1998,8 +1999,8 @@ float evaluate_driver(PathResolvedRNA *anim_rna, 
ChannelDriver *driver, const fl
                {
 #ifdef WITH_PYTHON
                        /* check for empty or invalid expression */
-                       if ( (driver->expression[0] == '\0') ||
-                            (driver->flag & DRIVER_FLAG_INVALID) )
+                       if ( (driver_orig->expression[0] == '\0') ||
+                            (driver_orig->flag & DRIVER_FLAG_INVALID) )
                        {
                                driver->curval = 0.0f;
                        }
@@ -2009,7 +2010,7 @@ float evaluate_driver(PathResolvedRNA *anim_rna, 
ChannelDriver *driver, const fl
                                 */
                                BLI_mutex_lock(&python_driver_lock);
 
-                               driver->curval = BPY_driver_exec(anim_rna, 
driver, evaltime);
+                               driver->curval = BPY_driver_exec(anim_rna, 
driver, driver_orig, evaltime);
 
                                BLI_mutex_unlock(&python_driver_lock);
                        }
@@ -2705,7 +2706,7 @@ float evaluate_fcurve(FCurve *fcu, float evaltime)
        return evaluate_fcurve_ex(fcu, evaltime, 0.0);
 }
 
-float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, float 
evaltime)
+float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, FCurve *fcu, 
ChannelDriver *driver_orig, float evaltime)
 {
        BLI_assert(fcu->driver != NULL);
        float cvalue = 0.0f;
@@ -2715,7 +2716,7 @@ float evaluate_fcurve_driver(PathResolvedRNA *anim_rna, 
FCurve *fcu, float evalt
         */
        if (fcu->driver) {
                /* evaltime now serves as input for the curve */
-               evaltime = evaluate_driver(anim_rna, fcu->driver, evaltime);
+               evaltime = evaluate_driver(anim_rna, fcu->driver, driver_orig, 
evaltime);
 
                /* only do a default 1-1 mapping if it's unlikely that anything 
else will set a value... */
                if (fcu->totvert == 0) {
@@ -2762,7 +2763,7 @@ float calculate_fcurve(PathResolvedRNA *anim_rna, FCurve 
*fcu, float evaltime)
                /* calculate and set curval (evaluates driver too if necessary) 
*/
                float curval;
                if (fcu->driver) {
-                       curval = evaluate_fcurve_driver(anim_rna, fcu, 
evaltime);
+                       curval = evaluate_fcurve_driver(anim_rna, fcu, 
fcu->driver, evaltime);
                }
                else {
                        curval = evaluate_fcurve(fcu, evaltime);
diff --git a/source/blender/editors/animation/keyframing.c 
b/source/blender/editors/animation/keyframing.c
index 1913eb944d9..fe5714aba2e 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -954,7 +954,7 @@ bool insert_keyframe_direct(Depsgraph *depsgraph, 
ReportList *reports, PointerRN
 
                if (RNA_path_resolved_create(&ptr, prop, fcu->array_index, 
&anim_rna)) {
                        /* for making it easier to add corrective drivers... */
-                       cfra = evaluate_driver(&anim_rna, fcu->driver, cfra);
+                       cfra = evaluate_driver(&anim_rna, fcu->driver, 
fcu->driver, cfra);
                }
                else {
                        cfra = 0.0f;
diff --git a/source/blender/python/BPY_extern.h 
b/source/blender/python/BPY_extern.h
index b4c36a7c516..da1b031f1c0 100644
--- a/source/blender/python/BPY_extern.h
+++ b/source/blender/python/BPY_extern.h
@@ -87,7 +87,8 @@ void  BPY_modules_load_user(struct bContext *C);
 void   BPY_app_handlers_reset(const short do_all);
 
 void   BPY_driver_reset(void);
-float  BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver 
*driver, const float evaltime);
+float  BPY_driver_exec(struct PathResolvedRNA *anim_rna, struct ChannelDriver 
*driver,
+                        struct ChannelDriver *driver_orig, const float 
evaltime);
 
 void   BPY_DECREF(void *pyob_ptr);     /* Py_DECREF() */
 void   BPY_DECREF_RNA_INVALIDATE(void *pyob_ptr);
diff --git a/source/blender/python/intern/bpy_driver.c 
b/source/blender/python/intern/bpy_driver.c
index 215a64a4449..96bfa9f26d3 100644
--- a/source/blender/python/intern/bpy_driver.c
+++ b/source/blender/python/intern/bpy_driver.c
@@ -48,6 +48,8 @@
 
 #include "bpy_driver.h"
 
+#include "BPY_extern.h"
+
 extern void BPY_update_rna_module(void);
 
 #define USE_RNA_AS_PYOBJECT
@@ -196,8 +198,12 @@ static void pydriver_error(ChannelDriver *driver)
  * (new)note: checking if python is running is not threadsafe [#28114]
  * now release the GIL on python operator execution instead, using
  * PyEval_SaveThread() / PyEval_RestoreThread() so we don't lock up blender.
+ *
+ * For copy-on-write we always cache expressions and write errors in the
+ * original driver, otherwise these would get freed while editing. Due to
+ * the GIL this is thread-safe.
  */
-float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, 
const float evaltime)
+float BPY_driver_exec(struct PathResolvedRNA *anim_rna, ChannelDriver *driver, 
ChannelDriver *driver_orig, const float evaltime)
 {
        PyObject *driver_vars = NULL;
        PyObject *retval = NULL;
@@ -213,7 +219,7 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, 
ChannelDriver *driver, c
        int i;
 
        /* get the py expression to be evaluated */
-       expr = driver->expression;
+       expr = driver_orig->expression;
        if (expr[0] == '\0')
                return 0.0f;
 
@@ -249,47 +255,47 @@ float BPY_driver_exec(struct PathResolvedRNA *anim_rna, 
ChannelDriver *driver, c
        /* update global namespace */
        bpy_pydriver_namespace_update_frame(evaltime);
 
-       if (driver->flag & DRIVER_FLAG_USE_SELF) {
+       if (driver_orig->flag & DRIVER_FLAG_USE_SELF) {
                bpy_pydriver_namespace_update_self(anim_rna);
        }
        else {
                bpy_pydriver_namespace_clear_self();
        }
 
-       if (driver->expr_comp == NULL)
-               driver->flag |= DRIVER_FLAG_RECOMPILE;
+       if (driver_orig->expr_comp == NULL)
+               driver_orig->flag |= DRIVER_FLAG_RECOMPILE;
 
        /* compile the expression first if it hasn't been compiled or needs to 
be rebuilt */
-       if (driver->flag & DRIVER_FLAG_RECOMPILE) {
-               Py_XDECREF(driver->expr_comp);
-               driver->expr_comp = PyTuple_New(2);
+       if (driver_orig->flag & DRIVER_FLAG_RECOMPILE) {
+               Py_XDECREF(driver_orig->expr_comp);
+               driver_orig->expr_comp = PyTuple_New(2);
 
                expr_code = Py_CompileString(expr, "<bpy driver>", 
Py_eval_input);
-               PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 0, expr_code);
+               PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 0, 
expr_code);
 
-               driver->flag &= ~DRIVER_FLAG_RECOMPILE;
-               driver->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can be 
removed but for now best keep until were sure */
+               driver_orig->flag &= ~DRIVER_FLAG_RECOMPILE;
+               driver_orig->flag |= DRIVER_FLAG_RENAMEVAR; /* maybe this can 
be removed but for now best keep until were sure */
        }
        else {
-               expr_code = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 
0);
+               expr_code = PyTuple_GET_ITEM(((PyObject 
*)driver_orig->expr_comp), 0);
        }
 
-       if (driver->flag & DRIVER_FLAG_RENAMEVAR) {
+       if (driver_orig->flag & DRIVER_FLAG_RENAMEVAR) {
                /* may not be set */
-               expr_vars = PyTuple_GET_ITEM(((PyObject *)driver->expr_comp), 
1);
+               expr_vars = PyTuple_GET_ITEM(((PyObject 
*)driver_orig->expr_comp), 1);
                Py_XDECREF(expr_vars);
 
-               expr_vars = PyTuple_New(BLI_listbase_count(&driver->variables));
-               PyTuple_SET_ITEM(((PyObject *)driver->expr_comp), 1, expr_vars);
+               expr_vars = 
PyTuple_New(BLI_listbase_count(&driver_orig->variables));
+               PyTuple_SET_ITEM(((PyObject *)driver_orig->expr_comp), 1, 
expr_vars);
 
-               for (dvar = driver->variables.first, i = 0; dvar; dvar = 
dvar->next) {
+               for (dvar = driver_orig->variable

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to