Initial step for IDTypeInfo refactor 'cleanup' project.
[blender.git] / source / creator / creator.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  */
19
20 /** \file
21  * \ingroup creator
22  */
23
24 #include <stdlib.h>
25 #include <string.h>
26
27 #ifdef WIN32
28 #  include <windows.h>
29 #  include "utfconv.h"
30 #endif
31
32 #if defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG)
33 #  pragma comment(lib, "tbbmalloc_proxy.lib")
34 #  pragma comment(linker, "/include:__TBB_malloc_proxy")
35 #endif
36
37 #include "MEM_guardedalloc.h"
38
39 #include "CLG_log.h"
40
41 #include "DNA_genfile.h"
42
43 #include "BLI_args.h"
44 #include "BLI_threads.h"
45 #include "BLI_utildefines.h"
46 #include "BLI_string.h"
47 #include "BLI_system.h"
48
49 /* mostly init functions */
50 #include "BKE_appdir.h"
51 #include "BKE_blender.h"
52 #include "BKE_brush.h"
53 #include "BKE_cachefile.h"
54 #include "BKE_callbacks.h"
55 #include "BKE_context.h"
56 #include "BKE_font.h"
57 #include "BKE_global.h"
58 #include "BKE_idtype.h"
59 #include "BKE_material.h"
60 #include "BKE_modifier.h"
61 #include "BKE_gpencil_modifier.h"
62 #include "BKE_node.h"
63 #include "BKE_shader_fx.h"
64 #include "BKE_sound.h"
65 #include "BKE_image.h"
66 #include "BKE_particle.h"
67
68 #include "DEG_depsgraph.h"
69
70 #include "IMB_imbuf.h" /* for IMB_init */
71
72 #include "RE_engine.h"
73 #include "RE_render_ext.h"
74
75 #include "ED_datafiles.h"
76
77 #include "WM_api.h"
78 #include "WM_toolsystem.h"
79
80 #include "RNA_define.h"
81
82 #ifdef WITH_FREESTYLE
83 #  include "FRS_freestyle.h"
84 #endif
85
86 #include <signal.h>
87
88 #ifdef __FreeBSD__
89 #  include <floatingpoint.h>
90 #endif
91
92 #ifdef WITH_BINRELOC
93 #  include "binreloc.h"
94 #endif
95
96 #ifdef WITH_LIBMV
97 #  include "libmv-capi.h"
98 #endif
99
100 #ifdef WITH_CYCLES_LOGGING
101 #  include "CCL_api.h"
102 #endif
103
104 #ifdef WITH_SDL_DYNLOAD
105 #  include "sdlew.h"
106 #endif
107
108 #include "creator_intern.h" /* own include */
109
110 /*  Local Function prototypes */
111 #ifdef WITH_PYTHON_MODULE
112 int main_python_enter(int argc, const char **argv);
113 void main_python_exit(void);
114 #endif
115
116 #ifdef WITH_USD
117 /**
118  * Workaround to make it possible to pass a path at runtime to USD.
119  *
120  * USD requires some JSON files, and it uses a static constructor to determine the possible
121  * file-system paths to find those files. This made it impossible for Blender to pass a path to the
122  * USD library at runtime, as the constructor would run before Blender's main() function. We have
123  * patched USD (see usd.diff) to avoid that particular static constructor, and have an
124  * initialization function instead.
125  *
126  * This function is implemented in the USD source code, pxr/base/lib/plug/initConfig.cpp.
127  */
128 void usd_initialise_plugin_path(const char *datafiles_usd_path);
129 #endif
130
131 /* written to by 'creator_args.c' */
132 struct ApplicationState app_state = {
133     .signal =
134         {
135             .use_crash_handler = true,
136             .use_abort_handler = true,
137         },
138     .exit_code_on_error =
139         {
140             .python = 0,
141         },
142 };
143
144 /* -------------------------------------------------------------------- */
145 /** \name Application Level Callbacks
146  *
147  * Initialize callbacks for the modules that need them.
148  *
149  * \{ */
150
151 static void callback_mem_error(const char *errorStr)
152 {
153   fputs(errorStr, stderr);
154   fflush(stderr);
155 }
156
157 static void main_callback_setup(void)
158 {
159   /* Error output from the alloc routines: */
160   MEM_set_error_callback(callback_mem_error);
161 }
162
163 /* free data on early exit (if Python calls 'sys.exit()' while parsing args for eg). */
164 struct CreatorAtExitData {
165   bArgs *ba;
166 #ifdef WIN32
167   const char **argv;
168   int argv_num;
169 #endif
170 };
171
172 static void callback_main_atexit(void *user_data)
173 {
174   struct CreatorAtExitData *app_init_data = user_data;
175
176   if (app_init_data->ba) {
177     BLI_argsFree(app_init_data->ba);
178     app_init_data->ba = NULL;
179   }
180
181 #ifdef WIN32
182   if (app_init_data->argv) {
183     while (app_init_data->argv_num) {
184       free((void *)app_init_data->argv[--app_init_data->argv_num]);
185     }
186     free((void *)app_init_data->argv);
187     app_init_data->argv = NULL;
188   }
189 #endif
190 }
191
192 static void callback_clg_fatal(void *fp)
193 {
194   BLI_system_backtrace(fp);
195 }
196
197 /** \} */
198
199 /* -------------------------------------------------------------------- */
200 /** \name Main Function
201  * \{ */
202
203 #ifdef WITH_PYTHON_MODULE
204 /* allow python module to call main */
205 #  define main main_python_enter
206 static void *evil_C = NULL;
207
208 #  ifdef __APPLE__
209 /* environ is not available in mac shared libraries */
210 #    include <crt_externs.h>
211 char **environ = NULL;
212 #  endif
213 #endif
214
215 /**
216  * Blender's main function responsibilities are:
217  * - setup subsystems.
218  * - handle arguments.
219  * - run #WM_main() event loop,
220  *   or exit immediately when running in background mode.
221  */
222 int main(int argc,
223 #ifdef WIN32
224          const char **UNUSED(argv_c)
225 #else
226          const char **argv
227 #endif
228 )
229 {
230   bContext *C;
231
232 #ifndef WITH_PYTHON_MODULE
233   bArgs *ba;
234 #endif
235
236 #ifdef WIN32
237   char **argv;
238   int argv_num;
239 #endif
240
241   /* --- end declarations --- */
242
243   /* ensure we free data on early-exit */
244   struct CreatorAtExitData app_init_data = {NULL};
245   BKE_blender_atexit_register(callback_main_atexit, &app_init_data);
246
247   /* Unbuffered stdout makes stdout and stderr better synchronized, and helps
248    * when stepping through code in a debugger (prints are immediately
249    * visible). */
250   setvbuf(stdout, NULL, _IONBF, 0);
251
252 #ifdef WIN32
253   /* We delay loading of openmp so we can set the policy here. */
254 #  if defined(_MSC_VER)
255   _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
256 #  endif
257
258   /* Win32 Unicode Args */
259   /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
260    *       (it depends on the args passed in, which is what we're getting here!)
261    */
262   {
263     wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
264     argv = malloc(argc * sizeof(char *));
265     for (argv_num = 0; argv_num < argc; argv_num++) {
266       argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
267     }
268     LocalFree(argv_16);
269
270     /* free on early-exit */
271     app_init_data.argv = argv;
272     app_init_data.argv_num = argv_num;
273   }
274 #endif /* WIN32 */
275
276   /* NOTE: Special exception for guarded allocator type switch:
277    *       we need to perform switch from lock-free to fully
278    *       guarded allocator before any allocation happened.
279    */
280   {
281     int i;
282     for (i = 0; i < argc; i++) {
283       if (STR_ELEM(argv[i], "-d", "--debug", "--debug-memory", "--debug-all")) {
284         printf("Switching to fully guarded memory allocator.\n");
285         MEM_use_guarded_allocator();
286         break;
287       }
288       else if (STREQ(argv[i], "--")) {
289         break;
290       }
291     }
292   }
293
294 #ifdef BUILD_DATE
295   {
296     time_t temp_time = build_commit_timestamp;
297     struct tm *tm = gmtime(&temp_time);
298     if (LIKELY(tm)) {
299       strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
300       strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
301     }
302     else {
303       const char *unknown = "date-unknown";
304       BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
305       BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
306     }
307   }
308 #endif
309
310 #ifdef WITH_SDL_DYNLOAD
311   sdlewInit();
312 #endif
313
314   /* Initialize logging */
315   CLG_init();
316   CLG_fatal_fn_set(callback_clg_fatal);
317
318   C = CTX_create();
319
320 #ifdef WITH_PYTHON_MODULE
321 #  ifdef __APPLE__
322   environ = *_NSGetEnviron();
323 #  endif
324
325 #  undef main
326   evil_C = C;
327 #endif
328
329 #ifdef WITH_BINRELOC
330   br_init(NULL);
331 #endif
332
333 #ifdef WITH_LIBMV
334   libmv_initLogging(argv[0]);
335 #elif defined(WITH_CYCLES_LOGGING)
336   CCL_init_logging(argv[0]);
337 #endif
338
339   main_callback_setup();
340
341 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
342   /* patch to ignore argument finder gives us (pid?) */
343   if (argc == 2 && STREQLEN(argv[1], "-psn_", 5)) {
344     extern int GHOST_HACK_getFirstFile(char buf[]);
345     static char firstfilebuf[512];
346
347     argc = 1;
348
349     if (GHOST_HACK_getFirstFile(firstfilebuf)) {
350       argc = 2;
351       argv[1] = firstfilebuf;
352     }
353   }
354 #endif
355
356 #ifdef __FreeBSD__
357   fpsetmask(0);
358 #endif
359
360   /* initialize path to executable */
361   BKE_appdir_program_path_init(argv[0]);
362
363   BLI_threadapi_init();
364   BLI_thread_put_process_on_fast_node();
365
366   DNA_sdna_current_init();
367
368   BKE_blender_globals_init(); /* blender.c */
369
370   BKE_idtype_init();
371   IMB_init();
372   BKE_cachefiles_init();
373   BKE_images_init();
374   BKE_modifier_init();
375   BKE_gpencil_modifier_init();
376   BKE_shaderfx_init();
377   DEG_register_node_types();
378
379   BKE_brush_system_init();
380   RE_texture_rng_init();
381
382   BKE_callback_global_init();
383
384   /* first test for background */
385 #ifndef WITH_PYTHON_MODULE
386   ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
387
388   /* ensure we free on early exit */
389   app_init_data.ba = ba;
390
391   main_args_setup(C, ba);
392
393   BLI_argsParse(ba, 1, NULL, NULL);
394
395   main_signal_setup();
396
397 #else
398   /* using preferences or user startup makes no sense for py-as-module */
399   G.factory_startup = true;
400 #endif
401
402 #ifdef WITH_FFMPEG
403   IMB_ffmpeg_init();
404 #endif
405
406   /* after level 1 args, this is so playanim skips RNA init */
407   RNA_init();
408
409   RE_engines_init();
410   init_nodesystem();
411   psys_init_rng();
412   /* end second init */
413
414 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
415   G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
416 #else
417   if (G.background) {
418     main_signal_setup_background();
419   }
420 #endif
421
422   /* background render uses this font too */
423   BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
424
425   /* Initialize ffmpeg if built in, also needed for background-mode if videos are
426    * rendered via ffmpeg. */
427   BKE_sound_init_once();
428
429   BKE_materials_init();
430
431 #ifdef WITH_USD
432   /* Tell USD which directory to search for its JSON files. If datafiles/usd
433    * does not exist, the USD library will not be able to read or write any files.
434    */
435   usd_initialise_plugin_path(BKE_appdir_folder_id(BLENDER_DATAFILES, "usd"));
436 #endif
437
438   if (G.background == 0) {
439 #ifndef WITH_PYTHON_MODULE
440     BLI_argsParse(ba, 2, NULL, NULL);
441     BLI_argsParse(ba, 3, NULL, NULL);
442 #endif
443     WM_init(C, argc, (const char **)argv);
444
445     /* this is properly initialized with user defs, but this is default */
446     /* call after loading the startup.blend so we can read U.tempdir */
447     BKE_tempdir_init(U.tempdir);
448   }
449   else {
450 #ifndef WITH_PYTHON_MODULE
451     BLI_argsParse(ba, 3, NULL, NULL);
452 #endif
453
454     WM_init(C, argc, (const char **)argv);
455
456     /* don't use user preferences temp dir */
457     BKE_tempdir_init(NULL);
458   }
459 #ifdef WITH_PYTHON
460   /**
461    * NOTE: the U.pythondir string is NULL until WM_init() is executed,
462    * so we provide the BPY_ function below to append the user defined
463    * python-dir to Python's sys.path at this point.  Simply putting
464    * WM_init() before #BPY_python_start() crashes Blender at startup.
465    */
466
467   /* TODO - U.pythondir */
468 #else
469   printf(
470       "\n* WARNING * - Blender compiled without Python!\n"
471       "this is not intended for typical usage\n\n");
472 #endif
473
474   CTX_py_init_set(C, true);
475   WM_keyconfig_init(C);
476
477 #ifdef WITH_FREESTYLE
478   /* initialize Freestyle */
479   FRS_initialize();
480   FRS_set_context(C);
481 #endif
482
483   /* OK we are ready for it */
484 #ifndef WITH_PYTHON_MODULE
485   main_args_setup_post(C, ba);
486 #endif
487
488   /* Explicitly free data allocated for argument parsing:
489    * - 'ba'
490    * - 'argv' on WIN32.
491    */
492   callback_main_atexit(&app_init_data);
493   BKE_blender_atexit_unregister(callback_main_atexit, &app_init_data);
494
495   /* paranoid, avoid accidental re-use */
496 #ifndef WITH_PYTHON_MODULE
497   ba = NULL;
498   (void)ba;
499 #endif
500
501 #ifdef WIN32
502   argv = NULL;
503   (void)argv;
504 #endif
505
506 #ifdef WITH_PYTHON_MODULE
507   return 0; /* keep blender in background mode running */
508 #endif
509
510   if (G.background) {
511     /* Using window-manager API in background mode is a bit odd, but works fine. */
512     WM_exit(C);
513   }
514   else {
515     if (!G.file_loaded) {
516       WM_init_splash(C);
517     }
518   }
519
520   WM_main(C);
521
522   return 0;
523 } /* end of int main(argc, argv) */
524
525 #ifdef WITH_PYTHON_MODULE
526 void main_python_exit(void)
527 {
528   WM_exit_ex((bContext *)evil_C, true);
529   evil_C = NULL;
530 }
531 #endif
532
533 /** \} */