move opengl library loading to a thread that starts as soon as possible and is awaited as late as we can allow
This commit is contained in:
parent
8233f31269
commit
449d4d3c32
@ -28,6 +28,7 @@ typedef struct EngineContext {
|
|||||||
char **argv;
|
char **argv;
|
||||||
/* where the app was run from, used as the root for packs */
|
/* where the app was run from, used as the root for packs */
|
||||||
char *base_dir;
|
char *base_dir;
|
||||||
|
char *title;
|
||||||
|
|
||||||
Vec2 window_dims;
|
Vec2 window_dims;
|
||||||
Rect viewport_rect;
|
Rect viewport_rect;
|
||||||
|
210
src/twn_loop.c
210
src/twn_loop.c
@ -4,7 +4,6 @@
|
|||||||
#include "twn_util.h"
|
#include "twn_util.h"
|
||||||
#include "twn_util_c.h"
|
#include "twn_util_c.h"
|
||||||
#include "twn_game_object_c.h"
|
#include "twn_game_object_c.h"
|
||||||
#include "twn_audio_c.h"
|
|
||||||
#include "twn_textures_c.h"
|
#include "twn_textures_c.h"
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
@ -20,6 +19,9 @@
|
|||||||
#define PACKAGE_EXTENSION "btw"
|
#define PACKAGE_EXTENSION "btw"
|
||||||
|
|
||||||
|
|
||||||
|
static SDL_Thread *opengl_load_thread;
|
||||||
|
|
||||||
|
|
||||||
static int event_callback(void *userdata, SDL_Event *event) {
|
static int event_callback(void *userdata, SDL_Event *event) {
|
||||||
(void)userdata;
|
(void)userdata;
|
||||||
|
|
||||||
@ -342,14 +344,16 @@ ERR_PACK_MANIFEST_PATH_ALLOC_FAIL:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool initialize(void) {
|
static int opengl_load_thread_fn(void *data) {
|
||||||
profile_start("SDL initialization");
|
(void)data;
|
||||||
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS) == -1) {
|
|
||||||
CRY_SDL("SDL initialization failed.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
profile_end("SDL initialization");
|
|
||||||
|
|
||||||
|
SDL_GL_LoadLibrary(NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool initialize(void) {
|
||||||
/* first things first, most things here will be loaded from the config file */
|
/* first things first, most things here will be loaded from the config file */
|
||||||
/* it's expected to be present in the data directory, no matter what */
|
/* it's expected to be present in the data directory, no matter what */
|
||||||
/* that is why PhysicsFS is initialized before anything else */
|
/* that is why PhysicsFS is initialized before anything else */
|
||||||
@ -446,91 +450,46 @@ static bool initialize(void) {
|
|||||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||||
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
|
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
|
||||||
|
|
||||||
/* init got far enough to create a window */
|
toml_datum_t datum_title = toml_string_in(about, "title");
|
||||||
{
|
if (!datum_title.ok)
|
||||||
toml_datum_t datum_title = toml_string_in(about, "title");
|
datum_title.u.s = SDL_strdup("townengine project");
|
||||||
if (!datum_title.ok)
|
|
||||||
datum_title.u.s = "townengine project";
|
|
||||||
|
|
||||||
/* not yet used
|
ctx.title = datum_title.u.s;
|
||||||
toml_datum_t datum_developer = toml_string_in(about, "developer");
|
|
||||||
if (!datum_developer.ok) {
|
/* not yet used
|
||||||
CRY("Initialization failed", "Valid about.developer expected in configuration file");
|
toml_datum_t datum_developer = toml_string_in(about, "developer");
|
||||||
|
if (!datum_developer.ok) {
|
||||||
|
CRY("Initialization failed", "Valid about.developer expected in configuration file");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
toml_array_t *datum_resolution = toml_array_in(game, "resolution");
|
||||||
|
if (datum_resolution) {
|
||||||
|
toml_datum_t datum_base_render_width = toml_int_at(datum_resolution, 0);
|
||||||
|
if (!datum_base_render_width.ok) {
|
||||||
|
CRY("Initialization failed", "Valid game.resolution expected in configuration file");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
toml_array_t *datum_resolution = toml_array_in(game, "resolution");
|
toml_datum_t datum_base_render_height = toml_int_at(datum_resolution, 1);
|
||||||
if (datum_resolution) {
|
if (!datum_base_render_height.ok) {
|
||||||
toml_datum_t datum_base_render_width = toml_int_at(datum_resolution, 0);
|
CRY("Initialization failed", "Valid game.resolution expected in configuration file");
|
||||||
if (!datum_base_render_width.ok) {
|
goto fail;
|
||||||
CRY("Initialization failed", "Valid game.resolution expected in configuration file");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
toml_datum_t datum_base_render_height = toml_int_at(datum_resolution, 1);
|
|
||||||
if (!datum_base_render_height.ok) {
|
|
||||||
CRY("Initialization failed", "Valid game.resolution expected in configuration file");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.base_render_width = datum_base_render_width.u.i;
|
|
||||||
ctx.base_render_height = datum_base_render_height.u.i;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ctx.base_render_width = 640;
|
|
||||||
ctx.base_render_height = 360;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.game.resolution.x = (float)ctx.base_render_width;
|
ctx.base_render_width = datum_base_render_width.u.i;
|
||||||
ctx.game.resolution.y = (float)ctx.base_render_height;
|
ctx.base_render_height = datum_base_render_height.u.i;
|
||||||
|
|
||||||
/* TODO: investigate viability of detached thread driver and window creation, as it's the worst load time offender */
|
} else {
|
||||||
profile_start("window creation");
|
ctx.base_render_width = 640;
|
||||||
ctx.window = SDL_CreateWindow(datum_title.u.s,
|
ctx.base_render_height = 360;
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
SDL_WINDOWPOS_CENTERED,
|
|
||||||
(int)ctx.base_render_width,
|
|
||||||
(int)ctx.base_render_height,
|
|
||||||
//SDL_WINDOW_ALLOW_HIGHDPI |
|
|
||||||
SDL_WINDOW_RESIZABLE |
|
|
||||||
SDL_WINDOW_OPENGL);
|
|
||||||
profile_end("window creation");
|
|
||||||
|
|
||||||
if (datum_title.ok)
|
|
||||||
SDL_free(datum_title.u.s);
|
|
||||||
|
|
||||||
//SDL_free(datum_developer.u.s);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.window == NULL) {
|
ctx.game.resolution.x = (float)ctx.base_render_width;
|
||||||
CRY_SDL("Window creation failed.");
|
ctx.game.resolution.y = (float)ctx.base_render_height;
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
profile_start("opengl context creation");
|
//SDL_free(datum_developer.u.s);
|
||||||
ctx.gl_context = SDL_GL_CreateContext(ctx.window);
|
|
||||||
if (!ctx.gl_context) {
|
|
||||||
CRY_SDL("GL context creation failed.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SDL_GL_MakeCurrent(ctx.window, ctx.gl_context)) {
|
|
||||||
CRY_SDL("GL context binding failed.");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: figure out what we ultimately prefer */
|
|
||||||
SDL_GL_SetSwapInterval(0);
|
|
||||||
|
|
||||||
if (!render_init())
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
setup_viewport(0, 0, (int)ctx.base_render_width, (int)ctx.base_render_height);
|
|
||||||
profile_end("opengl context creation");
|
|
||||||
|
|
||||||
/* might need this to have multiple windows */
|
|
||||||
ctx.window_id = SDL_GetWindowID(ctx.window);
|
|
||||||
|
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
// SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h);
|
// SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h);
|
||||||
@ -628,11 +587,6 @@ static bool initialize(void) {
|
|||||||
ctx.render_queue_2d = NULL;
|
ctx.render_queue_2d = NULL;
|
||||||
ctx.uncolored_mesh_batches = NULL;
|
ctx.uncolored_mesh_batches = NULL;
|
||||||
|
|
||||||
profile_start("texture and text cache initialization");
|
|
||||||
textures_cache_init(&ctx.texture_cache, ctx.window);
|
|
||||||
text_cache_init(&ctx.text_cache);
|
|
||||||
profile_end("texture and text cache initialization");
|
|
||||||
|
|
||||||
/* input */
|
/* input */
|
||||||
toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots");
|
toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots");
|
||||||
if (!datum_keybind_slots.ok) {
|
if (!datum_keybind_slots.ok) {
|
||||||
@ -652,6 +606,63 @@ static bool initialize(void) {
|
|||||||
ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */
|
ctx.game.fog_color = (Color){ 255, 255, 255, 255 }; /* TODO: pick some grey? */
|
||||||
ctx.game.fog_end = 1.0f;
|
ctx.game.fog_end = 1.0f;
|
||||||
|
|
||||||
|
update_viewport();
|
||||||
|
|
||||||
|
profile_start("game object load");
|
||||||
|
/* now we can actually start doing stuff */
|
||||||
|
game_object_load();
|
||||||
|
profile_end("game object load");
|
||||||
|
|
||||||
|
/* delayed as further as possible so that more work is done before we have to wait */
|
||||||
|
SDL_WaitThread(opengl_load_thread, NULL);
|
||||||
|
profile_end("opengl loading");
|
||||||
|
|
||||||
|
/* TODO: investigate viability of detached thread driver and window creation, as it's the worst load time offender */
|
||||||
|
profile_start("window creation");
|
||||||
|
ctx.window = SDL_CreateWindow(ctx.title,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
SDL_WINDOWPOS_CENTERED,
|
||||||
|
(int)ctx.base_render_width,
|
||||||
|
(int)ctx.base_render_height,
|
||||||
|
//SDL_WINDOW_ALLOW_HIGHDPI |
|
||||||
|
SDL_WINDOW_RESIZABLE |
|
||||||
|
SDL_WINDOW_OPENGL);
|
||||||
|
profile_end("window creation");
|
||||||
|
|
||||||
|
if (ctx.window == NULL) {
|
||||||
|
CRY_SDL("Window creation failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile_start("opengl context creation");
|
||||||
|
ctx.gl_context = SDL_GL_CreateContext(ctx.window);
|
||||||
|
if (!ctx.gl_context) {
|
||||||
|
CRY_SDL("GL context creation failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GL_MakeCurrent(ctx.window, ctx.gl_context)) {
|
||||||
|
CRY_SDL("GL context binding failed.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* TODO: figure out what we ultimately prefer */
|
||||||
|
SDL_GL_SetSwapInterval(0);
|
||||||
|
|
||||||
|
if (!render_init())
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
setup_viewport(0, 0, (int)ctx.base_render_width, (int)ctx.base_render_height);
|
||||||
|
profile_end("opengl context creation");
|
||||||
|
|
||||||
|
/* might need this to have multiple windows */
|
||||||
|
ctx.window_id = SDL_GetWindowID(ctx.window);
|
||||||
|
|
||||||
|
profile_start("texture and text cache initialization");
|
||||||
|
textures_cache_init(&ctx.texture_cache, ctx.window);
|
||||||
|
text_cache_init(&ctx.text_cache);
|
||||||
|
profile_end("texture and text cache initialization");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -674,7 +685,9 @@ static void clean_up(void) {
|
|||||||
PHYSFS_deinit();
|
PHYSFS_deinit();
|
||||||
|
|
||||||
SDL_free(ctx.base_dir);
|
SDL_free(ctx.base_dir);
|
||||||
|
SDL_free(ctx.title);
|
||||||
SDL_GL_DeleteContext(ctx.gl_context);
|
SDL_GL_DeleteContext(ctx.gl_context);
|
||||||
|
SDL_GL_UnloadLibrary();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,6 +701,20 @@ static void reset_state(void) {
|
|||||||
int enter_loop(int argc, char **argv) {
|
int enter_loop(int argc, char **argv) {
|
||||||
profile_start("startup");
|
profile_start("startup");
|
||||||
|
|
||||||
|
profile_start("SDL initialization");
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_EVENTS) == -1) {
|
||||||
|
CRY_SDL("SDL initialization failed.");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
profile_end("SDL initialization");
|
||||||
|
|
||||||
|
profile_start("opengl loading");
|
||||||
|
opengl_load_thread = SDL_CreateThread(opengl_load_thread_fn, "opengl loader", NULL);
|
||||||
|
if (!opengl_load_thread) {
|
||||||
|
CRY_SDL("Cannot create opengl loading thread: ");
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.argc = argc;
|
ctx.argc = argc;
|
||||||
ctx.argv = argv;
|
ctx.argv = argv;
|
||||||
ctx.base_dir = SDL_GetBasePath();
|
ctx.base_dir = SDL_GetBasePath();
|
||||||
@ -763,13 +790,6 @@ int enter_loop(int argc, char **argv) {
|
|||||||
ctx.game.debug = false;
|
ctx.game.debug = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
update_viewport();
|
|
||||||
|
|
||||||
profile_start("game object load");
|
|
||||||
/* now we can actually start doing stuff */
|
|
||||||
game_object_load();
|
|
||||||
profile_end("game object load");
|
|
||||||
|
|
||||||
ctx.was_successful = true;
|
ctx.was_successful = true;
|
||||||
ctx.game.initialization_needed = true;
|
ctx.game.initialization_needed = true;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user