Merge pull request #5863 from willox/develop

Allow switching between OpenGL and software rendering without restarting
This commit is contained in:
Ted John 2017-07-13 19:07:25 +01:00 committed by GitHub
commit 6a05aa9e33
16 changed files with 94 additions and 61 deletions

View File

@ -7,6 +7,7 @@
- Fix: [#5858] Crash when using custom ride with no colour presets.
- Fix: [#5872] Incorrect OpenGL rendering of masked sprites
- Improved: [#5859] OpenGL rendering performance
- Improved: [#5863] Switching drawing engines no longer requires the application to restart.
0.1.0 (2017-07-12)
------------------------------------------------------------------------

View File

@ -516,44 +516,28 @@ public:
sint32 x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(defaultDisplay);
sint32 y = SDL_WINDOWPOS_UNDEFINED_DISPLAY(defaultDisplay);
// Get saved window size
sint32 width = gConfigGeneral.window_width;
sint32 height = gConfigGeneral.window_height;
if (width <= 0) width = 640;
if (height <= 0) height = 480;
// Create window in window first rather than fullscreen so we have the display the window is on first
uint32 flags = SDL_WINDOW_RESIZABLE;
if (gConfigGeneral.drawing_engine == DRAWING_ENGINE_OPENGL)
{
flags |= SDL_WINDOW_OPENGL;
}
_window = SDL_CreateWindow(OPENRCT2_NAME, x, y, width, height, flags);
if (_window == nullptr)
{
SDLException::Throw("SDL_CreateWindow(...)");
}
SDL_SetWindowMinimumSize(_window, 720, 480);
SetCursorTrap(gConfigGeneral.trap_cursor);
_platformUiContext->SetWindowIcon(_window);
// Initialise the surface, palette and draw buffer
OnResize(width, height);
UpdateFullscreenResolutions();
SetFullscreenMode((FULLSCREEN_MODE)gConfigGeneral.fullscreen_mode);
CreateWindow(x, y);
// Check if steam overlay renderer is loaded into the process
_steamOverlayActive = _platformUiContext->IsSteamOverlayAttached();
TriggerResize();
}
void CloseWindow() override
{
drawing_engine_dispose();
SDL_DestroyWindow(_window);
_window = nullptr;
}
void RecreateWindow() override
{
// Use the position of the current window for the new window
sint32 x, y;
SDL_SetWindowFullscreen(_window, 0);
SDL_GetWindowPosition(_window, &x, &y);
CloseWindow();
CreateWindow(x, y);
}
void ShowMessageBox(const std::string &message) override
@ -646,6 +630,41 @@ public:
private:
void CreateWindow(sint32 x, sint32 y)
{
// Get saved window size
sint32 width = gConfigGeneral.window_width;
sint32 height = gConfigGeneral.window_height;
if (width <= 0) width = 640;
if (height <= 0) height = 480;
// Create window in window first rather than fullscreen so we have the display the window is on first
uint32 flags = SDL_WINDOW_RESIZABLE;
if (gConfigGeneral.drawing_engine == DRAWING_ENGINE_OPENGL)
{
flags |= SDL_WINDOW_OPENGL;
}
_window = SDL_CreateWindow(OPENRCT2_NAME, x, y, width, height, flags);
if (_window == nullptr)
{
SDLException::Throw("SDL_CreateWindow(...)");
}
SDL_SetWindowMinimumSize(_window, 720, 480);
SetCursorTrap(gConfigGeneral.trap_cursor);
_platformUiContext->SetWindowIcon(_window);
// Initialise the surface, palette and draw buffer
drawing_engine_init();
OnResize(width, height);
UpdateFullscreenResolutions();
SetFullscreenMode((FULLSCREEN_MODE)gConfigGeneral.fullscreen_mode);
TriggerResize();
}
void OnResize(sint32 width, sint32 height)
{
// Scale the native window size to the game's canvas size

View File

@ -81,8 +81,6 @@ DrawImageShader::~DrawImageShader()
glDeleteBuffers(1, &_vbo);
glDeleteBuffers(1, &_vboInstances);
glDeleteVertexArrays(1, &_vao);
glBindVertexArray(_vao);
}
void DrawImageShader::GetLocations()

View File

@ -41,8 +41,6 @@ DrawLineShader::~DrawLineShader()
{
glDeleteBuffers(1, &_vbo);
glDeleteVertexArrays(1, &_vao);
glBindVertexArray(_vao);
}
void DrawLineShader::GetLocations()

View File

@ -43,8 +43,6 @@ FillRectShader::~FillRectShader()
{
glDeleteBuffers(1, &_vbo);
glDeleteVertexArrays(1, &_vao);
glBindVertexArray(_vao);
}
void FillRectShader::GetLocations()

View File

@ -121,8 +121,14 @@ static const char * TryLoadAllProcAddresses()
namespace OpenGLState
{
uint16 ActiveTexture = UINT16_MAX;
GLuint CurrentProgram = UINT32_MAX;
uint16 ActiveTexture;
GLuint CurrentProgram;
void Reset()
{
ActiveTexture = UINT16_MAX;
CurrentProgram = UINT32_MAX;
}
}
void OpenGLAPI::SetTexture(uint16 index, GLenum type, GLuint texture)
@ -136,6 +142,8 @@ void OpenGLAPI::SetTexture(uint16 index, GLenum type, GLuint texture)
bool OpenGLAPI::Initialise()
{
OpenGLState::Reset();
#ifdef OPENGL_NO_LINK
const char * failedProcName = TryLoadAllProcAddresses();
if (failedProcName != nullptr)

View File

@ -198,4 +198,6 @@ namespace OpenGLState
{
extern uint16 ActiveTexture;
extern GLuint CurrentProgram;
void Reset();
}

View File

@ -663,6 +663,11 @@ extern "C"
return GetContext()->GetUiContext()->SetFullscreenMode((FULLSCREEN_MODE)mode);
}
void context_recreate_window()
{
GetContext()->GetUiContext()->RecreateWindow();
}
sint32 context_get_resolutions(Resolution * * outResolutions)
{
auto resolutions = GetContext()->GetUiContext()->GetFullscreenResolutions();

View File

@ -127,6 +127,7 @@ extern "C"
bool context_is_input_active();
void context_trigger_resize();
void context_set_fullscreen_mode(sint32 mode);
void context_recreate_window();
sint32 context_get_resolutions(struct Resolution * * outResolutions);
sint32 context_get_width();
sint32 context_get_height();

View File

@ -57,20 +57,18 @@ extern "C"
return _drawingEngineType;
}
bool drawing_engine_requires_restart(sint32 srcEngine, sint32 dstEngine)
bool drawing_engine_requires_new_window(sint32 srcEngine, sint32 dstEngine)
{
// Linux requires a restart. This could be improved in the future by recreating the window,
// https://github.com/OpenRCT2/OpenRCT2/issues/2015
bool requiresRestart = true;
#ifdef _WIN32
if (dstEngine != DRAWING_ENGINE_OPENGL)
if (srcEngine != DRAWING_ENGINE_OPENGL && dstEngine != DRAWING_ENGINE_OPENGL)
{
// Windows is apparently able to switch to hardware rendering on the fly although
// using the same window in an unaccelerated and accelerated context is unsupported by SDL2
requiresRestart = false;
return false;
}
#endif
return requiresRestart;
return true;
}
void drawing_engine_init()
@ -135,13 +133,11 @@ extern "C"
void drawing_engine_resize()
{
if (_drawingEngine == nullptr)
if (_drawingEngine != nullptr)
{
drawing_engine_init();
IUiContext * uiContext = GetContext()->GetUiContext();
_drawingEngine->Resize(uiContext->GetWidth(), uiContext->GetHeight());
}
IUiContext * uiContext = GetContext()->GetUiContext();
_drawingEngine->Resize(uiContext->GetWidth(), uiContext->GetHeight());
}
void drawing_engine_set_palette(const rct_palette_entry * colours)

View File

@ -27,7 +27,7 @@ extern "C"
extern rct_string_id DrawingEngineStringIds[3];
sint32 drawing_engine_get_type();
bool drawing_engine_requires_restart(sint32 srcEngine, sint32 dstEngine);
bool drawing_engine_requires_new_window(sint32 srcEngine, sint32 dstEngine);
void drawing_engine_init();
void drawing_engine_resize();
void drawing_engine_set_palette(const rct_palette_entry * colours);

View File

@ -86,7 +86,7 @@ void platform_draw_require_end();
void platform_free();
void platform_update_palette(const uint8 *colours, sint32 start_index, sint32 num_colours);
void platform_toggle_windowed_mode();
void platform_refresh_video();
void platform_refresh_video(bool recreate_window);
void platform_get_date_utc(rct2_date *out_date);
void platform_get_time_utc(rct2_time *out_time);
void platform_get_date_local(rct2_date *out_date);

View File

@ -152,11 +152,19 @@ void platform_toggle_windowed_mode()
config_save_default();
}
void platform_refresh_video()
void platform_refresh_video(bool recreate_window)
{
drawing_engine_dispose();
drawing_engine_init();
drawing_engine_resize();
if (recreate_window)
{
context_recreate_window();
}
else
{
drawing_engine_dispose();
drawing_engine_init();
drawing_engine_resize();
}
drawing_engine_set_palette(gPalette);
gfx_invalidate_screen();
}

View File

@ -33,6 +33,7 @@ namespace OpenRCT2 { namespace Ui
public:
void CreateWindow() override { }
void CloseWindow() override { }
void RecreateWindow() override { }
void * GetWindow() override { return nullptr; }
sint32 GetWidth() override { return 0; }
sint32 GetHeight() override { return 0; }

View File

@ -94,6 +94,7 @@ namespace OpenRCT2
// Window
virtual void CreateWindow() abstract;
virtual void CloseWindow() abstract;
virtual void RecreateWindow() abstract;
virtual void * GetWindow() abstract;
virtual sint32 GetWidth() abstract;
virtual sint32 GetHeight() abstract;

View File

@ -639,7 +639,7 @@ static void window_options_mouseup(rct_window *w, rct_widgetindex widgetIndex)
break;
case WIDX_MINIMIZE_FOCUS_LOSS:
gConfigGeneral.minimize_fullscreen_focus_loss ^= 1;
platform_refresh_video();
platform_refresh_video(false);
config_save_default();
window_invalidate(w);
break;
@ -1308,11 +1308,8 @@ static void window_options_dropdown(rct_window *w, rct_widgetindex widgetIndex,
sint32 dstEngine = dropdownIndex;
gConfigGeneral.drawing_engine = (uint8)dstEngine;
if (drawing_engine_requires_restart(srcEngine, dstEngine)) {
window_error_open(STR_RESTART_REQUIRED, STR_NONE);
} else {
platform_refresh_video();
}
bool recreate_window = drawing_engine_requires_new_window(srcEngine, dstEngine);
platform_refresh_video(recreate_window);
config_save_default();
window_invalidate(w);
}