Blender V4.3
creator.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <cstdlib>
10#include <cstring>
11
12#ifdef WIN32
13# include "utfconv.hh"
14# include <windows.h>
15# ifdef WITH_CPU_CHECK
16# pragma comment(linker, "/include:cpu_check_win32")
17# endif
18#endif
19
20#if defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG)
21# pragma comment(lib, "tbbmalloc_proxy.lib")
22# pragma comment(linker, "/include:__TBB_malloc_proxy")
23#endif
24
25#include "MEM_guardedalloc.h"
26
27#include "CLG_log.h"
28
29#include "DNA_genfile.h"
30
31#include "BLI_string.h"
32#include "BLI_system.h"
33#include "BLI_task.h"
34#include "BLI_threads.h"
35#include "BLI_utildefines.h"
36
37/* Mostly initialization functions. */
38#include "BKE_appdir.hh"
39#include "BKE_blender.hh"
40#include "BKE_brush.hh"
41#include "BKE_cachefile.hh"
42#include "BKE_callbacks.hh"
43#include "BKE_context.hh"
44#include "BKE_cpp_types.hh"
45#include "BKE_global.hh"
46#include "BKE_idtype.hh"
47#include "BKE_material.h"
48#include "BKE_modifier.hh"
49#include "BKE_node.hh"
50#include "BKE_particle.h"
51#include "BKE_shader_fx.h"
52#include "BKE_sound.h"
53#include "BKE_vfont.hh"
54#include "BKE_volume.hh"
55
56#ifndef WITH_PYTHON_MODULE
57# include "BLI_args.h"
58#endif
59
60#include "DEG_depsgraph.hh"
61
62#include "IMB_imbuf.hh" /* For #IMB_init. */
63
64#include "RE_engine.h"
65#include "RE_texture.h"
66
67#include "ED_datafiles.h"
68
69#include "WM_api.hh"
70
71#include "RNA_define.hh"
72
74
75#ifdef WITH_FREESTYLE
76# include "FRS_freestyle.h"
77#endif
78
79#include <csignal>
80
81#ifdef __FreeBSD__
82# include <floatingpoint.h>
83#endif
84
85#ifdef WITH_BINRELOC
86# include "binreloc.h"
87#endif
88
89#ifdef WITH_LIBMV
90# include "libmv-capi.h"
91#endif
92
93#ifdef WITH_CYCLES_LOGGING
94# include "CCL_api.h"
95#endif
96
97#include "creator_intern.h" /* Own include. */
98
99/* -------------------------------------------------------------------- */
103/* When building as a Python module, don't use special argument handling
104 * so the module loading logic can control the `argv` & `argc`. */
105#if defined(WIN32) && !defined(WITH_PYTHON_MODULE)
106# define USE_WIN32_UNICODE_ARGS
107#endif
108
111/* -------------------------------------------------------------------- */
115/* Written to by `creator_args.cc`. */
124
127/* -------------------------------------------------------------------- */
133static void callback_mem_error(const char *errorStr)
134{
135 fputs(errorStr, stderr);
136 fflush(stderr);
137}
138
140{
141 /* Error output from the guarded allocation routines. */
143}
144
147#ifndef WITH_PYTHON_MODULE
149#endif
150
151#ifdef USE_WIN32_UNICODE_ARGS
152 char **argv;
153 int argv_num;
154#endif
155
156#if defined(WITH_PYTHON_MODULE) && !defined(USE_WIN32_UNICODE_ARGS)
157 void *_empty; /* Prevent empty struct error with MSVC. */
158#endif
159};
160
161static void callback_main_atexit(void *user_data)
162{
163 CreatorAtExitData *app_init_data = static_cast<CreatorAtExitData *>(user_data);
164
165#ifndef WITH_PYTHON_MODULE
166 if (app_init_data->ba) {
167 BLI_args_destroy(app_init_data->ba);
168 app_init_data->ba = nullptr;
169 }
170#else
171 UNUSED_VARS(app_init_data); /* May be unused. */
172#endif
173
174#ifdef USE_WIN32_UNICODE_ARGS
175 if (app_init_data->argv) {
176 while (app_init_data->argv_num) {
177 free((void *)app_init_data->argv[--app_init_data->argv_num]);
178 }
179 free((void *)app_init_data->argv);
180 app_init_data->argv = nullptr;
181 }
182#else
183 UNUSED_VARS(app_init_data); /* May be unused. */
184#endif
185}
186
187static void callback_clg_fatal(void *fp)
188{
189 BLI_system_backtrace(static_cast<FILE *>(fp));
190}
191
194/* -------------------------------------------------------------------- */
201#ifdef WITH_PYTHON_MODULE
202
203/* Called in `bpy_interface.cc` when building as a Python module. */
204int main_python_enter(int argc, const char **argv);
205void main_python_exit();
206
207/* Rename the `main(..)` function, allowing Python initialization to call it. */
208# define main main_python_enter
209static void *evil_C = nullptr;
210
211# ifdef __APPLE__
212/* Environment is not available in macOS shared libraries. */
213# include <crt_externs.h>
214char **environ = nullptr;
215# endif /* __APPLE__ */
216
217#endif /* WITH_PYTHON_MODULE */
218
221/* -------------------------------------------------------------------- */
225#if (defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG) && defined(WITH_GMP)) || \
226 defined(DOXYGEN)
227# include "gmp.h"
228# include "tbb/scalable_allocator.h"
229
230void *gmp_alloc(size_t size)
231{
232 return scalable_malloc(size);
233}
234void *gmp_realloc(void *ptr, size_t /*old_size*/, size_t new_size)
235{
236 return scalable_realloc(ptr, new_size);
237}
238
239void gmp_free(void *ptr, size_t /*size*/)
240{
241 scalable_free(ptr);
242}
250{
251 mp_set_memory_functions(gmp_alloc, gmp_realloc, gmp_free);
252}
253#endif
254
257/* -------------------------------------------------------------------- */
261#if defined(__APPLE__)
262extern "C" int GHOST_HACK_getFirstFile(char buf[]);
263#endif
264
272int main(int argc,
273#ifdef USE_WIN32_UNICODE_ARGS
274 const char ** /*argv_c*/
275#else
276 const char **argv
277#endif
278)
279{
280 bContext *C;
281#ifndef WITH_PYTHON_MODULE
282 bArgs *ba;
283#endif
284
285#ifdef USE_WIN32_UNICODE_ARGS
286 char **argv;
287 int argv_num;
288#endif
289
290 /* Ensure we free data on early-exit. */
291 CreatorAtExitData app_init_data = {nullptr};
293
294/* Un-buffered `stdout` makes `stdout` and `stderr` better synchronized, and helps
295 * when stepping through code in a debugger (prints are immediately
296 * visible). However disabling buffering causes lock contention on windows
297 * see #76767 for details, since this is a debugging aid, we do not enable
298 * the un-buffered behavior for release builds. */
299#ifndef NDEBUG
300 setvbuf(stdout, nullptr, _IONBF, 0);
301#endif
302
303#ifdef WIN32
304/* We delay loading of OPENMP so we can set the policy here. */
305# if defined(_MSC_VER)
306 _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
307# endif
308
309# ifdef USE_WIN32_UNICODE_ARGS
310 /* Win32 Unicode Arguments. */
311 {
312 /* NOTE: Can't use `guardedalloc` allocation here, as it's not yet initialized
313 * (it depends on the arguments passed in, which is what we're getting here!). */
314 wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
315 argv = static_cast<char **>(malloc(argc * sizeof(char *)));
316 for (argv_num = 0; argv_num < argc; argv_num++) {
317 argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
318 }
319 LocalFree(argv_16);
320
321 /* Free on early-exit. */
322 app_init_data.argv = argv;
323 app_init_data.argv_num = argv_num;
324 }
325# endif /* USE_WIN32_UNICODE_ARGS */
326#endif /* WIN32 */
327
328#if defined(WITH_OPENGL_BACKEND) && BLI_SUBPROCESS_SUPPORT
329 if (STREQ(argv[0], "--compilation-subprocess")) {
330 BLI_assert(argc == 2);
331 GPU_compilation_subprocess_run(argv[1]);
332 return 0;
333 }
334#endif
335
336 /* NOTE: Special exception for guarded allocator type switch:
337 * we need to perform switch from lock-free to fully
338 * guarded allocator before any allocation happened.
339 */
340 {
341 int i;
342 for (i = 0; i < argc; i++) {
343 if (STR_ELEM(argv[i], "-d", "--debug", "--debug-memory", "--debug-all")) {
344 printf("Switching to fully guarded memory allocator.\n");
346 break;
347 }
348 if (STR_ELEM(argv[i], "--", "-c", "--command")) {
349 break;
350 }
351 }
353 }
354
355#ifdef BUILD_DATE
356 {
357 const time_t temp_time = build_commit_timestamp;
358 const tm *tm = gmtime(&temp_time);
359 if (LIKELY(tm)) {
360 strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
361 strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
362 }
363 else {
364 const char *unknown = "date-unknown";
365 STRNCPY(build_commit_date, unknown);
366 STRNCPY(build_commit_time, unknown);
367 }
368 }
369#endif
370
371 /* Initialize logging. */
372 CLG_init();
374
375 C = CTX_create();
376
377#ifdef WITH_PYTHON_MODULE
378# ifdef __APPLE__
379 environ = *_NSGetEnviron();
380# endif
381
382# undef main
383 evil_C = C;
384#endif
385
386#ifdef WITH_BINRELOC
387 br_init(nullptr);
388#endif
389
390#ifdef WITH_LIBMV
391 libmv_initLogging(argv[0]);
392#elif defined(WITH_CYCLES_LOGGING)
393 CCL_init_logging(argv[0]);
394#endif
395
396#if defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG) && defined(WITH_GMP)
398#endif
399
401
402#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE) && !defined(WITH_HEADLESS)
403 /* Patch to ignore argument finder gives us (PID?). */
404 if (argc == 2 && STRPREFIX(argv[1], "-psn_")) {
405 static char firstfilebuf[512];
406
407 argc = 1;
408
409 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
410 argc = 2;
411 argv[1] = firstfilebuf;
412 }
413 }
414#endif
415
416#ifdef __FreeBSD__
417 fpsetmask(0);
418#endif
419
420 /* Initialize path to executable. */
422
424
426
427 BKE_blender_globals_init(); /* `blender.cc` */
428
436
439
441
442/* First test for background-mode (#Global.background). */
443#ifndef WITH_PYTHON_MODULE
444 ba = BLI_args_create(argc, (const char **)argv); /* Skip binary path. */
445
446 /* Ensure we free on early exit. */
447 app_init_data.ba = ba;
448
449 main_args_setup(C, ba, false);
450
451 /* Begin argument parsing, ignore leaks so arguments that call #exit
452 * (such as `--version` & `--help`) don't report leaks. */
454
455 /* Parse environment handling arguments. */
456 BLI_args_parse(ba, ARG_PASS_ENVIRONMENT, nullptr, nullptr);
457
458#else
459 /* Using preferences or user startup makes no sense for #WITH_PYTHON_MODULE. */
460 G.factory_startup = true;
461#endif
462
463 /* After parsing #ARG_PASS_ENVIRONMENT such as `--env-*`,
464 * since they impact `BKE_appdir` behavior. */
466
467 /* After parsing number of threads argument. */
469
470#ifndef WITH_PYTHON_MODULE
471 /* The settings pass includes:
472 * - Background-mode assignment (#Global.background), checked by other subsystems
473 * which may be skipped in background mode.
474 * - The animation player may be launched which takes over argument passing,
475 * initializes the sub-systems it needs which have not yet been started.
476 * The animation player will call `exit(..)` too, so code after this call
477 * never runs when it's invoked.
478 * - All the `--debug-*` flags.
479 */
480 BLI_args_parse(ba, ARG_PASS_SETTINGS, nullptr, nullptr);
481
483#endif
484
485 /* Must be initialized after #BKE_appdir_init to account for color-management paths. */
486 IMB_init();
487#ifdef WITH_FFMPEG
488 /* Keep after #ARG_PASS_SETTINGS since debug flags are checked. */
490#endif
491
492 /* After #ARG_PASS_SETTINGS arguments, this is so #WM_main_playanim skips #RNA_init. */
493 RNA_init();
494
498 /* End second initialization. */
499
500#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
501 /* Python module mode ALWAYS runs in background-mode (for now). */
502 G.background = true;
503 /* Manually using `--background` also forces the audio device. */
505#else
506 if (G.background) {
508 }
509#endif
510
511 /* Background render uses this font too. */
513
514 /* Initialize FFMPEG if built in, also needed for background-mode if videos are
515 * rendered via FFMPEG. */
517
519
520#ifndef WITH_PYTHON_MODULE
521 if (G.background == 0) {
522 BLI_args_parse(ba, ARG_PASS_SETTINGS_GUI, nullptr, nullptr);
523 }
524 BLI_args_parse(ba, ARG_PASS_SETTINGS_FORCE, nullptr, nullptr);
525#endif
526
527 WM_init(C, argc, (const char **)argv);
528
529#ifndef WITH_PYTHON
530 printf(
531 "\n* WARNING * - Blender compiled without Python!\n"
532 "this is not intended for typical usage\n\n");
533#endif
534
535#ifdef WITH_FREESTYLE
536 /* Initialize Freestyle. */
537 FRS_init();
539#endif
540
541/* OK we are ready for it. */
542#ifndef WITH_PYTHON_MODULE
543 /* Handles #ARG_PASS_FINAL. */
545#endif
546
547 /* Explicitly free data allocated for argument parsing:
548 * - `ba`
549 * - `argv` on WIN32.
550 */
551 callback_main_atexit(&app_init_data);
553
554 /* End argument parsing, allow memory leaks to be printed. */
556
557/* Paranoid, avoid accidental re-use. */
558#ifndef WITH_PYTHON_MODULE
559 ba = nullptr;
560 (void)ba;
561#endif
562
563#ifdef USE_WIN32_UNICODE_ARGS
564 argv = nullptr;
565 (void)argv;
566#endif
567
568#ifndef WITH_PYTHON_MODULE
569 if (G.background) {
570 int exit_code;
571 if (app_state.main_arg_deferred != nullptr) {
572 exit_code = main_arg_deferred_handle();
574 }
575 else {
576 exit_code = G.is_break ? EXIT_FAILURE : EXIT_SUCCESS;
577 }
578 /* Using window-manager API in background-mode is a bit odd, but works fine. */
579 WM_exit(C, exit_code);
580 }
581 else {
582 /* Not supported, although it could be made to work if needed. */
584
585 /* Shows the splash as needed. */
587
588 WM_main(C);
589 }
590 /* Neither #WM_exit, #WM_main return, this quiets CLANG's `unreachable-code-return` warning. */
592
593#endif /* !WITH_PYTHON_MODULE */
594
595 return 0;
596
597} /* End of `int main(...)` function. */
598
599#ifdef WITH_PYTHON_MODULE
600void main_python_exit()
601{
602 WM_exit_ex((bContext *)evil_C, true, false);
603 evil_C = nullptr;
604}
605#endif
606
void BKE_appdir_init()
Definition appdir.cc:93
void BKE_appdir_program_path_init(const char *argv0) ATTR_NONNULL(1)
Definition appdir.cc:917
Blender util stuff.
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition blender.cc:466
void BKE_blender_atexit_unregister(void(*func)(void *user_data), const void *user_data)
Definition blender.cc:475
void BKE_blender_globals_init()
Definition blender.cc:186
void BKE_brush_system_init()
Definition brush.cc:470
void BKE_cachefiles_init()
Definition cachefile.cc:156
void BKE_callback_global_init()
Definition callbacks.cc:103
bContext * CTX_create()
void BKE_cpp_types_init()
void BKE_idtype_init()
Definition idtype.cc:127
General operations, lookup, etc. for materials.
void BKE_materials_init(void)
void BKE_modifier_init()
void BKE_particle_init_rng(void)
Definition particle.cc:415
void BKE_shaderfx_init(void)
Definition shader_fx.cc:48
void BKE_sound_init_once(void)
void BKE_sound_force_device(const char *device)
void BKE_vfont_builtin_register(const void *mem, int size)
Definition vfont.cc:237
Volume data-block.
void BKE_volumes_init()
A general argument parsing module.
void BLI_args_destroy(struct bArgs *ba)
Definition BLI_args.c:127
struct bArgs * BLI_args_create(int argc, const char **argv)
Definition BLI_args.c:110
void BLI_args_parse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void *default_data)
Definition BLI_args.c:300
#define BLI_assert_unreachable()
Definition BLI_assert.h:97
#define BLI_assert(a)
Definition BLI_assert.h:50
void BLI_kdtree_nd_ free(KDTree *tree)
#define STR_ELEM(...)
Definition BLI_string.h:653
#define STRNCPY(dst, src)
Definition BLI_string.h:593
void BLI_system_backtrace(FILE *fp)
Definition system.c:63
void BLI_task_scheduler_init(void)
void BLI_threadapi_init(void)
Definition threads.cc:114
#define STRPREFIX(a, b)
#define UNUSED_VARS(...)
#define STREQ(a, b)
#define LIKELY(x)
void CCL_init_logging(const char *argv0)
Definition logging.cpp:8
void CLG_fatal_fn_set(void(*fatal_fn)(void *file_handle))
Definition clog.c:731
void CLG_init(void)
Definition clog.c:699
void DEG_register_node_types()
blenloader genfile private function prototypes
void DNA_sdna_current_init(void)
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 IMB_init()
Definition module.cc:18
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
char build_commit_date[]
Definition bpy_app.cc:66
ulong build_commit_timestamp
Definition bpy_app.cc:65
char build_commit_time[]
Definition bpy_app.cc:67
static void callback_main_atexit(void *user_data)
Definition creator.cc:161
static void main_callback_setup()
Definition creator.cc:139
void * gmp_realloc(void *ptr, size_t, size_t new_size)
Definition creator.cc:234
void * gmp_alloc(size_t size)
Definition creator.cc:230
void gmp_free(void *ptr, size_t)
Definition creator.cc:239
void gmp_blender_init_allocator()
Definition creator.cc:249
ApplicationState app_state
Definition creator.cc:116
static void callback_mem_error(const char *errorStr)
Definition creator.cc:133
static void callback_clg_fatal(void *fp)
Definition creator.cc:187
#define printf
void main_arg_deferred_free()
int main_args_handle_load_file(int, const char **argv, void *data)
int main_arg_deferred_handle()
void main_args_setup(bContext *C, bArgs *ba, bool all)
void main_signal_setup_background(void)
@ ARG_PASS_ENVIRONMENT
@ ARG_PASS_SETTINGS_FORCE
@ ARG_PASS_SETTINGS_GUI
@ ARG_PASS_FINAL
@ ARG_PASS_SETTINGS
void main_signal_setup(void)
void RE_engines_init()
void MEM_use_memleak_detection(bool enabled)
void MEM_init_memleak_detection()
void libmv_initLogging(const char *argv0)
Definition logging.cc:21
void(* MEM_set_error_callback)(void(*func)(const char *))
Definition mallocn.cc:59
void MEM_use_guarded_allocator()
Definition mallocn.cc:170
#define G(x, y, z)
int main()
void node_system_init()
Definition node.cc:4649
void RNA_init()
Definition rna_access.cc:73
struct ApplicationState::@1407 signal
struct BA_ArgCallback_Deferred * main_arg_deferred
unsigned char python
struct ApplicationState::@1408 exit_code_on_error
void RE_texture_rng_init()
char * alloc_utf_8_from_16(const wchar_t *in16, size_t add)
Definition utfconv.cc:280
void WM_main(bContext *C)
Definition wm.cc:628
PointerRNA * ptr
Definition wm_files.cc:4126
void WM_init_splash_on_startup(bContext *C)
void WM_exit(bContext *C, const int exit_code)
void WM_exit_ex(bContext *C, const bool do_python_exit, const bool do_user_exit_actions)
void WM_init(bContext *C, int argc, const char **argv)