diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt index 77b0b03020..3b74e10460 100644 --- a/src/video/CMakeLists.txt +++ b/src/video/CMakeLists.txt @@ -22,6 +22,8 @@ if(NOT OPTION_DEDICATED) add_files( sdl2_v.cpp sdl2_v.h + sdl2_default_v.cpp + sdl2_default_v.h CONDITION SDL2_FOUND ) diff --git a/src/video/sdl2_default_v.cpp b/src/video/sdl2_default_v.cpp new file mode 100644 index 0000000000..b8e769ede0 --- /dev/null +++ b/src/video/sdl2_default_v.cpp @@ -0,0 +1,199 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file sdl2_default_v.cpp Implementation of the default backend for SDL2 video driver. */ + +#include "../stdafx.h" +#include "../openttd.h" +#include "../gfx_func.h" +#include "../rev.h" +#include "../blitter/factory.hpp" +#include "../network/network.h" +#include "../thread.h" +#include "../progress.h" +#include "../core/random_func.hpp" +#include "../core/math_func.hpp" +#include "../core/mem_func.hpp" +#include "../core/geometry_func.hpp" +#include "../fileio_func.h" +#include "../framerate_type.h" +#include "../window_func.h" +#include "sdl2_default_v.h" +#include +#include +#include +#ifdef __EMSCRIPTEN__ +# include +# include +#endif + +#include "../safeguards.h" + +static FVideoDriver_SDL_Default iFVideoDriver_SDL_Default; + +static SDL_Surface *_sdl_surface; +static SDL_Surface *_sdl_rgb_surface; +static SDL_Surface *_sdl_real_surface; +static SDL_Palette *_sdl_palette; + +void VideoDriver_SDL_Default::UpdatePalette() +{ + SDL_Color pal[256]; + + for (int i = 0; i != this->local_palette.count_dirty; i++) { + pal[i].r = this->local_palette.palette[this->local_palette.first_dirty + i].r; + pal[i].g = this->local_palette.palette[this->local_palette.first_dirty + i].g; + pal[i].b = this->local_palette.palette[this->local_palette.first_dirty + i].b; + pal[i].a = 0; + } + + SDL_SetPaletteColors(_sdl_palette, pal, this->local_palette.first_dirty, this->local_palette.count_dirty); + SDL_SetSurfacePalette(_sdl_surface, _sdl_palette); +} + +void VideoDriver_SDL_Default::MakePalette() +{ + if (_sdl_palette == nullptr) { + _sdl_palette = SDL_AllocPalette(256); + if (_sdl_palette == nullptr) usererror("SDL2: Couldn't allocate palette: %s", SDL_GetError()); + } + + _cur_palette.first_dirty = 0; + _cur_palette.count_dirty = 256; + this->local_palette = _cur_palette; + this->UpdatePalette(); + + if (_sdl_surface != _sdl_real_surface) { + /* When using a shadow surface, also set our palette on the real screen. This lets SDL + * allocate as many colors (or approximations) as + * possible, instead of using only the default SDL + * palette. This allows us to get more colors exactly + * right and might allow using better approximations for + * other colors. + * + * Note that colors allocations are tried in-order, so + * this favors colors further up into the palette. Also + * note that if two colors from the same animation + * sequence are approximated using the same color, that + * animation will stop working. + * + * Since changing the system palette causes the colours + * to change right away, and allocations might + * drastically change, we can't use this for animation, + * since that could cause weird coloring between the + * palette change and the blitting below, so we only set + * the real palette during initialisation. + */ + SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette); + } +} + +void VideoDriver_SDL_Default::Paint() +{ + PerformanceMeasurer framerate(PFE_VIDEO); + + if (IsEmptyRect(this->dirty_rect) && _cur_palette.count_dirty == 0) return; + + if (_cur_palette.count_dirty != 0) { + Blitter *blitter = BlitterFactory::GetCurrentBlitter(); + + switch (blitter->UsePaletteAnimation()) { + case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: + this->UpdatePalette(); + break; + + case Blitter::PALETTE_ANIMATION_BLITTER: { + bool need_buf = _screen.dst_ptr == nullptr; + if (need_buf) _screen.dst_ptr = this->GetVideoPointer(); + blitter->PaletteAnimate(this->local_palette); + if (need_buf) { + this->ReleaseVideoPointer(); + _screen.dst_ptr = nullptr; + } + break; + } + + case Blitter::PALETTE_ANIMATION_NONE: + break; + + default: + NOT_REACHED(); + } + _cur_palette.count_dirty = 0; + } + + SDL_Rect r = { this->dirty_rect.left, this->dirty_rect.top, this->dirty_rect.right - this->dirty_rect.left, this->dirty_rect.bottom - this->dirty_rect.top }; + + if (_sdl_surface != _sdl_real_surface) { + SDL_BlitSurface(_sdl_surface, &r, _sdl_real_surface, &r); + } + SDL_UpdateWindowSurfaceRects(this->sdl_window, &r, 1); + + this->dirty_rect = {}; +} + +void VideoDriver_SDL_Default::PaintThread() +{ + /* First tell the main thread we're started */ + std::unique_lock lock(*this->draw_mutex); + this->draw_signal->notify_one(); + + /* Now wait for the first thing to draw! */ + this->draw_signal->wait(*this->draw_mutex); + + while (this->draw_continue) { + /* Then just draw and wait till we stop */ + this->Paint(); + this->draw_signal->wait(lock); + } +} + +bool VideoDriver_SDL_Default::AllocateBackingStore(int w, int h, bool force) +{ + int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); + + _sdl_real_surface = SDL_GetWindowSurface(this->sdl_window); + if (_sdl_real_surface == nullptr) usererror("SDL2: Couldn't get window surface: %s", SDL_GetError()); + + if (!force && w == _sdl_real_surface->w && h == _sdl_real_surface->h) return false; + + /* Free any previously allocated rgb surface. */ + if (_sdl_rgb_surface != nullptr) { + SDL_FreeSurface(_sdl_rgb_surface); + _sdl_rgb_surface = nullptr; + } + + if (bpp == 8) { + _sdl_rgb_surface = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0); + if (_sdl_rgb_surface == nullptr) usererror("SDL2: Couldn't allocate shadow surface: %s", SDL_GetError()); + + _sdl_surface = _sdl_rgb_surface; + } else { + _sdl_surface = _sdl_real_surface; + } + + /* X11 doesn't appreciate it if we invalidate areas outside the window + * if shared memory is enabled (read: it crashes). So, as we might have + * gotten smaller, reset our dirty rects. GameSizeChanged() a bit lower + * will mark the whole screen dirty again anyway, but this time with the + * new dimensions. */ + this->dirty_rect = {}; + + _screen.width = _sdl_surface->w; + _screen.height = _sdl_surface->h; + _screen.pitch = _sdl_surface->pitch / (bpp / 8); + _screen.dst_ptr = this->GetVideoPointer(); + + this->MakePalette(); + + return true; +} + +void *VideoDriver_SDL_Default::GetVideoPointer() +{ + return _sdl_surface->pixels; +} diff --git a/src/video/sdl2_default_v.h b/src/video/sdl2_default_v.h new file mode 100644 index 0000000000..1b67be5d39 --- /dev/null +++ b/src/video/sdl2_default_v.h @@ -0,0 +1,40 @@ +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file sdl2_default_v.h Default backend of the SDL2 video driver. */ + +#ifndef VIDEO_SDL2_DEFAULT_H +#define VIDEO_SDL2_DEFAULT_H + +#include "sdl2_v.h" + +/** The SDL video driver using default SDL backend. */ +class VideoDriver_SDL_Default : public VideoDriver_SDL_Base { +public: + const char *GetName() const override { return "sdl"; } + +protected: + bool AllocateBackingStore(int w, int h, bool force = false) override; + void *GetVideoPointer() override; + void Paint() override; + void PaintThread() override; + + void ReleaseVideoPointer() override {} + +private: + void UpdatePalette(); + void MakePalette(); +}; + +/** Factory for the SDL video driver. */ +class FVideoDriver_SDL_Default : public DriverFactoryBase { +public: + FVideoDriver_SDL_Default() : DriverFactoryBase(Driver::DT_VIDEO, 5, "sdl", "SDL Video Driver") {} + Driver *CreateInstance() const override { return new VideoDriver_SDL_Default(); } +}; + +#endif /* VIDEO_SDL2_DEFAULT_H */ diff --git a/src/video/sdl2_opengl_v.cpp b/src/video/sdl2_opengl_v.cpp index a24d6cf2f7..9c9a9c6fad 100644 --- a/src/video/sdl2_opengl_v.cpp +++ b/src/video/sdl2_opengl_v.cpp @@ -50,12 +50,12 @@ static OGLProc GetOGLProcAddressCallback(const char *proc) bool VideoDriver_SDL_OpenGL::CreateMainWindow(uint w, uint h, uint flags) { - return this->VideoDriver_SDL::CreateMainWindow(w, h, SDL_WINDOW_OPENGL); + return this->VideoDriver_SDL_Base::CreateMainWindow(w, h, SDL_WINDOW_OPENGL); } const char *VideoDriver_SDL_OpenGL::Start(const StringList ¶m) { - const char *error = VideoDriver_SDL::Start(param); + const char *error = VideoDriver_SDL_Base::Start(param); if (error != nullptr) return error; error = this->AllocateContext(); @@ -79,7 +79,7 @@ const char *VideoDriver_SDL_OpenGL::Start(const StringList ¶m) void VideoDriver_SDL_OpenGL::Stop() { this->DestroyContext(); - this->VideoDriver_SDL::Stop(); + this->VideoDriver_SDL_Base::Stop(); } void VideoDriver_SDL_OpenGL::DestroyContext() diff --git a/src/video/sdl2_opengl_v.h b/src/video/sdl2_opengl_v.h index 6aff3b5f54..a59233db6d 100644 --- a/src/video/sdl2_opengl_v.h +++ b/src/video/sdl2_opengl_v.h @@ -10,7 +10,7 @@ #include "sdl2_v.h" /** The OpenGL video driver for windows. */ -class VideoDriver_SDL_OpenGL : public VideoDriver_SDL { +class VideoDriver_SDL_OpenGL : public VideoDriver_SDL_Base { public: VideoDriver_SDL_OpenGL() : gl_context(nullptr), anim_buffer(nullptr) {} @@ -36,6 +36,8 @@ protected: void Paint() override; bool CreateMainWindow(uint w, uint h, uint flags) override; + void PaintThread() override {} + private: void *gl_context; ///< OpenGL context. uint8 *anim_buffer; ///< Animation buffer from OpenGL back-end. diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 86774fc56e..818389b800 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -32,77 +32,18 @@ #include "../safeguards.h" -static FVideoDriver_SDL iFVideoDriver_SDL; - -static SDL_Surface *_sdl_surface; -static SDL_Surface *_sdl_rgb_surface; -static SDL_Surface *_sdl_real_surface; -static SDL_Palette *_sdl_palette; - #ifdef __EMSCRIPTEN__ /** Whether we just had a window-enter event. */ static bool _cursor_new_in_window = false; #endif -void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height) +void VideoDriver_SDL_Base::MakeDirty(int left, int top, int width, int height) { Rect r = {left, top, left + width, top + height}; this->dirty_rect = BoundingRect(this->dirty_rect, r); } -void VideoDriver_SDL::UpdatePalette() -{ - SDL_Color pal[256]; - - for (int i = 0; i != this->local_palette.count_dirty; i++) { - pal[i].r = this->local_palette.palette[this->local_palette.first_dirty + i].r; - pal[i].g = this->local_palette.palette[this->local_palette.first_dirty + i].g; - pal[i].b = this->local_palette.palette[this->local_palette.first_dirty + i].b; - pal[i].a = 0; - } - - SDL_SetPaletteColors(_sdl_palette, pal, this->local_palette.first_dirty, this->local_palette.count_dirty); - SDL_SetSurfacePalette(_sdl_surface, _sdl_palette); -} - -void VideoDriver_SDL::MakePalette() -{ - if (_sdl_palette == nullptr) { - _sdl_palette = SDL_AllocPalette(256); - if (_sdl_palette == nullptr) usererror("SDL2: Couldn't allocate palette: %s", SDL_GetError()); - } - - _cur_palette.first_dirty = 0; - _cur_palette.count_dirty = 256; - this->local_palette = _cur_palette; - this->UpdatePalette(); - - if (_sdl_surface != _sdl_real_surface) { - /* When using a shadow surface, also set our palette on the real screen. This lets SDL - * allocate as many colors (or approximations) as - * possible, instead of using only the default SDL - * palette. This allows us to get more colors exactly - * right and might allow using better approximations for - * other colors. - * - * Note that colors allocations are tried in-order, so - * this favors colors further up into the palette. Also - * note that if two colors from the same animation - * sequence are approximated using the same color, that - * animation will stop working. - * - * Since changing the system palette causes the colours - * to change right away, and allocations might - * drastically change, we can't use this for animation, - * since that could cause weird coloring between the - * palette change and the blitting below, so we only set - * the real palette during initialisation. - */ - SDL_SetSurfacePalette(_sdl_real_surface, _sdl_palette); - } -} - -void VideoDriver_SDL::CheckPaletteAnim() +void VideoDriver_SDL_Base::CheckPaletteAnim() { if (_cur_palette.count_dirty == 0) return; @@ -110,67 +51,7 @@ void VideoDriver_SDL::CheckPaletteAnim() this->MakeDirty(0, 0, _screen.width, _screen.height); } -void VideoDriver_SDL::Paint() -{ - PerformanceMeasurer framerate(PFE_VIDEO); - - if (IsEmptyRect(this->dirty_rect) && _cur_palette.count_dirty == 0) return; - - if (_cur_palette.count_dirty != 0) { - Blitter *blitter = BlitterFactory::GetCurrentBlitter(); - - switch (blitter->UsePaletteAnimation()) { - case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND: - this->UpdatePalette(); - break; - - case Blitter::PALETTE_ANIMATION_BLITTER: { - bool need_buf = _screen.dst_ptr == nullptr; - if (need_buf) _screen.dst_ptr = this->GetVideoPointer(); - blitter->PaletteAnimate(this->local_palette); - if (need_buf) { - this->ReleaseVideoPointer(); - _screen.dst_ptr = nullptr; - } - break; - } - - case Blitter::PALETTE_ANIMATION_NONE: - break; - - default: - NOT_REACHED(); - } - _cur_palette.count_dirty = 0; - } - - SDL_Rect r = { this->dirty_rect.left, this->dirty_rect.top, this->dirty_rect.right - this->dirty_rect.left, this->dirty_rect.bottom - this->dirty_rect.top }; - - if (_sdl_surface != _sdl_real_surface) { - SDL_BlitSurface(_sdl_surface, &r, _sdl_real_surface, &r); - } - SDL_UpdateWindowSurfaceRects(this->sdl_window, &r, 1); - - this->dirty_rect = {}; -} - -void VideoDriver_SDL::PaintThread() -{ - /* First tell the main thread we're started */ - std::unique_lock lock(*this->draw_mutex); - this->draw_signal->notify_one(); - - /* Now wait for the first thing to draw! */ - this->draw_signal->wait(*this->draw_mutex); - - while (this->draw_continue) { - /* Then just draw and wait till we stop */ - this->Paint(); - this->draw_signal->wait(lock); - } -} - -/* static */ void VideoDriver_SDL::PaintThreadThunk(VideoDriver_SDL *drv) +/* static */ void VideoDriver_SDL_Base::PaintThreadThunk(VideoDriver_SDL_Base *drv) { drv->PaintThread(); } @@ -253,7 +134,7 @@ static uint FindStartupDisplay(uint startup_display) return 0; } -void VideoDriver_SDL::ClientSizeChanged(int w, int h, bool force) +void VideoDriver_SDL_Base::ClientSizeChanged(int w, int h, bool force) { /* Allocate backing store of the new size. */ if (this->AllocateBackingStore(w, h, force)) { @@ -268,7 +149,7 @@ void VideoDriver_SDL::ClientSizeChanged(int w, int h, bool force) } } -bool VideoDriver_SDL::CreateMainWindow(uint w, uint h, uint flags) +bool VideoDriver_SDL_Base::CreateMainWindow(uint w, uint h, uint flags) { if (this->sdl_window != nullptr) return true; @@ -315,7 +196,7 @@ bool VideoDriver_SDL::CreateMainWindow(uint w, uint h, uint flags) return true; } -bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) +bool VideoDriver_SDL_Base::CreateMainSurface(uint w, uint h, bool resize) { GetAvailableVideoMode(&w, &h); DEBUG(driver, 1, "SDL2: using mode %ux%u", w, h); @@ -332,53 +213,7 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) return true; } -bool VideoDriver_SDL::AllocateBackingStore(int w, int h, bool force) -{ - int bpp = BlitterFactory::GetCurrentBlitter()->GetScreenDepth(); - - _sdl_real_surface = SDL_GetWindowSurface(this->sdl_window); - if (_sdl_real_surface == nullptr) usererror("SDL2: Couldn't get window surface: %s", SDL_GetError()); - - if (!force && w == _sdl_real_surface->w && h == _sdl_real_surface->h) return false; - - /* Free any previously allocated rgb surface. */ - if (_sdl_rgb_surface != nullptr) { - SDL_FreeSurface(_sdl_rgb_surface); - _sdl_rgb_surface = nullptr; - } - - if (bpp == 8) { - _sdl_rgb_surface = SDL_CreateRGBSurface(0, w, h, 8, 0, 0, 0, 0); - if (_sdl_rgb_surface == nullptr) usererror("SDL2: Couldn't allocate shadow surface: %s", SDL_GetError()); - - _sdl_surface = _sdl_rgb_surface; - } else { - _sdl_surface = _sdl_real_surface; - } - - /* X11 doesn't appreciate it if we invalidate areas outside the window - * if shared memory is enabled (read: it crashes). So, as we might have - * gotten smaller, reset our dirty rects. GameSizeChanged() a bit lower - * will mark the whole screen dirty again anyway, but this time with the - * new dimensions. */ - this->dirty_rect = {}; - - _screen.width = _sdl_surface->w; - _screen.height = _sdl_surface->h; - _screen.pitch = _sdl_surface->pitch / (bpp / 8); - _screen.dst_ptr = this->GetVideoPointer(); - - this->MakePalette(); - - return true; -} - -void *VideoDriver_SDL::GetVideoPointer() -{ - return _sdl_surface->pixels; -} - -bool VideoDriver_SDL::ClaimMousePointer() +bool VideoDriver_SDL_Base::ClaimMousePointer() { SDL_ShowCursor(0); #ifdef __EMSCRIPTEN__ @@ -390,7 +225,7 @@ bool VideoDriver_SDL::ClaimMousePointer() /** * This is called to indicate that an edit box has gained focus, text input mode should be enabled. */ -void VideoDriver_SDL::EditBoxGainedFocus() +void VideoDriver_SDL_Base::EditBoxGainedFocus() { if (!this->edit_box_focused) { SDL_StartTextInput(); @@ -401,7 +236,7 @@ void VideoDriver_SDL::EditBoxGainedFocus() /** * This is called to indicate that an edit box has lost focus, text input mode should be disabled. */ -void VideoDriver_SDL::EditBoxLostFocus() +void VideoDriver_SDL_Base::EditBoxLostFocus() { if (this->edit_box_focused) { SDL_StopTextInput(); @@ -535,7 +370,7 @@ static uint ConvertSdlKeycodeIntoMy(SDL_Keycode kc) return key; } -int VideoDriver_SDL::PollEvent() +int VideoDriver_SDL_Base::PollEvent() { SDL_Event ev; @@ -699,7 +534,7 @@ static const char *InitializeSDL() return nullptr; } -const char *VideoDriver_SDL::Initialize() +const char *VideoDriver_SDL_Base::Initialize() { this->UpdateAutoResolution(); @@ -712,7 +547,7 @@ const char *VideoDriver_SDL::Initialize() return nullptr; } -const char *VideoDriver_SDL::Start(const StringList &parm) +const char *VideoDriver_SDL_Base::Start(const StringList &parm) { if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 0) return "Only real blitters supported"; @@ -749,7 +584,7 @@ const char *VideoDriver_SDL::Start(const StringList &parm) return nullptr; } -void VideoDriver_SDL::Stop() +void VideoDriver_SDL_Base::Stop() { SDL_QuitSubSystem(SDL_INIT_VIDEO); if (SDL_WasInit(SDL_INIT_EVERYTHING) == 0) { @@ -757,7 +592,7 @@ void VideoDriver_SDL::Stop() } } -void VideoDriver_SDL::InputLoop() +void VideoDriver_SDL_Base::InputLoop() { uint32 mod = SDL_GetModState(); const Uint8 *keys = SDL_GetKeyboardState(NULL); @@ -790,7 +625,7 @@ void VideoDriver_SDL::InputLoop() if (old_ctrl_pressed != _ctrl_pressed) HandleCtrlChanged(); } -void VideoDriver_SDL::LoopOnce() +void VideoDriver_SDL_Base::LoopOnce() { InteractiveRandom(); // randomness @@ -824,7 +659,7 @@ void VideoDriver_SDL::LoopOnce() #endif } -void VideoDriver_SDL::MainLoop() +void VideoDriver_SDL_Base::MainLoop() { if (this->draw_threaded) { /* Initialise the mutex first, because that's the thing we *need* @@ -837,7 +672,7 @@ void VideoDriver_SDL::MainLoop() this->draw_signal = new std::condition_variable_any(); this->draw_continue = true; - this->draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL::PaintThreadThunk, this); + this->draw_threaded = StartNewThread(&draw_thread, "ottd:draw-sdl", &VideoDriver_SDL_Base::PaintThreadThunk, this); /* Free the mutex if we won't be able to use it. */ if (!this->draw_threaded) { @@ -868,7 +703,7 @@ void VideoDriver_SDL::MainLoop() #endif } -void VideoDriver_SDL::MainLoopCleanup() +void VideoDriver_SDL_Base::MainLoopCleanup() { if (this->draw_mutex != nullptr) { this->draw_continue = false; @@ -896,7 +731,7 @@ void VideoDriver_SDL::MainLoopCleanup() #endif } -bool VideoDriver_SDL::ChangeResolution(int w, int h) +bool VideoDriver_SDL_Base::ChangeResolution(int w, int h) { std::unique_lock lock; if (this->draw_mutex != nullptr) lock = std::unique_lock(*this->draw_mutex); @@ -904,7 +739,7 @@ bool VideoDriver_SDL::ChangeResolution(int w, int h) return CreateMainSurface(w, h, true); } -bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen) +bool VideoDriver_SDL_Base::ToggleFullscreen(bool fullscreen) { std::unique_lock lock; if (this->draw_mutex != nullptr) lock = std::unique_lock(*this->draw_mutex); @@ -937,7 +772,7 @@ bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen) return ret == 0; } -bool VideoDriver_SDL::AfterBlitterChange() +bool VideoDriver_SDL_Base::AfterBlitterChange() { assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0); int w, h; @@ -945,17 +780,17 @@ bool VideoDriver_SDL::AfterBlitterChange() return CreateMainSurface(w, h, false); } -void VideoDriver_SDL::AcquireBlitterLock() +void VideoDriver_SDL_Base::AcquireBlitterLock() { if (this->draw_mutex != nullptr) this->draw_mutex->lock(); } -void VideoDriver_SDL::ReleaseBlitterLock() +void VideoDriver_SDL_Base::ReleaseBlitterLock() { if (this->draw_mutex != nullptr) this->draw_mutex->unlock(); } -Dimension VideoDriver_SDL::GetScreenSize() const +Dimension VideoDriver_SDL_Base::GetScreenSize() const { SDL_DisplayMode mode; if (SDL_GetCurrentDisplayMode(this->startup_display, &mode) != 0) return VideoDriver::GetScreenSize(); @@ -963,7 +798,7 @@ Dimension VideoDriver_SDL::GetScreenSize() const return { static_cast(mode.w), static_cast(mode.h) }; } -bool VideoDriver_SDL::LockVideoBuffer() +bool VideoDriver_SDL_Base::LockVideoBuffer() { if (this->buffer_locked) return false; this->buffer_locked = true; @@ -976,7 +811,7 @@ bool VideoDriver_SDL::LockVideoBuffer() return true; } -void VideoDriver_SDL::UnlockVideoBuffer() +void VideoDriver_SDL_Base::UnlockVideoBuffer() { if (_screen.dst_ptr != nullptr) { /* Hand video buffer back to the drawing backend. */ diff --git a/src/video/sdl2_v.h b/src/video/sdl2_v.h index cfd82d1512..7042bf270c 100644 --- a/src/video/sdl2_v.h +++ b/src/video/sdl2_v.h @@ -15,9 +15,9 @@ #include "video_driver.hpp" /** The SDL video driver. */ -class VideoDriver_SDL : public VideoDriver { +class VideoDriver_SDL_Base : public VideoDriver { public: - VideoDriver_SDL() : sdl_window(nullptr) {} + VideoDriver_SDL_Base() : sdl_window(nullptr) {} const char *Start(const StringList ¶m) override; @@ -59,19 +59,17 @@ protected: void InputLoop() override; bool LockVideoBuffer() override; void UnlockVideoBuffer() override; - void Paint() override; - void PaintThread() override; void CheckPaletteAnim() override; /** Indicate to the driver the client-side might have changed. */ void ClientSizeChanged(int w, int h, bool force); /** (Re-)create the backing store. */ - virtual bool AllocateBackingStore(int w, int h, bool force = false); + virtual bool AllocateBackingStore(int w, int h, bool force = false) = 0; /** Get a pointer to the video buffer. */ - virtual void *GetVideoPointer(); + virtual void *GetVideoPointer() = 0; /** Hand video buffer back to the painting backend. */ - virtual void ReleaseVideoPointer() {} + virtual void ReleaseVideoPointer() = 0; /** Create the main window. */ virtual bool CreateMainWindow(uint w, uint h, uint flags = 0); @@ -81,13 +79,10 @@ private: void MainLoopCleanup(); bool CreateMainSurface(uint w, uint h, bool resize); const char *Initialize(); - bool CreateMainWindow(uint w, uint h); - void UpdatePalette(); - void MakePalette(); #ifdef __EMSCRIPTEN__ /* Convert a constant pointer back to a non-constant pointer to a member function. */ - static void EmscriptenLoop(void *self) { ((VideoDriver_SDL *)self)->LoopOnce(); } + static void EmscriptenLoop(void *self) { ((VideoDriver_SDL_Base *)self)->LoopOnce(); } #endif /** @@ -99,14 +94,7 @@ private: std::thread draw_thread; std::unique_lock draw_lock; - static void PaintThreadThunk(VideoDriver_SDL *drv); -}; - -/** Factory for the SDL video driver. */ -class FVideoDriver_SDL : public DriverFactoryBase { -public: - FVideoDriver_SDL() : DriverFactoryBase(Driver::DT_VIDEO, 5, "sdl", "SDL Video Driver") {} - Driver *CreateInstance() const override { return new VideoDriver_SDL(); } + static void PaintThreadThunk(VideoDriver_SDL_Base *drv); }; #endif /* VIDEO_SDL_H */