Refactor BKE_blender into separate headers
[blender-staging.git] / source / creator / creator.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
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.
8  *
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.
13  *
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.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file creator/creator.c
29  *  \ingroup creator
30  */
31
32 #include <stdlib.h>
33 #include <string.h>
34
35 #ifdef WIN32
36 #  if defined(_MSC_VER) && defined(_M_X64)
37 #    include <math.h> /* needed for _set_FMA3_enable */
38 #  endif
39 #  include <windows.h>
40 #  include "utfconv.h"
41 #endif
42
43 #include "MEM_guardedalloc.h"
44
45 #ifdef WIN32
46 #  include "BLI_winstuff.h"
47 #endif
48
49 #include "BLI_args.h"
50 #include "BLI_threads.h"
51 #include "BLI_utildefines.h"
52 #include "BLI_callbacks.h"
53 #include "BLI_string.h"
54
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 */
61 #include "BKE_font.h"
62 #include "BKE_global.h"
63 #include "BKE_material.h"
64 #include "BKE_modifier.h"
65 #include "BKE_node.h"
66 #include "BKE_sound.h"
67 #include "BKE_image.h"
68 #include "BKE_particle.h"
69
70
71 #include "IMB_imbuf.h"  /* for IMB_init */
72
73 #include "RE_engine.h"
74 #include "RE_render_ext.h"
75
76 #include "ED_datafiles.h"
77
78 #include "WM_api.h"
79
80 #include "RNA_define.h"
81
82 #ifdef WITH_FREESTYLE
83 #  include "FRS_freestyle.h"
84 #endif
85
86 /* for passing information between creator and gameengine */
87 #ifdef WITH_GAMEENGINE
88 #  include "BL_System.h"
89 #else /* dummy */
90 #  define SYS_SystemHandle int
91 #endif
92
93 #include <signal.h>
94
95 #ifdef __FreeBSD__
96 #  include <floatingpoint.h>
97 #endif
98
99 #ifdef WITH_BINRELOC
100 #  include "binreloc.h"
101 #endif
102
103 #ifdef WITH_LIBMV
104 #  include "libmv-capi.h"
105 #endif
106
107 #ifdef WITH_CYCLES_LOGGING
108 #  include "CCL_api.h"
109 #endif
110
111 #ifdef WITH_SDL_DYNLOAD
112 #  include "sdlew.h"
113 #endif
114
115 #include "creator_intern.h"  /* own include */
116
117
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);
122 #endif
123
124 /* written to by 'creator_args.c' */
125 struct ApplicationState app_state = {
126         .signal = {
127                 .use_crash_handler = true,
128                 .use_abort_handler = true,
129         },
130         .exit_code_on_error = {
131                 .python = 0,
132         }
133 };
134
135 /* -------------------------------------------------------------------- */
136
137 /** \name Application Level Callbacks
138  *
139  * Initialize callbacks for the modules that need them.
140  *
141  * \{ */
142
143 static void callback_mem_error(const char *errorStr)
144 {
145         fputs(errorStr, stderr);
146         fflush(stderr);
147 }
148
149 static void main_callback_setup(void)
150 {
151         /* Error output from the alloc routines: */
152         MEM_set_error_callback(callback_mem_error);
153 }
154
155 /** \} */
156
157
158
159 /* -------------------------------------------------------------------- */
160
161 /** \name Main Function
162  * \{ */
163
164 #ifdef WITH_PYTHON_MODULE
165 /* allow python module to call main */
166 #  define main main_python_enter
167 static void *evil_C = NULL;
168
169 #  ifdef __APPLE__
170      /* environ is not available in mac shared libraries */
171 #    include <crt_externs.h>
172 char **environ = NULL;
173 #  endif
174 #endif
175
176 /**
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.
182  */
183 int main(
184         int argc,
185 #ifdef WIN32
186         const char **UNUSED(argv_c)
187 #else
188         const char **argv
189 #endif
190         )
191 {
192         bContext *C;
193         SYS_SystemHandle syshandle;
194
195 #ifndef WITH_PYTHON_MODULE
196         bArgs *ba;
197 #endif
198
199 #ifdef WIN32
200         char **argv;
201         int argv_num;
202 #endif
203
204         /* --- end declarations --- */
205
206
207 #ifdef WIN32
208         /* We delay loading of openmp so we can set the policy here. */
209 # if defined(_MSC_VER)
210         _putenv_s("OMP_WAIT_POLICY", "PASSIVE");
211 # endif
212
213         /* FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it. */
214 #  if defined(_MSC_VER) && defined(_M_X64)
215         _set_FMA3_enable(0);
216 #  endif
217
218         /* Win32 Unicode Args */
219         /* NOTE: cannot use guardedalloc malloc here, as it's not yet initialized
220          *       (it depends on the args passed in, which is what we're getting here!)
221          */
222         {
223                 wchar_t **argv_16 = CommandLineToArgvW(GetCommandLineW(), &argc);
224                 argv = malloc(argc * sizeof(char *));
225                 for (argv_num = 0; argv_num < argc; argv_num++) {
226                         argv[argv_num] = alloc_utf_8_from_16(argv_16[argv_num], 0);
227                 }
228                 LocalFree(argv_16);
229         }
230 #endif  /* WIN32 */
231
232         /* NOTE: Special exception for guarded allocator type switch:
233          *       we need to perform switch from lock-free to fully
234          *       guarded allocator before any allocation happened.
235          */
236         {
237                 int i;
238                 for (i = 0; i < argc; i++) {
239                         if (STREQ(argv[i], "--debug") || STREQ(argv[i], "-d") ||
240                             STREQ(argv[i], "--debug-memory") || STREQ(argv[i], "--debug-all"))
241                         {
242                                 printf("Switching to fully guarded memory allocator.\n");
243                                 MEM_use_guarded_allocator();
244                                 break;
245                         }
246                         else if (STREQ(argv[i], "--")) {
247                                 break;
248                         }
249                 }
250         }
251
252 #ifdef BUILD_DATE
253         {
254                 time_t temp_time = build_commit_timestamp;
255                 struct tm *tm = gmtime(&temp_time);
256                 if (LIKELY(tm)) {
257                         strftime(build_commit_date, sizeof(build_commit_date), "%Y-%m-%d", tm);
258                         strftime(build_commit_time, sizeof(build_commit_time), "%H:%M", tm);
259                 }
260                 else {
261                         const char *unknown = "date-unknown";
262                         BLI_strncpy(build_commit_date, unknown, sizeof(build_commit_date));
263                         BLI_strncpy(build_commit_time, unknown, sizeof(build_commit_time));
264                 }
265         }
266 #endif
267
268 #ifdef WITH_SDL_DYNLOAD
269         sdlewInit();
270 #endif
271
272         C = CTX_create();
273
274 #ifdef WITH_PYTHON_MODULE
275 #ifdef __APPLE__
276         environ = *_NSGetEnviron();
277 #endif
278
279 #undef main
280         evil_C = C;
281 #endif
282
283
284
285 #ifdef WITH_BINRELOC
286         br_init(NULL);
287 #endif
288
289 #ifdef WITH_LIBMV
290         libmv_initLogging(argv[0]);
291 #elif defined(WITH_CYCLES_LOGGING)
292         CCL_init_logging(argv[0]);
293 #endif
294
295         main_callback_setup();
296         
297 #if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
298         /* patch to ignore argument finder gives us (pid?) */
299         if (argc == 2 && STREQLEN(argv[1], "-psn_", 5)) {
300                 extern int GHOST_HACK_getFirstFile(char buf[]);
301                 static char firstfilebuf[512];
302
303                 argc = 1;
304
305                 if (GHOST_HACK_getFirstFile(firstfilebuf)) {
306                         argc = 2;
307                         argv[1] = firstfilebuf;
308                 }
309         }
310 #endif
311         
312 #ifdef __FreeBSD__
313         fpsetmask(0);
314 #endif
315
316         /* initialize path to executable */
317         BKE_appdir_program_path_init(argv[0]);
318
319         BLI_threadapi_init();
320
321         BKE_blender_globals_init();  /* blender.c */
322
323         IMB_init();
324         BKE_images_init();
325         BKE_modifier_init();
326         DAG_init();
327
328         BKE_brush_system_init();
329         RE_texture_rng_init();
330         
331
332         BLI_callback_global_init();
333
334 #ifdef WITH_GAMEENGINE
335         syshandle = SYS_GetSystem();
336 #else
337         syshandle = 0;
338 #endif
339
340         /* first test for background */
341 #ifndef WITH_PYTHON_MODULE
342         ba = BLI_argsInit(argc, (const char **)argv); /* skip binary path */
343         main_args_setup(C, ba, &syshandle);
344
345         BLI_argsParse(ba, 1, NULL, NULL);
346
347         main_signal_setup();
348
349 #else
350         G.factory_startup = true;  /* using preferences or user startup makes no sense for py-as-module */
351         (void)syshandle;
352 #endif
353
354 #ifdef WITH_FFMPEG
355         IMB_ffmpeg_init();
356 #endif
357
358         /* after level 1 args, this is so playanim skips RNA init */
359         RNA_init();
360
361         RE_engines_init();
362         init_nodesystem();
363         psys_init_rng();
364         /* end second init */
365
366
367 #if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS)
368         G.background = true; /* python module mode ALWAYS runs in background mode (for now) */
369 #else
370         if (G.background) {
371                 main_signal_setup_background();
372         }
373 #endif
374
375         /* background render uses this font too */
376         BKE_vfont_builtin_register(datatoc_bfont_pfb, datatoc_bfont_pfb_size);
377
378         /* Initialize ffmpeg if built in, also needed for bg mode if videos are
379          * rendered via ffmpeg */
380         BKE_sound_init_once();
381         
382         init_def_material();
383
384         if (G.background == 0) {
385 #ifndef WITH_PYTHON_MODULE
386                 BLI_argsParse(ba, 2, NULL, NULL);
387                 BLI_argsParse(ba, 3, NULL, NULL);
388 #endif
389                 WM_init(C, argc, (const char **)argv);
390
391                 /* this is properly initialized with user defs, but this is default */
392                 /* call after loading the startup.blend so we can read U.tempdir */
393                 BKE_tempdir_init(U.tempdir);
394         }
395         else {
396 #ifndef WITH_PYTHON_MODULE
397                 BLI_argsParse(ba, 3, NULL, NULL);
398 #endif
399
400                 WM_init(C, argc, (const char **)argv);
401
402                 /* don't use user preferences temp dir */
403                 BKE_tempdir_init(NULL);
404         }
405 #ifdef WITH_PYTHON
406         /**
407          * NOTE: the U.pythondir string is NULL until WM_init() is executed,
408          * so we provide the BPY_ function below to append the user defined
409          * python-dir to Python's sys.path at this point.  Simply putting
410          * WM_init() before #BPY_python_start() crashes Blender at startup.
411          */
412
413         /* TODO - U.pythondir */
414 #else
415         printf("\n* WARNING * - Blender compiled without Python!\nthis is not intended for typical usage\n\n");
416 #endif
417         
418         CTX_py_init_set(C, 1);
419         WM_keymap_init(C);
420
421 #ifdef WITH_FREESTYLE
422         /* initialize Freestyle */
423         FRS_initialize();
424         FRS_set_context(C);
425 #endif
426
427         /* OK we are ready for it */
428 #ifndef WITH_PYTHON_MODULE
429         main_args_setup_post(C, ba);
430         
431         if (G.background == 0) {
432                 if (!G.file_loaded)
433                         if (U.uiflag2 & USER_KEEP_SESSION)
434                                 WM_recover_last_session(C, NULL);
435         }
436
437 #endif
438
439 #ifndef WITH_PYTHON_MODULE
440         BLI_argsFree(ba);
441 #endif
442
443 #ifdef WIN32
444         while (argv_num) {
445                 free(argv[--argv_num]);
446         }
447         free(argv);
448         argv = NULL;
449 #endif
450
451 #ifdef WITH_PYTHON_MODULE
452         return 0; /* keep blender in background mode running */
453 #endif
454
455         if (G.background) {
456                 /* Using window-manager API in background mode is a bit odd, but works fine. */
457                 WM_exit(C);
458         }
459         else {
460                 if (G.fileflags & G_FILE_AUTOPLAY) {
461                         if (G.f & G_SCRIPT_AUTOEXEC) {
462                                 if (WM_init_game(C)) {
463                                         return 0;
464                                 }
465                         }
466                         else {
467                                 if (!(G.f & G_SCRIPT_AUTOEXEC_FAIL_QUIET)) {
468                                         G.f |= G_SCRIPT_AUTOEXEC_FAIL;
469                                         BLI_snprintf(G.autoexec_fail, sizeof(G.autoexec_fail), "Game AutoStart");
470                                 }
471                         }
472                 }
473
474                 if (!G.file_loaded) {
475                         WM_init_splash(C);
476                 }
477         }
478
479         WM_main(C);
480
481         return 0;
482 } /* end of int main(argc, argv)        */
483
484 #ifdef WITH_PYTHON_MODULE
485 void main_python_exit(void)
486 {
487         WM_exit_ext((bContext *)evil_C, true);
488         evil_C = NULL;
489 }
490 #endif
491
492 /** \} */