WM: Add GHOST lazy init for background mode.

This allows for background rendering with EEVEE and other opengl render
engine.

I've only tested it on Linux for the moment so I can't say about other
platforms.

We do lazy init because we cannot assume we will need Ghost for rendering
before having parsed all arguments and we cannot know if a script will
trigger rendering. This is also because it currently does not work without
any display server (blender will crash).
This commit is contained in:
2018-04-25 17:43:08 +02:00
parent 56fbdd7908
commit 46bfdb48a1
5 changed files with 73 additions and 24 deletions

View File

@@ -1361,6 +1361,11 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
DrawEngineType *draw_engine_type = engine_type->draw_engine; DrawEngineType *draw_engine_type = engine_type->draw_engine;
RenderData *r = &scene->r; RenderData *r = &scene->r;
Render *render = engine->re; Render *render = engine->re;
if (G.background && DST.ogl_context == NULL) {
WM_init_opengl();
}
/* Changing Context */ /* Changing Context */
DRW_opengl_context_enable(); DRW_opengl_context_enable();
/* IMPORTANT: We dont support immediate mode in render mode! /* IMPORTANT: We dont support immediate mode in render mode!
@@ -2049,13 +2054,16 @@ void DRW_opengl_context_create(void)
BLI_assert(DST.ogl_context == NULL); /* Ensure it's called once */ BLI_assert(DST.ogl_context == NULL); /* Ensure it's called once */
BLI_mutex_init(&DST.ogl_context_mutex); BLI_mutex_init(&DST.ogl_context_mutex);
if (!G.background) {
immDeactivate(); immDeactivate();
}
/* This changes the active context. */ /* This changes the active context. */
DST.ogl_context = WM_opengl_context_create(); DST.ogl_context = WM_opengl_context_create();
/* Be sure to create gawain.context too. */ /* Be sure to create gawain.context too. */
DST.gwn_context = GWN_context_create(); DST.gwn_context = GWN_context_create();
immActivate(); if (!G.background) {
immActivate();
}
/* Set default Blender OpenGL state */ /* Set default Blender OpenGL state */
GPU_state_init(); GPU_state_init();
/* So we activate the window's one afterwards. */ /* So we activate the window's one afterwards. */
@@ -2082,12 +2090,16 @@ void DRW_opengl_context_enable(void)
* multiple threads. */ * multiple threads. */
BLI_mutex_lock(&DST.ogl_context_mutex); BLI_mutex_lock(&DST.ogl_context_mutex);
if (BLI_thread_is_main()) { if (BLI_thread_is_main()) {
immDeactivate(); if (!G.background) {
immDeactivate();
}
} }
WM_opengl_context_activate(DST.ogl_context); WM_opengl_context_activate(DST.ogl_context);
GWN_context_active_set(DST.gwn_context); GWN_context_active_set(DST.gwn_context);
if (BLI_thread_is_main()) { if (BLI_thread_is_main()) {
immActivate(); if (!G.background) {
immActivate();
}
BLF_batch_reset(); BLF_batch_reset();
} }
} }

View File

@@ -63,7 +63,9 @@ void GPU_init(void)
gpu_batch_init(); gpu_batch_init();
immInit(); if (!G.background) {
immInit();
}
GPU_pbvh_fix_linking(); GPU_pbvh_fix_linking();
} }
@@ -72,7 +74,9 @@ void GPU_init(void)
void GPU_exit(void) void GPU_exit(void)
{ {
immDestroy(); if (!G.background) {
immDestroy();
}
gpu_batch_exit(); gpu_batch_exit();

View File

@@ -93,6 +93,7 @@ void WM_main (struct bContext *C) ATTR_NORETURN;
void WM_init_splash (struct bContext *C); void WM_init_splash (struct bContext *C);
void WM_init_opengl (void);
void WM_check (struct bContext *C); void WM_check (struct bContext *C);

View File

@@ -154,6 +154,40 @@ static void wm_free_reports(bContext *C)
bool wm_start_with_console = false; /* used in creator.c */ bool wm_start_with_console = false; /* used in creator.c */
/**
* Since we cannot know in advance if we will require the draw manager
* context when starting blender in background mode (specially true with
* scripts) we deferre the ghost initialization the most as possible
* so that it does not break anything that can run in headless mode (as in
* without display server attached).
**/
static bool opengl_is_init = false;
void WM_init_opengl(void)
{
/* must be called only once */
BLI_assert(opengl_is_init == false);
if (G.background) {
/* Ghost is still not init elsewhere in background mode. */
wm_ghost_init(NULL);
}
/* Needs to be first to have an ogl context bound. */
DRW_opengl_context_create();
GPU_init();
GPU_set_mipmap(true);
GPU_set_linear_mipmap(true);
GPU_set_anisotropic(U.anisotropic_filter);
GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
#ifdef WITH_OPENSUBDIV
BKE_subsurf_osd_init();
#endif
opengl_is_init = true;
}
/* only called once, for startup */ /* only called once, for startup */
void WM_init(bContext *C, int argc, const char **argv) void WM_init(bContext *C, int argc, const char **argv)
{ {
@@ -162,6 +196,7 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_ghost_init(C); /* note: it assigns C to ghost! */ wm_ghost_init(C); /* note: it assigns C to ghost! */
wm_init_cursor_data(); wm_init_cursor_data();
} }
GHOST_CreateSystemPaths(); GHOST_CreateSystemPaths();
BKE_addon_pref_type_init(); BKE_addon_pref_type_init();
@@ -200,7 +235,6 @@ void WM_init(bContext *C, int argc, const char **argv)
/* get the default database, plus a wm */ /* get the default database, plus a wm */
wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, NULL); wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, NULL);
BLT_lang_set(NULL); BLT_lang_set(NULL);
@@ -210,18 +244,7 @@ void WM_init(bContext *C, int argc, const char **argv)
/* sets 3D mouse deadzone */ /* sets 3D mouse deadzone */
WM_ndof_deadzone_set(U.ndof_deadzone); WM_ndof_deadzone_set(U.ndof_deadzone);
#endif #endif
DRW_opengl_context_create(); WM_init_opengl();
GPU_init();
GPU_set_mipmap(true);
GPU_set_linear_mipmap(true);
GPU_set_anisotropic(U.anisotropic_filter);
GPU_set_gpu_mipmapping(U.use_gpu_mipmap);
#ifdef WITH_OPENSUBDIV
BKE_subsurf_osd_init();
#endif
UI_init(); UI_init();
} }
@@ -456,7 +479,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
COM_deinitialize(); COM_deinitialize();
#endif #endif
if (!G.background) { if (opengl_is_init) {
#ifdef WITH_OPENSUBDIV #ifdef WITH_OPENSUBDIV
BKE_subsurf_osd_cleanup(); BKE_subsurf_osd_cleanup();
#endif #endif
@@ -483,7 +506,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLF_exit(); BLF_exit();
if (!G.background) { if (opengl_is_init) {
GPU_pass_cache_free(); GPU_pass_cache_free();
DRW_opengl_context_destroy(); DRW_opengl_context_destroy();
} }

View File

@@ -1735,13 +1735,22 @@ void wm_window_testbreak(void)
/* **************** init ********************** */ /* **************** init ********************** */
/* bContext can be null in background mode because we don't
* need to event handling. */
void wm_ghost_init(bContext *C) void wm_ghost_init(bContext *C)
{ {
if (!g_system) { if (!g_system) {
GHOST_EventConsumerHandle consumer = GHOST_CreateEventConsumer(ghost_event_proc, C); GHOST_EventConsumerHandle consumer;
if (C != NULL) {
consumer = GHOST_CreateEventConsumer(ghost_event_proc, C);
}
g_system = GHOST_CreateSystem(); g_system = GHOST_CreateSystem();
GHOST_AddEventConsumer(g_system, consumer);
if (C != NULL) {
GHOST_AddEventConsumer(g_system, consumer);
}
if (wm_init_state.native_pixels) { if (wm_init_state.native_pixels) {
GHOST_UseNativePixels(); GHOST_UseNativePixels();