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:
Clément Foucault 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;
RenderData *r = &scene->r;
Render *render = engine->re;
if (G.background && DST.ogl_context == NULL) {
WM_init_opengl();
}
/* Changing Context */
DRW_opengl_context_enable();
/* 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_mutex_init(&DST.ogl_context_mutex);
immDeactivate();
if (!G.background) {
immDeactivate();
}
/* This changes the active context. */
DST.ogl_context = WM_opengl_context_create();
/* Be sure to create gawain.context too. */
DST.gwn_context = GWN_context_create();
immActivate();
if (!G.background) {
immActivate();
}
/* Set default Blender OpenGL state */
GPU_state_init();
/* So we activate the window's one afterwards. */
@ -2082,12 +2090,16 @@ void DRW_opengl_context_enable(void)
* multiple threads. */
BLI_mutex_lock(&DST.ogl_context_mutex);
if (BLI_thread_is_main()) {
immDeactivate();
if (!G.background) {
immDeactivate();
}
}
WM_opengl_context_activate(DST.ogl_context);
GWN_context_active_set(DST.gwn_context);
if (BLI_thread_is_main()) {
immActivate();
if (!G.background) {
immActivate();
}
BLF_batch_reset();
}
}

View File

@ -63,7 +63,9 @@ void GPU_init(void)
gpu_batch_init();
immInit();
if (!G.background) {
immInit();
}
GPU_pbvh_fix_linking();
}
@ -72,7 +74,9 @@ void GPU_init(void)
void GPU_exit(void)
{
immDestroy();
if (!G.background) {
immDestroy();
}
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_opengl (void);
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 */
/**
* 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 */
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_init_cursor_data();
}
GHOST_CreateSystemPaths();
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 */
wm_homefile_read(C, NULL, G.factory_startup, false, true, NULL, NULL);
BLT_lang_set(NULL);
@ -210,18 +244,7 @@ void WM_init(bContext *C, int argc, const char **argv)
/* sets 3D mouse deadzone */
WM_ndof_deadzone_set(U.ndof_deadzone);
#endif
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
WM_init_opengl();
UI_init();
}
@ -456,7 +479,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
COM_deinitialize();
#endif
if (!G.background) {
if (opengl_is_init) {
#ifdef WITH_OPENSUBDIV
BKE_subsurf_osd_cleanup();
#endif
@ -483,7 +506,7 @@ void WM_exit_ext(bContext *C, const bool do_python)
BLF_exit();
if (!G.background) {
if (opengl_is_init) {
GPU_pass_cache_free();
DRW_opengl_context_destroy();
}

View File

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