Ghost Context Refactor
[blender-staging.git] / source / creator / creator.c
index b442194bd7df2a3d4b26760b3d88671e45efda6d..12ae5c502e4f2344df3d0e696f7f2ad6f164ca9b 100644 (file)
 #  include <xmmintrin.h>
 #endif
 
-/* crash handler */
-#ifdef WIN32
-#  include <process.h> /* getpid */
-#else
-#  include <unistd.h> /* getpid */
-#endif
-
 #ifdef WIN32
+#  if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64)
+#    include <math.h> /* needed for _set_FMA3_enable */
+#  endif
 #  include <windows.h>
 #  include "utfconv.h"
 #endif
@@ -63,6 +59,7 @@
 #include <stddef.h>
 #include <string.h>
 #include <errno.h>
+#include <time.h>
 
 /* This little block needed for linking to Blender... */
 
 #include "BLI_threads.h"
 #include "BLI_utildefines.h"
 #include "BLI_callbacks.h"
+#include "BLI_blenlib.h"
+#include "BLI_mempool.h"
+#include "BLI_system.h"
+#include BLI_SYSTEM_PID_H
 
 #include "DNA_ID.h"
 #include "DNA_scene_types.h"
 #include "DNA_userdef_types.h"
 
-#include "BLI_blenlib.h"
-
 #include "BKE_blender.h"
 #include "BKE_brush.h"
 #include "BKE_context.h"
 #include "BKE_main.h"
 #include "BKE_material.h"
 #include "BKE_modifier.h"
-#include "BKE_packedFile.h"
 #include "BKE_scene.h"
 #include "BKE_node.h"
 #include "BKE_report.h"
 #include "BKE_sound.h"
 #include "BKE_image.h"
+#include "BKE_particle.h"
 
 #include "IMB_imbuf.h"  /* for IMB_init */
 
 #include "RE_pipeline.h"
 
 #include "ED_datafiles.h"
+#include "ED_util.h"
 
 #include "WM_api.h"
 
 #  include "libmv-capi.h"
 #endif
 
+#ifdef WITH_CYCLES_LOGGING
+#  include "CCL_api.h"
+#endif
+
 /* from buildinfo.c */
 #ifdef BUILD_DATE
 extern char build_date[];
 extern char build_time[];
-extern char build_rev[];
+extern char build_hash[];
+extern unsigned long build_commit_timestamp;
+
+/* TODO(sergey): ideally size need to be in sync with buildinfo.c */
+extern char build_commit_date[16];
+extern char build_commit_time[16];
+
+extern char build_branch[];
 extern char build_platform[];
 extern char build_type[];
 extern char build_cflags[];
@@ -200,7 +211,7 @@ static void blender_esc(int sig)
 {
        static int count = 0;
        
-       G.is_break = TRUE;  /* forces render loop to read queue, not sure if its needed */
+       G.is_break = true;  /* forces render loop to read queue, not sure if its needed */
        
        if (sig == 2) {
                if (count) {
@@ -219,7 +230,9 @@ static int print_version(int UNUSED(argc), const char **UNUSED(argv), void *UNUS
 #ifdef BUILD_DATE
        printf("\tbuild date: %s\n", build_date);
        printf("\tbuild time: %s\n", build_time);
-       printf("\tbuild revision: %s\n", build_rev);
+       printf("\tbuild commit date: %s\n", build_commit_date);
+       printf("\tbuild commit time: %s\n", build_commit_time);
+       printf("\tbuild hash: %s\n", build_hash);
        printf("\tbuild platform: %s\n", build_platform);
        printf("\tbuild type: %s\n", build_type);
        printf("\tbuild c flags: %s\n", build_cflags);
@@ -300,8 +313,13 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
 #ifdef WITH_LIBMV
        BLI_argsPrintArgDoc(ba, "--debug-libmv");
 #endif
+#ifdef WITH_CYCLES_LOGGING
+       BLI_argsPrintArgDoc(ba, "--debug-cycles");
+#endif
+       BLI_argsPrintArgDoc(ba, "--debug-memory");
        BLI_argsPrintArgDoc(ba, "--debug-jobs");
        BLI_argsPrintArgDoc(ba, "--debug-python");
+       BLI_argsPrintArgDoc(ba, "--debug-depsgraph");
 
        BLI_argsPrintArgDoc(ba, "--debug-wm");
        BLI_argsPrintArgDoc(ba, "--debug-all");
@@ -358,7 +376,7 @@ static int print_help(int UNUSED(argc), const char **UNUSED(argv), void *data)
        printf("  $BLENDER_USER_CONFIG      Directory for user configuration files.\n");
        printf("  $BLENDER_USER_SCRIPTS     Directory for user scripts.\n");
        printf("  $BLENDER_SYSTEM_SCRIPTS   Directory for system wide scripts.\n");
-       printf("  Directory for user data files (icons, translations, ..).\n");
+       printf("  $BLENDER_USER_DATAFILES   Directory for user data files (icons, translations, ..).\n");
        printf("  $BLENDER_SYSTEM_DATAFILES Directory for system wide data files.\n");
        printf("  $BLENDER_SYSTEM_PYTHON    Directory for system python libraries.\n");
 #ifdef WIN32
@@ -412,10 +430,13 @@ static int debug_mode(int UNUSED(argc), const char **UNUSED(argv), void *data)
        G.debug |= G_DEBUG;  /* std output printf's */
        printf(BLEND_VERSION_STRING_FMT);
        MEM_set_memory_debug();
+#ifdef DEBUG
+       BLI_mempool_set_memory_debug();
+#endif
 
 #ifdef WITH_BUILDINFO
        printf("Build: %s %s %s %s\n", build_date, build_time, build_platform, build_type);
-#endif // WITH_BUILDINFO
+#endif
 
        BLI_argsPrint(data);
        return 0;
@@ -436,6 +457,21 @@ static int debug_mode_libmv(int UNUSED(argc), const char **UNUSED(argv), void *U
 }
 #endif
 
+#ifdef WITH_CYCLES_LOGGING
+static int debug_mode_cycles(int UNUSED(argc), const char **UNUSED(argv),
+                             void *UNUSED(data))
+{
+       CCL_start_debug_logging();
+       return 0;
+}
+#endif
+
+static int debug_mode_memory(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data))
+{
+       MEM_set_memory_debug();
+       return 0;
+}
+
 static int set_debug_value(int argc, const char **argv, void *UNUSED(data))
 {
        if (argc > 1) {
@@ -515,10 +551,10 @@ static void blender_crash_handler_backtrace(FILE *fp)
 
        process = GetCurrentProcess();
 
-       SymInitialize(process, NULL, TRUE);
+       SymInitialize(process, NULL, true);
 
        nframes = CaptureStackBackTrace(0, SIZE, stack, NULL);
-       symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof( char ), "crash Symbol table");
+       symbolinfo = MEM_callocN(sizeof(SYMBOL_INFO) + MAXSYMBOL * sizeof(char), "crash Symbol table");
        symbolinfo->MaxNameLen = MAXSYMBOL - 1;
        symbolinfo->SizeOfStruct = sizeof(SYMBOL_INFO);
 
@@ -549,7 +585,7 @@ static void blender_crash_handler(int signum)
                char fname[FILE_MAX];
 
                if (!G.main->name[0]) {
-                       BLI_make_file_string("/", fname, BLI_temporary_dir(), "crash.blend");
+                       BLI_make_file_string("/", fname, BLI_temp_dir_base(), "crash.blend");
                }
                else {
                        BLI_strncpy(fname, G.main->name, sizeof(fname));
@@ -570,23 +606,22 @@ static void blender_crash_handler(int signum)
        char fname[FILE_MAX];
 
        if (!G.main->name[0]) {
-               BLI_join_dirfile(fname, sizeof(fname), BLI_temporary_dir(), "blender.crash.txt");
+               BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), "blender.crash.txt");
        }
        else {
-               BLI_join_dirfile(fname, sizeof(fname), BLI_temporary_dir(), BLI_path_basename(G.main->name));
+               BLI_join_dirfile(fname, sizeof(fname), BLI_temp_dir_base(), BLI_path_basename(G.main->name));
                BLI_replace_extension(fname, sizeof(fname), ".crash.txt");
        }
 
        printf("Writing: %s\n", fname);
        fflush(stdout);
 
-       BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Revision: %s\n", BLEND_VERSION_ARG,
-#ifdef BUILD_DATE
-                    build_rev
+#ifndef BUILD_DATE
+       BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Unknown revision\n", BLEND_VERSION_ARG);
 #else
-                    "Unknown"
+       BLI_snprintf(header, sizeof(header), "# " BLEND_VERSION_FMT ", Commit date: %s %s, Hash %s\n",
+                    BLEND_VERSION_ARG, build_commit_date, build_commit_time, build_hash);
 #endif
-                    );
 
        /* open the crash log */
        errno = 0;
@@ -605,6 +640,8 @@ static void blender_crash_handler(int signum)
                fclose(fp);
        }
 
+       /* Delete content of temp dir! */
+       BLI_temp_dir_session_purge();
 
        /* really crash */
        signal(signum, SIG_DFL);
@@ -760,7 +797,7 @@ static int set_audio(int argc, const char **argv, void *UNUSED(data))
 static int set_output(int argc, const char **argv, void *data)
 {
        bContext *C = data;
-       if (argc >= 1) {
+       if (argc > 1) {
                Scene *scene = CTX_data_scene(C);
                if (scene) {
                        BLI_strncpy(scene->r.pic, argv[1], sizeof(scene->r.pic));
@@ -796,6 +833,9 @@ static int set_engine(int argc, const char **argv, void *data)
                                if (BLI_findstring(&R_engines, argv[1], offsetof(RenderEngineType, idname))) {
                                        BLI_strncpy_utf8(rd->engine, argv[1], sizeof(rd->engine));
                                }
+                               else {
+                                       printf("\nError: engine not found '%s'\n", argv[1]);
+                               }
                        }
                        else {
                                printf("\nError: no blend loaded. order the arguments so '-E  / --engine ' is after a blend is loaded.\n");
@@ -851,7 +891,7 @@ static int set_threads(int argc, const char **argv, void *UNUSED(data))
                return 1;
        }
        else {
-               printf("\nError: you must specify a number of threads between 0 and 8 '-t  / --threads'.\n");
+               printf("\nError: you must specify a number of threads between 0 and %d '-t / --threads'.\n", BLENDER_MAX_THREADS);
                return 0;
        }
 }
@@ -863,6 +903,8 @@ static int set_verbosity(int argc, const char **argv, void *UNUSED(data))
 
 #ifdef WITH_LIBMV
                libmv_setLoggingVerbosity(level);
+#elif defined(WITH_CYCLES_LOGGING)
+               CCL_logging_verbosity_set(level);
 #else
                (void)level;
 #endif
@@ -878,7 +920,7 @@ static int set_verbosity(int argc, const char **argv, void *UNUSED(data))
 static int set_extension(int argc, const char **argv, void *data)
 {
        bContext *C = data;
-       if (argc >= 1) {
+       if (argc > 1) {
                Scene *scene = CTX_data_scene(C);
                if (scene) {
                        if (argv[1][0] == '0') {
@@ -983,6 +1025,7 @@ static int render_frame(int argc, const char **argv, void *data)
                                        break;
                        }
 
+                       BLI_begin_threaded_malloc();
                        BKE_reports_init(&reports, RPT_PRINT);
 
                        frame = CLAMPIS(frame, MINAFRAME, MAXFRAME);
@@ -990,6 +1033,7 @@ static int render_frame(int argc, const char **argv, void *data)
                        RE_SetReports(re, &reports);
                        RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, frame, frame, scene->r.frame_step);
                        RE_SetReports(re, NULL);
+                       BLI_end_threaded_malloc();
                        return 1;
                }
                else {
@@ -1011,10 +1055,12 @@ static int render_animation(int UNUSED(argc), const char **UNUSED(argv), void *d
                Main *bmain = CTX_data_main(C);
                Render *re = RE_NewRender(scene->id.name);
                ReportList reports;
+               BLI_begin_threaded_malloc();
                BKE_reports_init(&reports, RPT_PRINT);
                RE_SetReports(re, &reports);
                RE_BlenderAnim(re, bmain, scene, NULL, scene->lay, scene->r.sfra, scene->r.efra, scene->r.frame_step);
                RE_SetReports(re, NULL);
+               BLI_end_threaded_malloc();
        }
        else {
                printf("\nError: no blend loaded. cannot use '-a'.\n");
@@ -1233,19 +1279,24 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
        BLI_path_cwd(filename);
 
        if (G.background) {
-               int retval = BKE_read_file(C, filename, NULL);
+               int retval;
+
+               BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_PRE);
+
+               retval = BKE_read_file(C, filename, NULL);
 
                /* we successfully loaded a blend file, get sure that
                 * pointcache works */
                if (retval != BKE_READ_FILE_FAIL) {
                        wmWindowManager *wm = CTX_wm_manager(C);
+                       Main *bmain = CTX_data_main(C);
 
                        /* special case, 2.4x files */
-                       if (wm == NULL && CTX_data_main(C)->wm.first == NULL) {
+                       if (wm == NULL && BLI_listbase_is_empty(&bmain->wm)) {
                                extern void wm_add_default(bContext *C);
 
                                /* wm_add_default() needs the screen to be set. */
-                               CTX_wm_screen_set(C, CTX_data_main(C)->screen.first);
+                               CTX_wm_screen_set(C, bmain->screen.first);
                                wm_add_default(C);
                        }
 
@@ -1254,7 +1305,10 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
                        G.relbase_valid = 1;
                        if (CTX_wm_manager(C) == NULL) CTX_wm_manager_set(C, wm);  /* reset wm */
 
-                       DAG_on_visible_update(CTX_data_main(C), TRUE);
+                       /* WM_file_read would call normally */
+                       ED_editors_init(C);
+                       DAG_on_visible_update(bmain, true);
+                       BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C));
                }
                else {
                        /* failed to load file, stop processing arguments */
@@ -1267,6 +1321,8 @@ static int load_file(int UNUSED(argc), const char **argv, void *data)
                BPY_python_reset(C);
 #endif
 
+               BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST);
+
                /* happens for the UI on file reading too (huh? (ton))*/
                // XXX          BKE_reset_undo();
                //                      BKE_write_undo("original");     /* save current state */
@@ -1356,7 +1412,7 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
 #undef PY_ENABLE_AUTO
 #undef PY_DISABLE_AUTO
        
-       BLI_argsAdd(ba, 1, "-b", "--background", "<file>\n\tLoad <file> in background (often used for UI-less rendering)", background_mode, NULL);
+       BLI_argsAdd(ba, 1, "-b", "--background", "\n\tRun in background (often used for UI-less rendering)", background_mode, NULL);
 
        BLI_argsAdd(ba, 1, "-a", NULL, playback_doc, playback_mode, NULL);
 
@@ -1381,9 +1437,14 @@ static void setupArguments(bContext *C, bArgs *ba, SYS_SystemHandle *syshandle)
 #ifdef WITH_LIBMV
        BLI_argsAdd(ba, 1, NULL, "--debug-libmv", "\n\tEnable debug messages from libmv library", debug_mode_libmv, NULL);
 #endif
+#ifdef WITH_CYCLES_LOGGING
+       BLI_argsAdd(ba, 1, NULL, "--debug-cycles", "\n\tEnable debug messages from Cycles", debug_mode_cycles, NULL);
+#endif
+       BLI_argsAdd(ba, 1, NULL, "--debug-memory", "\n\tEnable fully guarded memory allocation and debugging", debug_mode_memory, NULL);
 
        BLI_argsAdd(ba, 1, NULL, "--debug-value", "<value>\n\tSet debug value of <value> on startup\n", set_debug_value, NULL);
        BLI_argsAdd(ba, 1, NULL, "--debug-jobs",  "\n\tEnable time profiling for background jobs.", debug_mode_generic, (void *)G_DEBUG_JOBS);
+       BLI_argsAdd(ba, 1, NULL, "--debug-depsgraph", "\n\tEnable debug messages from dependency graph", debug_mode_generic, (void *)G_DEBUG_DEPSGRAPH);
 
        BLI_argsAdd(ba, 1, NULL, "--verbose", "<verbose>\n\tSet logging verbosity level.", set_verbosity, NULL);
 
@@ -1444,14 +1505,23 @@ char **environ = NULL;
 #  endif
 #endif
 
-
+/**
+ * Blender's main function responsabilities are:
+ * - setup subsystems.
+ * - handle arguments.
+ * - run WM_main() event loop,
+ *   or exit when running in background mode.
+ */
+int main(
+       int argc,
 #ifdef WIN32
-int main(int argc, const char **UNUSED(argv_c)) /* Do not mess with const */
+        const char **UNUSED(argv_c)
 #else
-int main(int argc, const char **argv)
+        const char **argv
 #endif
+         )
 {
-       bContext *C = CTX_create();
+       bContext *C;
        SYS_SystemHandle syshandle;
 
 #ifndef WITH_PYTHON_MODULE
@@ -1459,15 +1529,64 @@ int main(int argc, const char **argv)
 #endif
 
 #ifdef WIN32
+       /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
+#  if defined(_MSC_VER) && _MSC_VER >= 1800 && defined(_M_X64)
+       _set_FMA3_enable(0);
+#  endif
+
+       /* Win32 Unicode Args */
+       /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
+        *       (it depends on the args passed in, which is what we're getting here!)
+        */
        wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
+       char **argv = malloc(argc * sizeof(char *));
        int argci = 0;
-       char **argv = MEM_mallocN(argc * sizeof(char *), "argv array");
+       
        for (argci = 0; argci < argc; argci++) {
                argv[argci] = alloc_utf_8_from_16(argv_16[argci], 0);
        }
+       
        LocalFree(argv_16);
 #endif
 
+       /* NOTE: Special exception for guarded allocator type switch:
+        *       we need to perform switch from lock-free to fully
+        *       guarded allocator before any allocation happened.
+        */
+       {
+               int i;
+               for (i = 0; i < argc; i++) {
+                       if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
+                           STREQ(argv[i], "--debug-memory"))
+                       {
+                               printf("Switching to fully guarded memory allocator.\n");
+                               MEM_use_guarded_allocator();
+                               break;
+                       }
+                       else if (STREQ(argv[i], "--")) {
+                               break;
+                       }
+               }
+       }
+
+#ifdef BUILD_DATE
+       {
+               time_t temp_time = build_commit_timestamp;
+               struct tm *tm = gmtime(&temp_time);
+               if (LIKELY(tm)) {
+                       strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
+                       strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
+               }
+               else {
+                       const char *unknown = "date-unknown";
+                       BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
+                       BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
+               }
+       }
+#endif
+
+       C = CTX_create();
+
 #ifdef WITH_PYTHON_MODULE
 #ifdef __APPLE__
        environ = *_NSGetEnviron();
@@ -1485,24 +1604,11 @@ int main(int argc, const char **argv)
 
 #ifdef WITH_LIBMV
        libmv_initLogging(argv[0]);
+#elif defined(WITH_CYCLES_LOGGING)
+       CCL_init_logging(argv[0]);
 #endif
 
        setCallbacks();
-#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
-       /* patch to ignore argument finder gives us (pid?) */
-       if (argc == 2 && strncmp(argv[1], "-psn_", 5) == 0) {
-               extern int GHOST_HACK_getFirstFile(char buf[]);
-               static char firstfilebuf[512];
-
-               argc = 1;
-
-               if (GHOST_HACK_getFirstFile(firstfilebuf)) {
-                       argc = 2;
-                       argv[1] = firstfilebuf;
-               }
-       }
-
-#endif
 
 #ifdef __FreeBSD__
        fpsetmask(0);
@@ -1518,6 +1624,7 @@ int main(int argc, const char **argv)
        IMB_init();
        BKE_images_init();
        BKE_modifier_init();
+       DAG_init();
 
        BKE_brush_system_init();
 
@@ -1554,6 +1661,7 @@ int main(int argc, const char **argv)
 
        RE_engines_init();
        init_nodesystem();
+       psys_init_rng();
        /* end second init */
 
 
@@ -1584,7 +1692,7 @@ int main(int argc, const char **argv)
 
                /* this is properly initialized with user defs, but this is default */
                /* call after loading the startup.blend so we can read U.tempdir */
-               BLI_init_temporary_dir(U.tempdir);
+               BLI_temp_dir_init(U.tempdir);
        }
        else {
 #ifndef WITH_PYTHON_MODULE
@@ -1594,7 +1702,7 @@ int main(int argc, const char **argv)
                WM_init(C, argc, (const char **)argv);
 
                /* don't use user preferences temp dir */
-               BLI_init_temporary_dir(NULL);
+               BLI_temp_dir_init(NULL);
        }
 #ifdef WITH_PYTHON
        /**
@@ -1638,7 +1746,7 @@ int main(int argc, const char **argv)
        while (argci) {
                free(argv[--argci]);
        }
-       MEM_freeN(argv);
+       free(argv);
        argv = NULL;
 #endif
 
@@ -1678,7 +1786,7 @@ int main(int argc, const char **argv)
 #ifdef WITH_PYTHON_MODULE
 void main_python_exit(void)
 {
-       WM_exit((bContext *)evil_C);
+       WM_exit_ext((bContext *)evil_C, true);
        evil_C = NULL;
 }
 #endif