Blender  V3.3
creator.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #ifdef WIN32
12 # include "utfconv.h"
13 # include <windows.h>
14 #endif
15 
16 #if defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG)
17 # pragma comment(lib, "tbbmalloc_proxy.lib")
18 # pragma comment(linker, "/include:__TBB_malloc_proxy")
19 #endif
20 
21 #include "MEM_guardedalloc.h"
22 
23 #include "CLG_log.h"
24 
25 #include "DNA_genfile.h"
26 
27 #include "BLI_args.h"
28 #include "BLI_string.h"
29 #include "BLI_system.h"
30 #include "BLI_task.h"
31 #include "BLI_threads.h"
32 #include "BLI_utildefines.h"
33 
34 /* Mostly initialization functions. */
35 #include "BKE_appdir.h"
36 #include "BKE_blender.h"
37 #include "BKE_brush.h"
38 #include "BKE_cachefile.h"
39 #include "BKE_callbacks.h"
40 #include "BKE_context.h"
41 #include "BKE_global.h"
42 #include "BKE_gpencil_modifier.h"
43 #include "BKE_idtype.h"
44 #include "BKE_image.h"
45 #include "BKE_main.h"
46 #include "BKE_material.h"
47 #include "BKE_modifier.h"
48 #include "BKE_node.h"
49 #include "BKE_particle.h"
50 #include "BKE_shader_fx.h"
51 #include "BKE_sound.h"
52 #include "BKE_vfont.h"
53 #include "BKE_volume.h"
54 
55 #include "DEG_depsgraph.h"
56 
57 #include "IMB_imbuf.h" /* For #IMB_init. */
58 
59 #include "RE_engine.h"
60 #include "RE_texture.h"
61 
62 #include "ED_datafiles.h"
63 
64 #include "WM_api.h"
65 #include "WM_toolsystem.h"
66 
67 #include "RNA_define.h"
68 
69 #ifdef WITH_FREESTYLE
70 # include "FRS_freestyle.h"
71 #endif
72 
73 #include <signal.h>
74 
75 #ifdef __FreeBSD__
76 # include <floatingpoint.h>
77 #endif
78 
79 #ifdef WITH_BINRELOC
80 # include "binreloc.h"
81 #endif
82 
83 #ifdef WITH_LIBMV
84 # include "libmv-capi.h"
85 #endif
86 
87 #ifdef WITH_CYCLES_LOGGING
88 # include "CCL_api.h"
89 #endif
90 
91 #ifdef WITH_SDL_DYNLOAD
92 # include "sdlew.h"
93 #endif
94 
95 #include "creator_intern.h" /* Own include. */
96 
97 /* -------------------------------------------------------------------- */
101 /* written to by 'creator_args.c' */
102 struct ApplicationState app_state = {
103  .signal =
104  {
105  .use_crash_handler = true,
106  .use_abort_handler = true,
107  },
108  .exit_code_on_error =
109  {
110  .python = 0,
111  },
112 };
113 
116 /* -------------------------------------------------------------------- */
122 static void callback_mem_error(const char *errorStr)
123 {
124  fputs(errorStr, stderr);
125  fflush(stderr);
126 }
127 
128 static void main_callback_setup(void)
129 {
130  /* Error output from the guarded allocation routines. */
132 }
133 
134 /* free data on early exit (if Python calls 'sys.exit()' while parsing args for eg). */
137 #ifdef WIN32
138  const char **argv;
139  int argv_num;
140 #endif
141 };
142 
143 static void callback_main_atexit(void *user_data)
144 {
145  struct CreatorAtExitData *app_init_data = user_data;
146 
147  if (app_init_data->ba) {
148  BLI_args_destroy(app_init_data->ba);
149  app_init_data->ba = NULL;
150  }
151 
152 #ifdef WIN32
153  if (app_init_data->argv) {
154  while (app_init_data->argv_num) {
155  free((void *)app_init_data->argv[--app_init_data->argv_num]);
156  }
157  free((void *)app_init_data->argv);
158  app_init_data->argv = NULL;
159  }
160 #endif
161 }
162 
163 static void callback_clg_fatal(void *fp)
164 {
166 }
167 
170 /* -------------------------------------------------------------------- */
177 #ifdef WITH_PYTHON_MODULE
178 
179 /* Called in `bpy_interface.c` when building as a Python module. */
180 int main_python_enter(int argc, const char **argv);
181 void main_python_exit(void);
182 
183 /* Rename the 'main' function, allowing Python initialization to call it. */
184 # define main main_python_enter
185 static void *evil_C = NULL;
186 
187 # ifdef __APPLE__
188 /* Environment is not available in macOS shared libraries. */
189 # include <crt_externs.h>
190 char **environ = NULL;
191 # endif /* __APPLE__ */
192 
193 #endif /* WITH_PYTHON_MODULE */
194 
197 /* -------------------------------------------------------------------- */
201 #if (defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG) && defined(WITH_GMP)) || \
202  defined(DOXYGEN)
203 # include "gmp.h"
204 # include "tbb/scalable_allocator.h"
205 
206 void *gmp_alloc(size_t size)
207 {
208  return scalable_malloc(size);
209 }
210 void *gmp_realloc(void *ptr, size_t old_size, size_t new_size)
211 {
212  return scalable_realloc(ptr, new_size);
213 }
214 
215 void gmp_free(void *ptr, size_t size)
216 {
217  scalable_free(ptr);
218 }
226 {
227  mp_set_memory_functions(gmp_alloc, gmp_realloc, gmp_free);
228 }
229 #endif
230 
233 /* -------------------------------------------------------------------- */
244 int main(int argc,
245 #ifdef WIN32
246  const char **UNUSED(argv_c)
247 #else
248  const char **argv
249 #endif
250 )
251 {
252  bContext *C;
253 
254 #ifndef WITH_PYTHON_MODULE
255  bArgs *ba;
256 #endif
257 
258 #ifdef WIN32
259  char **argv;
260  int argv_num;
261 #endif
262 
263  /* --- end declarations --- */
264 
265  /* Ensure we free data on early-exit. */
266  struct CreatorAtExitData app_init_data = {NULL};
268 
269  /* Un-buffered `stdout` makes `stdout` and `stderr` better synchronized, and helps
270  * when stepping through code in a debugger (prints are immediately
271  * visible). However disabling buffering causes lock contention on windows
272  * see T76767 for details, since this is a debugging aid, we do not enable
273  * the un-buffered behavior for release builds. */
274 #ifndef NDEBUG
275  setvbuf(stdout, NULL, _IONBF, 0);
276 #endif
277 
278 #ifdef WIN32
279  /* We delay loading of OPENMP so we can set the policy here. */
280 # if defined(_MSC_VER)
281  _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
282 # endif
283 
284  /* Win32 Unicode Arguments. */
285  /* NOTE: cannot use `guardedalloc` allocation here, as it's not yet initialized
286  * (it depends on the arguments passed in, which is what we're getting here!)
287  */
288  {
289  wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
290  argv = malloc(argc * sizeof(char *));
291  for (argv_num = 0; argv_num < argc; argv_num++) {
292  argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
293  }
294  LocalFree(argv_16);
295 
296  /* free on early-exit */
297  app_init_data.argv = argv;
298  app_init_data.argv_num = argv_num;
299  }
300 #endif /* WIN32 */
301 
302  /* NOTE: Special exception for guarded allocator type switch:
303  * we need to perform switch from lock-free to fully
304  * guarded allocator before any allocation happened.
305  */
306  {
307  int i;
308  for (i = 0; i < argc; i++) {
309  if (STR_ELEM(argv[i], "-d", "--debug", "--debug-memory", "--debug-all")) {
310  printf("Switching to fully guarded memory allocator.\n");
312  break;
313  }
314  if (STREQ(argv[i], "--")) {
315  break;
316  }
317  }
319  }
320 
321 #ifdef BUILD_DATE
322  {
323  time_t temp_time = build_commit_timestamp;
324  struct tm *tm = gmtime(&temp_time);
325  if (LIKELY(tm)) {
326  strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
327  strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
328  }
329  else {
330  const char *unknown = "date-unknown";
333  }
334  }
335 #endif
336 
337 #ifdef WITH_SDL_DYNLOAD
338  sdlewInit();
339 #endif
340 
341  /* Initialize logging. */
342  CLG_init();
344 
345  C = CTX_create();
346 
347 #ifdef WITH_PYTHON_MODULE
348 # ifdef __APPLE__
349  environ = *_NSGetEnviron();
350 # endif
351 
352 # undef main
353  evil_C = C;
354 #endif
355 
356 #ifdef WITH_BINRELOC
357  br_init(NULL);
358 #endif
359 
360 #ifdef WITH_LIBMV
361  libmv_initLogging(argv[0]);
362 #elif defined(WITH_CYCLES_LOGGING)
363  CCL_init_logging(argv[0]);
364 #endif
365 
366 #if defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG) && defined(WITH_GMP)
368 #endif
369 
371 
372 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE) && !defined(WITH_HEADLESS)
373  /* Patch to ignore argument finder gives us (PID?) */
374  if (argc == 2 && STRPREFIX(argv[1], "-psn_")) {
375  extern int GHOST_HACK_getFirstFile(char buf[]);
376  static char firstfilebuf[512];
377 
378  argc = 1;
379 
380  if (GHOST_HACK_getFirstFile(firstfilebuf)) {
381  argc = 2;
382  argv[1] = firstfilebuf;
383  }
384  }
385 #endif
386 
387 #ifdef __FreeBSD__
388  fpsetmask(0);
389 #endif
390 
391  /* Initialize path to executable. */
393 
395 
397 
398  BKE_blender_globals_init(); /* blender.c */
399 
400  BKE_idtype_init();
407 
410 
412 
413  /* First test for background-mode (#Global.background) */
414 #ifndef WITH_PYTHON_MODULE
415  ba = BLI_args_create(argc, (const char **)argv); /* skip binary path */
416 
417  /* Ensure we free on early exit. */
418  app_init_data.ba = ba;
419 
420  main_args_setup(C, ba);
421 
422  /* Begin argument parsing, ignore leaks so arguments that call #exit
423  * (such as '--version' & '--help') don't report leaks. */
425 
426  /* Parse environment handling arguments. */
428 
429 #else
430  /* Using preferences or user startup makes no sense for #WITH_PYTHON_MODULE. */
431  G.factory_startup = true;
432 #endif
433 
434  /* After parsing #ARG_PASS_ENVIRONMENT such as `--env-*`,
435  * since they impact `BKE_appdir` behavior. */
436  BKE_appdir_init();
437 
438  /* After parsing number of threads argument. */
440 
441  /* Initialize sub-systems that use `BKE_appdir.h`. */
442  IMB_init();
443 
444 #ifndef WITH_PYTHON_MODULE
445  /* First test for background-mode (#Global.background) */
447 
449 #endif
450 
451 #ifdef WITH_FFMPEG
452  /* Keep after #ARG_PASS_SETTINGS since debug flags are checked. */
453  IMB_ffmpeg_init();
454 #endif
455 
456  /* After #ARG_PASS_SETTINGS arguments, this is so #WM_main_playanim skips #RNA_init. */
457  RNA_init();
458 
459  RE_engines_init();
462  /* End second initialization. */
463 
464 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
465  /* Python module mode ALWAYS runs in background-mode (for now). */
466  G.background = true;
467 #else
468  if (G.background) {
470  }
471 #endif
472 
473  /* Background render uses this font too. */
475 
476  /* Initialize FFMPEG if built in, also needed for background-mode if videos are
477  * rendered via FFMPEG. */
479 
481 
482 #ifndef WITH_PYTHON_MODULE
483  if (G.background == 0) {
485  }
487 #endif
488 
489  WM_init(C, argc, (const char **)argv);
490 
491  /* Need to be after WM init so that userpref are loaded. */
493 
494 #ifndef WITH_PYTHON
495  printf(
496  "\n* WARNING * - Blender compiled without Python!\n"
497  "this is not intended for typical usage\n\n");
498 #endif
499 
500  CTX_py_init_set(C, true);
502 
503 #ifdef WITH_FREESTYLE
504  /* Initialize Freestyle. */
505  FRS_init();
507 #endif
508 
509  /* OK we are ready for it */
510 #ifndef WITH_PYTHON_MODULE
511  /* Handles #ARG_PASS_FINAL. */
512  main_args_setup_post(C, ba);
513 #endif
514 
515  /* Explicitly free data allocated for argument parsing:
516  * - 'ba'
517  * - 'argv' on WIN32.
518  */
519  callback_main_atexit(&app_init_data);
521 
522  /* End argument parsing, allow memory leaks to be printed. */
524 
525  /* Paranoid, avoid accidental re-use. */
526 #ifndef WITH_PYTHON_MODULE
527  ba = NULL;
528  (void)ba;
529 #endif
530 
531 #ifdef WIN32
532  argv = NULL;
533  (void)argv;
534 #endif
535 
536 #ifndef WITH_PYTHON_MODULE
537  if (G.background) {
538  /* Using window-manager API in background-mode is a bit odd, but works fine. */
539  WM_exit(C);
540  }
541  else {
542  /* When no file is loaded, show the splash screen. */
543  const char *blendfile_path = BKE_main_blendfile_path_from_global();
544  if (blendfile_path[0] == '\0') {
545  WM_init_splash(C);
546  }
547  WM_main(C);
548  }
549 #endif /* WITH_PYTHON_MODULE */
550 
551  return 0;
552 } /* End of `int main(...)` function. */
553 
554 #ifdef WITH_PYTHON_MODULE
555 void main_python_exit(void)
556 {
557  WM_exit_ex((bContext *)evil_C, true);
558  evil_C = NULL;
559 }
560 #endif
561 
void BKE_appdir_init(void)
Definition: appdir.c:88
void BKE_appdir_program_path_init(const char *argv0)
Definition: appdir.c:861
Blender util stuff.
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition: blender.c:396
void BKE_blender_atexit_unregister(void(*func)(void *user_data), const void *user_data)
Definition: blender.c:405
void BKE_blender_globals_init(void)
Definition: blender.c:161
void BKE_brush_system_init(void)
Definition: brush.cc:427
void BKE_cachefiles_init(void)
Definition: cachefile.c:164
void BKE_callback_global_init(void)
Definition: callbacks.c:100
bContext * CTX_create(void)
Definition: context.c:102
void CTX_py_init_set(bContext *C, bool value)
Definition: context.c:237
void BKE_gpencil_modifier_init(void)
void BKE_idtype_init(void)
Definition: idtype.c:106
const char * BKE_main_blendfile_path_from_global(void)
Definition: main.c:562
General operations, lookup, etc. for materials.
void BKE_materials_init(void)
Definition: material.c:2078
void BKE_modifier_init(void)
void BKE_node_system_init(void)
Definition: node.cc:4930
void BKE_particle_init_rng(void)
Definition: particle.c:513
void BKE_shaderfx_init(void)
Definition: shader_fx.c:56
void BKE_sound_init_once(void)
void BKE_vfont_builtin_register(const void *mem, int size)
Definition: vfont.c:228
Volume data-block.
void BKE_volumes_init(void)
Definition: volume.cc:500
A general argument parsing module.
void BLI_args_parse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void *data)
Definition: BLI_args.c:273
void BLI_args_destroy(struct bArgs *ba)
Definition: BLI_args.c:114
struct bArgs * BLI_args_create(int argc, const char **argv)
Definition: BLI_args.c:99
void BLI_kdtree_nd_() free(KDTree *tree)
Definition: kdtree_impl.h:102
#define STR_ELEM(...)
Definition: BLI_string.h:539
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
void BLI_system_backtrace(FILE *fp)
Definition: system.c:62
void BLI_task_scheduler_init(void)
void BLI_threadapi_init(void)
Definition: threads.cc:125
#define STRPREFIX(a, b)
#define UNUSED(x)
#define STREQ(a, b)
#define LIKELY(x)
void CCL_init_logging(const char *argv0)
Definition: logging.cpp:7
void CLG_fatal_fn_set(void(*fatal_fn)(void *file_handle))
Definition: clog.c:728
void CLG_init(void)
Definition: clog.c:696
void DEG_register_node_types(void)
blenloader genfile private function prototypes
void DNA_sdna_current_init(void)
Definition: dna_genfile.c:561
const char datatoc_bfont_pfb[]
int datatoc_bfont_pfb_size
void FRS_set_context(struct bContext *C)
void FRS_init(void)
int GHOST_HACK_getFirstFile(char buf[FIRSTFILEBUFLG])
void IMB_ffmpeg_init(void)
void IMB_init(void)
Definition: module.c:16
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:25
char build_commit_date[]
Definition: buildinfo.c:33
char build_commit_time[]
Definition: buildinfo.c:34
ulong build_commit_timestamp
Definition: buildinfo.c:32
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static void callback_main_atexit(void *user_data)
Definition: creator.c:143
int main(int argc, const char **argv)
Definition: creator.c:244
void * gmp_realloc(void *ptr, size_t old_size, size_t new_size)
Definition: creator.c:210
struct ApplicationState app_state
Definition: creator.c:102
void gmp_free(void *ptr, size_t size)
Definition: creator.c:215
void gmp_blender_init_allocator()
Definition: creator.c:225
static void main_callback_setup(void)
Definition: creator.c:128
static void callback_mem_error(const char *errorStr)
Definition: creator.c:122
void * gmp_alloc(size_t size)
Definition: creator.c:206
static void callback_clg_fatal(void *fp)
Definition: creator.c:163
void main_args_setup(bContext *C, bArgs *ba)
void main_args_setup_post(bContext *C, bArgs *ba)
void main_signal_setup_background(void)
@ ARG_PASS_ENVIRONMENT
@ ARG_PASS_SETTINGS_FORCE
@ ARG_PASS_SETTINGS_GUI
@ ARG_PASS_SETTINGS
void main_signal_setup(void)
void * user_data
SyclQueue void void size_t num_bytes void
void RE_engines_init(void)
Definition: engine.c:59
void RE_engines_init_experimental()
Definition: engine.c:64
void MEM_use_memleak_detection(bool enabled)
void MEM_init_memleak_detection()
void libmv_initLogging(const char *argv0)
Definition: logging.cc:20
void MEM_use_guarded_allocator(void)
Definition: mallocn.c:134
void(* MEM_set_error_callback)(void(*func)(const char *))
Definition: mallocn.c:42
#define G(x, y, z)
void RNA_init(void)
Definition: rna_access.c:65
struct ApplicationState::@1221 signal
Definition: BLI_args.c:45
void RE_texture_rng_init(void)
char * alloc_utf_8_from_16(const wchar_t *in16, size_t add)
Definition: utfconv.c:279
void WM_main(bContext *C)
Definition: wm.c:622
void WM_keyconfig_init(bContext *C)
Definition: wm.c:433
PointerRNA * ptr
Definition: wm_files.c:3480
void WM_init_splash(bContext *C)
Definition: wm_init_exit.c:366
void WM_exit_ex(bContext *C, const bool do_python)
Definition: wm_init_exit.c:434
void WM_exit(bContext *C)
Main exit function to close Blender ordinarily.
Definition: wm_init_exit.c:646
void WM_init(bContext *C, int argc, const char **argv)
Definition: wm_init_exit.c:212