Blender V5.0
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
8
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_endian_defines.h"
32#include "BLI_fftw.hh"
33#include "BLI_path_utils.hh"
34#include "BLI_string.h"
35#include "BLI_system.h"
36#include "BLI_task.h"
37#include "BLI_threads.h"
38#include "BLI_utildefines.h"
39
40/* Mostly initialization functions. */
41#include "BKE_appdir.hh"
42#include "BKE_blender.hh"
43#include "BKE_brush.hh"
44#include "BKE_callbacks.hh"
45#include "BKE_context.hh"
46#include "BKE_cpp_types.hh"
47#include "BKE_global.hh"
48#include "BKE_idtype.hh"
49#include "BKE_material.hh"
50#include "BKE_modifier.hh"
51#include "BKE_node.hh"
52#include "BKE_particle.h"
53#include "BKE_shader_fx.h"
54#include "BKE_sound.h"
55#include "BKE_vfont.hh"
56#include "BKE_volume.hh"
57
58#ifndef WITH_PYTHON_MODULE
59# include "BLI_args.h"
60#endif
61
62#include "DEG_depsgraph.hh"
63
64#include "IMB_imbuf.hh" /* For #IMB_init. */
65
66#include "MOV_util.hh"
67
68#include "RE_engine.h"
69#include "RE_texture.h"
70
71#include "ED_datafiles.h"
72
73#include "SEQ_modifier.hh"
74
75#include "WM_api.hh"
76
77#include "RNA_define.hh"
78
79#ifdef WITH_OPENGL_BACKEND
81#endif
82
83#ifdef WITH_FREESTYLE
84# include "FRS_freestyle.h"
85#endif
86
87#include <csignal>
88
89#ifdef __FreeBSD__
90# include <floatingpoint.h>
91#endif
92
93#ifdef WITH_BINRELOC
94# include "binreloc.h"
95#endif
96
97#ifdef WITH_LIBMV
98# include "libmv-capi.h"
99#endif
100
101#ifdef WITH_CYCLES
102# include "CCL_api.h"
103#endif
104
105#include "creator_intern.h" /* Own include. */
106
107BLI_STATIC_ASSERT(ENDIAN_ORDER == L_ENDIAN, "Blender only builds on little endian systems")
108
109/* -------------------------------------------------------------------- */
112
113/* When building as a Python module, don't use special argument handling
114 * so the module loading logic can control the `argv` & `argc`. */
115#if defined(WIN32) && !defined(WITH_PYTHON_MODULE)
116# define USE_WIN32_UNICODE_ARGS
117#endif
118
120
121/* -------------------------------------------------------------------- */
124
125/* Written to by `creator_args.cc`. */
128 app_state.signal.use_crash_handler = true;
129 app_state.signal.use_abort_handler = true;
130 app_state.exit_code_on_error.python = 0;
131 app_state.main_arg_deferred = nullptr;
132 return app_state;
133}();
134
136
137/* -------------------------------------------------------------------- */
142
143static void callback_mem_error(const char *errorStr)
144{
145 fputs(errorStr, stderr);
146 fflush(stderr);
147}
148
150{
151 /* Error output from the guarded allocation routines. */
153}
154
159
162#ifndef WITH_PYTHON_MODULE
164#endif
165
166#ifdef USE_WIN32_UNICODE_ARGS
167 char **argv;
168 int argv_num;
169#endif
170
176};
177
178static void callback_main_atexit(void *user_data)
179{
180 CreatorAtExitData *app_init_data = static_cast<CreatorAtExitData *>(user_data);
181
182#ifndef WITH_PYTHON_MODULE
183 if (app_init_data->ba) {
184 BLI_args_destroy(app_init_data->ba);
185 app_init_data->ba = nullptr;
186 }
187#endif
188
189#ifdef USE_WIN32_UNICODE_ARGS
190 if (app_init_data->argv) {
191 while (app_init_data->argv_num) {
192 free((void *)app_init_data->argv[--app_init_data->argv_num]);
193 }
194 free((void *)app_init_data->argv);
195 app_init_data->argv = nullptr;
196 }
197#endif
198
199 if (CreatorAtExitData_EarlyExit *early_exit = app_init_data->early_exit) {
200 CTX_free(early_exit->C);
201
203
206
208
209 CLG_exit();
210 }
211}
212
213static void callback_clg_fatal(void *fp)
214{
215 BLI_system_backtrace(static_cast<FILE *>(fp));
216}
217
219
220/* -------------------------------------------------------------------- */
226
227#ifdef WITH_PYTHON_MODULE
228
229/* Called in `bpy_interface.cc` when building as a Python module. */
230int main_python_enter(int argc, const char **argv);
231void main_python_exit();
232
233/* Rename the `main(..)` function, allowing Python initialization to call it. */
234# define main main_python_enter
235static void *evil_C = nullptr;
236
237# ifdef __APPLE__
238/* Environment is not available in macOS shared libraries. */
239# include <crt_externs.h>
240char **environ = nullptr;
241# endif /* __APPLE__ */
242
243#endif /* WITH_PYTHON_MODULE */
244
246
247/* -------------------------------------------------------------------- */
250
251#if (defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG) && defined(WITH_GMP)) || \
252 defined(DOXYGEN)
253# include "gmp.h"
254# include "tbb/scalable_allocator.h"
255
256void *gmp_alloc(size_t size)
257{
258 return scalable_malloc(size);
259}
260void *gmp_realloc(void *ptr, size_t /*old_size*/, size_t new_size)
261{
262 return scalable_realloc(ptr, new_size);
263}
264
265void gmp_free(void *ptr, size_t /*size*/)
266{
267 scalable_free(ptr);
268}
269
276{
277 mp_set_memory_functions(gmp_alloc, gmp_realloc, gmp_free);
278}
279#endif
280
282{
283 /* LD_PRELOAD may have been modified on startup for Blender. However
284 * we don't want it for other executables launched from Blender. */
285 const char *restore_ld_preload = BLI_getenv("BLENDER_RESTORE_LD_PRELOAD");
286 if (restore_ld_preload) {
287 BLI_setenv("LD_PRELOAD", restore_ld_preload);
288 }
289}
290
292
293/* -------------------------------------------------------------------- */
296
297#if defined(__APPLE__)
298extern "C" int GHOST_HACK_getFirstFile(char buf[]);
299#endif
300
308int main(int argc,
309#ifdef USE_WIN32_UNICODE_ARGS
310 const char ** /*argv_c*/
311#else
312 const char **argv
313#endif
314)
315{
316 bContext *C;
317#ifndef WITH_PYTHON_MODULE
318 bArgs *ba;
319#endif
320
321 /* Ensure we free data on early-exit. */
322 CreatorAtExitData app_init_data = {nullptr};
324
325 CreatorAtExitData_EarlyExit app_init_data_early_exit = {nullptr};
326 app_init_data.early_exit = &app_init_data_early_exit;
327
328/* Un-buffered `stdout` makes `stdout` and `stderr` better synchronized, and helps
329 * when stepping through code in a debugger (prints are immediately
330 * visible). However disabling buffering causes lock contention on windows
331 * see #76767 for details, since this is a debugging aid, we do not enable
332 * the un-buffered behavior for release builds. */
333#ifndef NDEBUG
334 setvbuf(stdout, nullptr, _IONBF, 0);
335#endif
336
338
339#ifdef WIN32
340# ifdef USE_WIN32_UNICODE_ARGS
341 /* Win32 Unicode Arguments. */
342 {
343 /* NOTE: Can't use `guardedalloc` allocation here, as it's not yet initialized
344 * (it depends on the arguments passed in, which is what we're getting here!). */
345 wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
346 app_init_data.argv = static_cast<char **>(malloc(argc * sizeof(char *)));
347 for (int i = 0; i < argc; i++) {
348 app_init_data.argv[i] = alloc_utf_8_from_16(argv_16[i], 0);
349 }
350 LocalFree(argv_16);
351
352 /* Free on early-exit. */
353 app_init_data.argv_num = argc;
354 }
355 const char **argv = const_cast<const char **>(app_init_data.argv);
356# endif /* USE_WIN32_UNICODE_ARGS */
357#endif /* WIN32 */
358
359#if defined(WITH_OPENGL_BACKEND) && BLI_SUBPROCESS_SUPPORT
360 if (STREQ(argv[0], "--compilation-subprocess")) {
361 BLI_assert(argc == 2);
362 GPU_compilation_subprocess_run(argv[1]);
363 return 0;
364 }
365#endif
366
367 /* NOTE: Special exception for guarded allocator type switch:
368 * we need to perform switch from lock-free to fully
369 * guarded allocator before any allocation happened.
370 */
371 {
372 int i;
373 for (i = 0; i < argc; i++) {
374 if (STR_ELEM(argv[i], "-d", "--debug", "--debug-memory", "--debug-all")) {
375 printf("Switching to fully guarded memory allocator.\n");
377 break;
378 }
379 if (STR_ELEM(argv[i], "--", "-c", "--command")) {
380 break;
381 }
382 }
384 }
385
386#ifdef BUILD_DATE
387 {
388 const time_t temp_time = build_commit_timestamp;
389 const tm *tm = gmtime(&temp_time);
390 if (LIKELY(tm)) {
391 strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
392 strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
393 }
394 else {
395 const char *unknown = "date-unknown";
396 STRNCPY(build_commit_date, unknown);
397 STRNCPY(build_commit_time, unknown);
398 }
399 }
400#endif
401
402 /* Initialize logging. */
403 CLG_init();
409
410 C = CTX_create();
411
412 app_init_data_early_exit.C = C;
413
414#ifdef WITH_PYTHON_MODULE
415# ifdef __APPLE__
416 environ = *_NSGetEnviron();
417# endif
418
419# undef main
420 evil_C = C;
421#endif
422
423#ifdef WITH_BINRELOC
424 br_init(nullptr);
425#endif
426
427#ifdef WITH_LIBMV
428 libmv_initLogging(argv[0]);
429#endif
430
431#if defined(WITH_TBB_MALLOC) && defined(_MSC_VER) && defined(NDEBUG) && defined(WITH_GMP)
433#endif
434
436
437#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE) && !defined(WITH_HEADLESS)
438 /* Patch to ignore argument finder gives us (PID?). */
439 if (argc == 2 && STRPREFIX(argv[1], "-psn_")) {
440 static char firstfilebuf[512];
441
442 argc = 1;
443
444 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
445 argc = 2;
446 argv[1] = firstfilebuf;
447 }
448 }
449#endif
450
451#ifdef __FreeBSD__
452 fpsetmask(0);
453#endif
454
455 /* Initialize path to executable. */
457
459
461
462 BKE_blender_globals_init(); /* `blender.cc` */
463
471
473
474/* First test for background-mode (#Global.background). */
475#ifndef WITH_PYTHON_MODULE
476 ba = BLI_args_create(argc, argv); /* Skip binary path. */
477
478 /* Ensure we free on early exit. */
479 app_init_data.ba = ba;
480
481 main_args_setup(C, ba, false);
482
483 /* Parse environment handling arguments. */
484 BLI_args_parse(ba, ARG_PASS_ENVIRONMENT, nullptr, nullptr);
485
486#else
487 /* Using preferences or user startup makes no sense for #WITH_PYTHON_MODULE. */
488 G.factory_startup = true;
489#endif
490
491 /* After parsing #ARG_PASS_ENVIRONMENT such as `--env-*`,
492 * since they impact `BKE_appdir` behavior. */
494
495 /* After parsing number of threads argument. */
497
498 /* Initialize FFTW threading support. */
500
501#ifndef WITH_PYTHON_MODULE
502 /* The settings pass includes:
503 * - Background-mode assignment (#Global.background), checked by other subsystems
504 * which may be skipped in background mode.
505 * - The animation player may be launched which takes over argument passing,
506 * initializes the sub-systems it needs which have not yet been started.
507 * The animation player will call `exit(..)` too, so code after this call
508 * never runs when it's invoked.
509 * - All the `--debug-*` flags.
510 */
511 BLI_args_parse(ba, ARG_PASS_SETTINGS, nullptr, nullptr);
512
514#endif
515
516 /* Continue with regular initialization, no need to use "early" exit. */
517 app_init_data.early_exit = nullptr;
518
519#ifdef WITH_CYCLES
520 CCL_log_init();
521#endif
522
523 /* Must be initialized after #BKE_appdir_init to account for color-management paths. */
524 IMB_init();
525 /* Keep after #ARG_PASS_SETTINGS since debug flags are checked. */
526 MOV_init();
527
528 /* After #ARG_PASS_SETTINGS arguments, this is so #WM_main_playanim skips #RNA_init. */
529 RNA_init();
530
534
537 /* End second initialization. */
538
539#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
540 /* Python module mode ALWAYS runs in background-mode (for now). */
541 G.background = true;
542 /* Manually using `--background` also forces the audio device. */
544#else
545 if (G.background) {
547 }
548#endif
549
550 /* Background render uses this font too. */
552
553 /* Initialize FFMPEG if built in, also needed for background-mode if videos are
554 * rendered via FFMPEG. */
556
558
559#ifndef WITH_PYTHON_MODULE
560 if (G.background == 0) {
561 BLI_args_parse(ba, ARG_PASS_SETTINGS_GUI, nullptr, nullptr);
562 }
563 BLI_args_parse(ba, ARG_PASS_SETTINGS_FORCE, nullptr, nullptr);
564#endif
565
566 WM_init(C, argc, argv);
567
568#ifndef WITH_PYTHON
569 printf(
570 "\n* WARNING * - Blender compiled without Python!\n"
571 "this is not intended for typical usage\n\n");
572#endif
573
574#ifdef WITH_FREESTYLE
575 /* Initialize Freestyle. */
576 FRS_init();
578#endif
579
580/* OK we are ready for it. */
581#ifndef WITH_PYTHON_MODULE
582 /* Handles #ARG_PASS_FINAL. */
584#endif
585
586 /* Explicitly free data allocated for argument parsing:
587 * - `ba`
588 * - `argv` on WIN32.
589 */
590 callback_main_atexit(&app_init_data);
592
593/* Paranoid, avoid accidental re-use. */
594#ifndef WITH_PYTHON_MODULE
595 ba = nullptr;
596 (void)ba;
597#endif
598
599#ifdef USE_WIN32_UNICODE_ARGS
600 argv = nullptr;
601 (void)argv;
602#endif
603
604#ifndef WITH_PYTHON_MODULE
605 if (G.background) {
606 int exit_code;
607 if (app_state.main_arg_deferred != nullptr) {
608 exit_code = main_arg_deferred_handle();
610 }
611 else {
612 exit_code = G.is_break ? EXIT_FAILURE : EXIT_SUCCESS;
613 }
614 /* Using window-manager API in background-mode is a bit odd, but works fine. */
615 WM_exit(C, exit_code);
616 }
617 else {
618 /* Not supported, although it could be made to work if needed. */
619 BLI_assert(app_state.main_arg_deferred == nullptr);
620
621 /* Shows the splash as needed. */
623
624 WM_main(C);
625 }
626 /* Neither #WM_exit, #WM_main return, this quiets CLANG's `unreachable-code-return` warning. */
628
629#endif /* !WITH_PYTHON_MODULE */
630
631 return 0;
632
633} /* End of `int main(...)` function. */
634
635#ifdef WITH_PYTHON_MODULE
636void main_python_exit()
637{
638 WM_exit_ex((bContext *)evil_C, true, false);
639 evil_C = nullptr;
640}
641#endif
642
void BKE_appdir_init()
Definition appdir.cc:93
void BKE_appdir_exit()
Definition appdir.cc:101
void BKE_appdir_program_path_init(const char *argv0) ATTR_NONNULL(1)
Definition appdir.cc:933
Blender util stuff.
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition blender.cc:490
void BKE_blender_atexit_unregister(void(*func)(void *user_data), const void *user_data)
Definition blender.cc:499
void BKE_blender_globals_init()
Definition blender.cc:193
void BKE_blender_globals_clear()
Definition blender.cc:217
void BKE_brush_system_init()
Definition brush.cc:556
void BKE_callback_global_init()
Definition callbacks.cc:102
void CTX_free(bContext *C)
bContext * CTX_create()
void BKE_cpp_types_init()
void BKE_idtype_init()
Definition idtype.cc:121
General operations, lookup, etc. for materials.
void BKE_materials_init()
void BKE_modifier_init()
void BKE_particle_init_rng(void)
Definition particle.cc:418
void BKE_shaderfx_init(void)
Definition shader_fx.cc:48
void BKE_sound_force_device(const char *device)
void BKE_sound_init_once()
void BKE_vfont_builtin_register(const void *mem, int size)
Definition vfont.cc:282
Volume data-block.
void BKE_volumes_init()
A general argument parsing module.
void BLI_args_destroy(struct bArgs *ba)
Definition BLI_args.cc:144
struct bArgs * BLI_args_create(int argc, const char **argv)
Definition BLI_args.cc:124
void BLI_args_parse(struct bArgs *ba, int pass, BA_ArgCallback default_cb, void *default_data)
Definition BLI_args.cc:336
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_assert(a)
Definition BLI_assert.h:46
#define L_ENDIAN
#define ENDIAN_ORDER
void BLI_kdtree_nd_ free(KDTree *tree)
void BLI_setenv(const char *env, const char *val) ATTR_NONNULL(1)
const char * BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define STR_ELEM(...)
Definition BLI_string.h:661
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
void BLI_system_backtrace(FILE *fp)
Definition system.cc:103
void BLI_task_scheduler_init(void)
void BLI_threadapi_init(void)
Definition threads.cc:114
#define STRPREFIX(a, b)
#define STREQ(a, b)
#define LIKELY(x)
void CCL_log_init(void)
Definition logging.cpp:12
void CLG_output_use_basename_set(int value)
Definition clog.cc:895
void CLG_exit()
Definition clog.cc:880
void CLG_output_use_memory_set(int value)
Definition clog.cc:905
void CLG_output_use_source_set(int value)
Definition clog.cc:890
void CLG_fatal_fn_set(void(*fatal_fn)(void *file_handle))
Definition clog.cc:915
void CLG_output_use_timestamp_set(int value)
Definition clog.cc:900
void CLG_init()
Definition clog.cc:873
void DEG_free_node_types()
void DEG_register_node_types()
blenloader genfile private function prototypes
void DNA_sdna_current_free(void)
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_init()
Definition module.cc:15
Read Guarded memory(de)allocation.
#define C
Definition RandGen.cpp:29
char build_commit_date[]
Definition bpy_app.cc:68
ulong build_commit_timestamp
Definition bpy_app.cc:67
char build_commit_time[]
Definition bpy_app.cc:69
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static void callback_main_atexit(void *user_data)
Definition creator.cc:178
static void main_callback_setup()
Definition creator.cc:149
void * gmp_realloc(void *ptr, size_t, size_t new_size)
Definition creator.cc:260
void * gmp_alloc(size_t size)
Definition creator.cc:256
static void restore_ld_preload()
Definition creator.cc:281
void gmp_free(void *ptr, size_t)
Definition creator.cc:265
void gmp_blender_init_allocator()
Definition creator.cc:275
ApplicationState app_state
Definition creator.cc:126
static void callback_mem_error(const char *errorStr)
Definition creator.cc:143
static void callback_clg_fatal(void *fp)
Definition creator.cc:213
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)
#define main()
#define printf(...)
void RE_engines_init()
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:67
void MEM_use_guarded_allocator()
Definition mallocn.cc:204
#define G(x, y, z)
void MOV_init()
void node_system_init()
Definition node.cc:5426
void initialize_float()
Definition fftw.cc:88
void RNA_init()
Definition rna_access.cc:88
CreatorAtExitData_EarlyExit * early_exit
Definition creator.cc:175
i
Definition text_draw.cc:230
void RE_texture_rng_init()
char * alloc_utf_8_from_16(const wchar_t *in16, size_t add)
Definition utfconv.cc:282
void WM_main(bContext *C)
Definition wm.cc:583
PointerRNA * ptr
Definition wm_files.cc:4238
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)