2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19 * All rights reserved.
21 * The Original Code is: all of this file.
23 * Contributor(s): none yet.
25 * ***** END GPL LICENSE BLOCK *****
28 /** \file creator/creator.c
36 # if defined(_MSC_VER) && defined(_M_X64)
37 # include <math.h> /* needed for _set_FMA3_enable */
43 #include "MEM_guardedalloc.h"
46 # include "BLI_winstuff.h"
50 #include "BLI_threads.h"
51 #include "BLI_utildefines.h"
52 #include "BLI_callbacks.h"
53 #include "BLI_string.h"
55 /* mostly init functions */
56 #include "BKE_appdir.h"
57 #include "BKE_blender.h"
58 #include "BKE_brush.h"
59 #include "BKE_context.h"
60 #include "BKE_depsgraph.h" /* for DAG_init */
62 #include "BKE_global.h"
63 #include "BKE_material.h"
64 #include "BKE_modifier.h"
66 #include "BKE_sound.h"
67 #include "BKE_image.h"
68 #include "BKE_particle.h"
71 #include "IMB_imbuf.h" /* for IMB_init */
73 #include "RE_engine.h"
74 #include "RE_render_ext.h"
76 #include "ED_datafiles.h"
80 #include "RNA_define.h"
83 # include "FRS_freestyle.h"
86 /* for passing information between creator and gameengine */
87 #ifdef WITH_GAMEENGINE
88 # include "BL_System.h"
90 # define SYS_SystemHandle int
96 # include <floatingpoint.h>
100 # include "binreloc.h"
104 # include "libmv-capi.h"
107 #ifdef WITH_CYCLES_LOGGING
108 # include "CCL_api.h"
111 #ifdef WITH_SDL_DYNLOAD
115 #include "creator_intern.h" /* own include */
118 /* Local Function prototypes */
119 #ifdef WITH_PYTHON_MODULE
120 int main_python_enter(int argc, const char **argv);
121 void main_python_exit(void);
124 /* written to by 'creator_args.c' */
125 struct ApplicationState app_state = {
127 .use_crash_handler = true,
128 .use_abort_handler = true,
130 .exit_code_on_error = {
135 /* -------------------------------------------------------------------- */
137 /** \name Application Level Callbacks
139 * Initialize callbacks for the modules that need them.
143 static void callback_mem_error(const char *errorStr)
145 fputs(errorStr, stderr);
149 static void main_callback_setup(void)
151 /* Error output from the alloc routines: */
152 MEM_set_error_callback(callback_mem_error);
159 /* -------------------------------------------------------------------- */
161 /** \name Main Function
164 #ifdef WITH_PYTHON_MODULE
165 /* allow python module to call main */
166 # define main main_python_enter
167 static void *evil_C = NULL;
170 /* environ is not available in mac shared libraries */
171 # include <crt_externs.h>
172 char **environ = NULL;
177 * Blender's main function responsibilities are:
178 * - setup subsystems.
179 * - handle arguments.
180 * - run #WM_main() event loop,
181 * or exit immediately when running in background mode.
186 const char **UNUSED(argv_c)
193 SYS_SystemHandle syshandle;
195 #ifndef WITH_PYTHON_MODULE
204 /* --- end declarations --- */
208 /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
209 # if defined(_MSC_VER) && defined(_M_X64)
213 /* Win32 Unicode Args */
214 /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
215 * (it depends on the args passed in, which is what we're getting here!)
218 wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
219 argv = malloc(argc * sizeof(char *));
220 for (argv_num = 0; argv_num < argc; argv_num++) {
221 argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
227 /* NOTE: Special exception for guarded allocator type switch:
228 * we need to perform switch from lock-free to fully
229 * guarded allocator before any allocation happened.
233 for (i = 0; i < argc; i++) {
234 if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
235 STREQ(argv[i], "--debug-memory") || STREQ(argv[i], "--debug-all"))
237 printf("Switching to fully guarded memory allocator.\n");
238 MEM_use_guarded_allocator();
241 else if (STREQ(argv[i], "--")) {
249 time_t temp_time = build_commit_timestamp;
250 struct tm *tm = gmtime(&temp_time);
252 strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
253 strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
256 const char *unknown = "date-unknown";
257 BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
258 BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
263 #ifdef WITH_SDL_DYNLOAD
269 #ifdef WITH_PYTHON_MODULE
271 environ = *_NSGetEnviron();
285 libmv_initLogging(argv[0]);
286 #elif defined(WITH_CYCLES_LOGGING)
287 CCL_init_logging(argv[0]);
290 main_callback_setup();
292 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
293 /* patch to ignore argument finder gives us (pid?) */
294 if (argc == 2 && STREQLEN(argv[1], "-psn_", 5)) {
295 extern int GHOST_HACK_getFirstFile(char buf[]);
296 static char firstfilebuf[512];
300 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
302 argv[1] = firstfilebuf;
311 /* initialize path to executable */
312 BKE_appdir_program_path_init(argv[0]);
314 BLI_threadapi_init();
316 initglobals(); /* blender.c */
323 BKE_brush_system_init();
324 RE_texture_rng_init();
327 BLI_callback_global_init();
329 #ifdef WITH_GAMEENGINE
330 syshandle = SYS_GetSystem();
335 /* first test for background */
336 #ifndef WITH_PYTHON_MODULE
337 ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
338 main_args_setup(C, ba, &syshandle);
340 BLI_argsParse(ba, 1, NULL, NULL);
345 G.factory_startup = true; /* using preferences or user startup makes no sense for py-as-module */
353 /* after level 1 args, this is so playanim skips RNA init */
359 /* end second init */
362 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
363 G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
366 main_signal_setup_background();
370 /* background render uses this font too */
371 BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
373 /* Initialize ffmpeg if built in, also needed for bg mode if videos are
374 * rendered via ffmpeg */
375 BKE_sound_init_once();
379 if (G.background == 0) {
380 #ifndef WITH_PYTHON_MODULE
381 BLI_argsParse(ba, 2, NULL, NULL);
382 BLI_argsParse(ba, 3, NULL, NULL);
384 WM_init(C, argc, (const char **)argv);
386 /* this is properly initialized with user defs, but this is default */
387 /* call after loading the startup.blend so we can read U.tempdir */
388 BKE_tempdir_init(U.tempdir);
391 #ifndef WITH_PYTHON_MODULE
392 BLI_argsParse(ba, 3, NULL, NULL);
395 WM_init(C, argc, (const char **)argv);
397 /* don't use user preferences temp dir */
398 BKE_tempdir_init(NULL);
402 * NOTE: the U.pythondir string is NULL until WM_init() is executed,
403 * so we provide the BPY_ function below to append the user defined
404 * python-dir to Python's sys.path at this point. Simply putting
405 * WM_init() before #BPY_python_start() crashes Blender at startup.
408 /* TODO - U.pythondir */
410 printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
413 CTX_py_init_set(C, 1);
416 #ifdef WITH_FREESTYLE
417 /* initialize Freestyle */
422 /* OK we are ready for it */
423 #ifndef WITH_PYTHON_MODULE
424 main_args_setup_post(C, ba);
426 if (G.background == 0) {
428 if (U.uiflag2 & USER_KEEP_SESSION)
429 WM_recover_last_session(C, NULL);
434 #ifndef WITH_PYTHON_MODULE
440 free(argv[--argv_num]);
446 #ifdef WITH_PYTHON_MODULE
447 return 0; /* keep blender in background mode running */
451 /* Using window-manager API in background mode is a bit odd, but works fine. */
455 if (G.fileflags & G_FILE_AUTOPLAY) {
456 if (G.f & G_SCRIPT_AUTOEXEC) {
457 if (WM_init_game(C)) {
462 if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
463 G.f |= G_SCRIPT_AUTOEXEC_FAIL;
464 BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
469 if (!G.file_loaded) {
477 } /* end of int main(argc, argv) */
479 #ifdef WITH_PYTHON_MODULE
480 void main_python_exit(void)
482 WM_exit_ext((bContext *)evil_C, true);