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