mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-09-05 11:25:59 -04:00
SLD context now running in main thread (for better compatibility)
This commit is contained in:
parent
96eaeb4851
commit
e0aa5096ba
16 changed files with 259 additions and 275 deletions
|
@ -10,7 +10,12 @@ static std::unique_ptr<uint16_t[]> buffer2nd;
|
|||
static uint16_t *render_target;
|
||||
static uint16_t screen_pitch = 640;
|
||||
|
||||
char game_display_init(const INI_CONFIG_SECTION *display_section, const char *title) {
|
||||
int game_display_init(const INI_CONFIG_SECTION *display_section,
|
||||
const char *title,
|
||||
int (*game_thread)(va_list), ...) {
|
||||
|
||||
va_list args;
|
||||
va_start(args,game_thread);
|
||||
|
||||
SDLContext::VideoConfig cfg = {};
|
||||
const char *aspect_str;
|
||||
|
@ -43,19 +48,19 @@ char game_display_init(const INI_CONFIG_SECTION *display_section, const char *ti
|
|||
cfg.cursor_size = ini_get_int(display_section, "cursor_size", 100)*0.01f;
|
||||
|
||||
screen_pitch = 640;
|
||||
get_sdl_global_context().init_video(cfg, title);
|
||||
screen_buffer = std::make_unique<uint16_t[]>(screen_pitch*480);
|
||||
buffer2nd = std::make_unique<uint16_t[]>(screen_pitch*480);
|
||||
std::fill(screen_buffer.get(), screen_buffer.get()+screen_pitch*480,0);
|
||||
render_target = screen_buffer.get();
|
||||
|
||||
return 1;
|
||||
|
||||
|
||||
return get_sdl_global_context().init_window(cfg, title, [&]{
|
||||
screen_buffer = std::make_unique<uint16_t[]>(screen_pitch*480);
|
||||
buffer2nd = std::make_unique<uint16_t[]>(screen_pitch*480);
|
||||
std::fill(screen_buffer.get(), screen_buffer.get()+screen_pitch*480,0);
|
||||
render_target = screen_buffer.get();
|
||||
return game_thread(args);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void game_display_close(void) {
|
||||
get_sdl_global_context().close_video();
|
||||
}
|
||||
|
||||
uint16_t *GetScreenAdr() {
|
||||
return render_target;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
#include "../config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
@ -19,8 +20,11 @@ void RedirectScreen(uint16_t *newaddr);
|
|||
void RestoreScreen(void);
|
||||
void RedirectScreenBufferSecond(void);
|
||||
|
||||
char game_display_init(const INI_CONFIG_SECTION *display_section, const char *title);
|
||||
void game_display_close(void);
|
||||
|
||||
///Initializes display - in current thread (main thread), starts game thread. Display is closed when thread finishes
|
||||
int game_display_init(const INI_CONFIG_SECTION *display_section,
|
||||
const char *title,
|
||||
int (*game_thread)(va_list), ...);
|
||||
void game_display_update_rect(unsigned short x,unsigned short y,unsigned short xs,unsigned short ys);
|
||||
char game_display_is_quit_requested();
|
||||
void game_display_cancel_quit_request();
|
||||
|
|
|
@ -268,14 +268,12 @@ static Uint32 find_best_rgba_like_format(SDL_Renderer* renderer) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
||||
int SDLContext::init_window(const VideoConfig &config, const char *title, std::function<int()> game_thread) {
|
||||
static Uint32 update_request_event = SDL_RegisterEvents(1);
|
||||
static Uint32 refresh_request_event = SDL_RegisterEvents(1);
|
||||
_update_request_event = update_request_event;
|
||||
_refresh_request = refresh_request_event;
|
||||
|
||||
assert(!_render_thread.joinable());
|
||||
|
||||
|
||||
int width = config.window_width;
|
||||
int height = config.window_height;
|
||||
|
@ -294,142 +292,132 @@ void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
|||
std::exception_ptr e;
|
||||
std::string_view stage;
|
||||
std::string rname;
|
||||
_render_thread = std::jthread([&](std::stop_token stp){
|
||||
bool err = false;
|
||||
try {
|
||||
stage = "window";
|
||||
SDL_Window *window = SDL_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0));
|
||||
int exit_code = 0;
|
||||
try {
|
||||
stage = "window";
|
||||
SDL_Window *window = SDL_CreateWindow(title,
|
||||
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
|
||||
width, height, SDL_WINDOW_RESIZABLE|(_fullscreen_mode?SDL_WINDOW_FULLSCREEN_DESKTOP:0));
|
||||
|
||||
if (!window) {
|
||||
handle_sdl_error("SDL Error create window");
|
||||
}
|
||||
|
||||
_window.reset(window);
|
||||
|
||||
auto composer = config.composer;
|
||||
|
||||
stage = "renderer";
|
||||
|
||||
while (true) {
|
||||
|
||||
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, composer);
|
||||
if (!renderer) {
|
||||
if (config.composer & SDL_RENDERER_SOFTWARE) {
|
||||
handle_sdl_error("Failed to create composer");
|
||||
} else {
|
||||
composer |= SDL_RENDERER_SOFTWARE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
_texture_render_format = find_best_rgba_like_format(renderer);
|
||||
if (_texture_render_format == 0) {
|
||||
if (composer & SDL_RENDERER_SOFTWARE) {
|
||||
throw std::runtime_error("Failed to create composer, failed software fallback");
|
||||
} else {
|
||||
SDL_DestroyRenderer(renderer);
|
||||
composer |= SDL_RENDERER_SOFTWARE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_renderer.reset(renderer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
SDL_RendererInfo rinfo;
|
||||
SDL_GetRendererInfo(_renderer.get(), &rinfo);
|
||||
|
||||
rname = rinfo.name;
|
||||
|
||||
stage = "pixel format";
|
||||
|
||||
_main_pixel_format.reset(SDL_AllocFormat(_texture_render_format));
|
||||
if (!_main_pixel_format) {
|
||||
handle_sdl_error("Failed to create texture format");
|
||||
}
|
||||
|
||||
if (istrcmp(config.scale_quality, "auto") == 0) {
|
||||
if (rinfo.flags & SDL_RENDERER_ACCELERATED) {
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
|
||||
}
|
||||
} else {
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality);
|
||||
}
|
||||
|
||||
|
||||
|
||||
stage = "main render target";
|
||||
|
||||
|
||||
SDL_Texture *texture = SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480);
|
||||
if (!texture) {
|
||||
handle_sdl_error("Failed to create render target");
|
||||
}
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
_texture.reset(texture);
|
||||
|
||||
stage = "secondary render target";
|
||||
|
||||
texture = SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480);
|
||||
if (!texture) {
|
||||
handle_sdl_error("Failed to create second render target");
|
||||
}
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
_texture2.reset(texture);
|
||||
|
||||
stage = "all done";
|
||||
|
||||
_visible_texture = _texture.get();
|
||||
_hidden_texture = _texture2.get();
|
||||
} catch (...) {
|
||||
e = std::current_exception();
|
||||
err = true;
|
||||
if (!window) {
|
||||
handle_sdl_error("SDL Error create window");
|
||||
}
|
||||
done = true;
|
||||
done.notify_all();
|
||||
|
||||
if (!err) {
|
||||
_window.reset(window);
|
||||
|
||||
auto composer = config.composer;
|
||||
|
||||
stage = "renderer";
|
||||
|
||||
while (true) {
|
||||
|
||||
SDL_Renderer *renderer = SDL_CreateRenderer(_window.get(), -1, composer);
|
||||
if (!renderer) {
|
||||
if (config.composer & SDL_RENDERER_SOFTWARE) {
|
||||
handle_sdl_error("Failed to create composer");
|
||||
} else {
|
||||
composer |= SDL_RENDERER_SOFTWARE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
_texture_render_format = find_best_rgba_like_format(renderer);
|
||||
if (_texture_render_format == 0) {
|
||||
if (composer & SDL_RENDERER_SOFTWARE) {
|
||||
throw std::runtime_error("Failed to create composer, failed software fallback");
|
||||
} else {
|
||||
SDL_DestroyRenderer(renderer);
|
||||
composer |= SDL_RENDERER_SOFTWARE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_renderer.reset(renderer);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
SDL_RendererInfo rinfo;
|
||||
SDL_GetRendererInfo(_renderer.get(), &rinfo);
|
||||
|
||||
rname = rinfo.name;
|
||||
|
||||
stage = "pixel format";
|
||||
|
||||
_main_pixel_format.reset(SDL_AllocFormat(_texture_render_format));
|
||||
if (!_main_pixel_format) {
|
||||
handle_sdl_error("Failed to create texture format");
|
||||
}
|
||||
|
||||
if (istrcmp(config.scale_quality, "auto") == 0) {
|
||||
if (rinfo.flags & SDL_RENDERER_ACCELERATED) {
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "best");
|
||||
}
|
||||
} else {
|
||||
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, config.scale_quality);
|
||||
}
|
||||
|
||||
|
||||
|
||||
stage = "main render target";
|
||||
|
||||
|
||||
SDL_Texture *texture = SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480);
|
||||
if (!texture) {
|
||||
handle_sdl_error("Failed to create render target");
|
||||
}
|
||||
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
_texture.reset(texture);
|
||||
|
||||
stage = "secondary render target";
|
||||
|
||||
texture = SDL_CreateTexture(_renderer.get(), _texture_render_format, SDL_TEXTUREACCESS_STREAMING, 640, 480);
|
||||
if (!texture) {
|
||||
handle_sdl_error("Failed to create second render target");
|
||||
}
|
||||
SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
|
||||
_texture2.reset(texture);
|
||||
|
||||
stage = "all done";
|
||||
|
||||
_visible_texture = _texture.get();
|
||||
_hidden_texture = _texture2.get();
|
||||
|
||||
std::stop_source stop_src;
|
||||
|
||||
std::thread main_thrd([&]{
|
||||
try {
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
event_loop(stp);
|
||||
exit_code = game_thread();
|
||||
} catch (...) {
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
crash_sdl_exception();
|
||||
e = std::current_exception();
|
||||
}
|
||||
}
|
||||
_texture.reset();
|
||||
_texture2.reset();
|
||||
_renderer.reset();
|
||||
_window.reset();
|
||||
});
|
||||
stop_src.request_stop();
|
||||
});
|
||||
main_thrd.detach();
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
event_loop(stop_src.get_token());
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
||||
done.wait(false);
|
||||
if (e) {
|
||||
_render_thread.join();
|
||||
try {
|
||||
std::rethrow_exception(e);
|
||||
} catch (...) {
|
||||
std::throw_with_nested(
|
||||
std::runtime_error(std::string("Oops! The application couldn't start properly (problem during SDL initialization). Stage: [")
|
||||
.append(stage).append("]\n\n"
|
||||
"Renderer: ").append(rname).append("\n\n"
|
||||
"This may be caused by outdated or missing graphics or audio drivers."
|
||||
"To fix this, please try the following:\n- Restart your computer and try again\n- "
|
||||
"Make sure your graphics and sound drivers are up to date.")));
|
||||
}
|
||||
} catch (...) {
|
||||
crash_sdl_exception();
|
||||
return -1;
|
||||
}
|
||||
_texture.reset();
|
||||
_texture2.reset();
|
||||
_renderer.reset();
|
||||
_window.reset();
|
||||
|
||||
if (e) {
|
||||
std::rethrow_exception(e);
|
||||
}
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
void SDLContext::init_video(const VideoConfig &config, const char *title) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SDLContext::close_video() {
|
||||
_render_thread.request_stop();
|
||||
_render_thread.join();
|
||||
}
|
||||
|
||||
int SDLContext::check_axis_dir(int &cooldown, int value) {
|
||||
int range = 0x8000-_jcontrol_map.walk_deadzone;
|
||||
|
|
|
@ -98,13 +98,14 @@ public:
|
|||
int freq;
|
||||
};
|
||||
|
||||
int init_window(const VideoConfig &config, const char *title, std::function<int()> game_thread);
|
||||
|
||||
void init_video(const VideoConfig &config, const char *title);
|
||||
|
||||
void set_window_icon(const void *icon_data, size_t icon_size);
|
||||
|
||||
void configure_controller(const JoystickConfig &cfg);
|
||||
|
||||
void close_video();
|
||||
|
||||
AudioInfo init_audio(const AudioConfig &config, SDL_AudioCallback cb, void *cb_ctx);
|
||||
void pause_audio(bool pause);
|
||||
|
@ -272,7 +273,6 @@ protected:
|
|||
Uint32 _update_request_event;
|
||||
Uint32 _refresh_request;
|
||||
|
||||
std::jthread _render_thread;
|
||||
|
||||
|
||||
void event_loop(std::stop_token stp);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue