summaryrefslogtreecommitdiff
path: root/src/video
diff options
context:
space:
mode:
authorPatric Stout <truebrain@openttd.org>2021-01-17 15:46:38 +0100
committerMichael Lutz <michi@icosahedron.de>2021-02-22 22:16:07 +0100
commita3039403729abb52679984a55e8d46fc527629b2 (patch)
treeeedf474fb33dab4591ad1c7b41f2abd8b64fd75d /src/video
parenta77b202767d98ae0904e6f42efb10a38c4c40c4e (diff)
downloadopenttd-a3039403729abb52679984a55e8d46fc527629b2.tar.xz
Feature: [SDL2] OpenGL support
Diffstat (limited to 'src/video')
-rw-r--r--src/video/CMakeLists.txt6
-rw-r--r--src/video/sdl2_opengl_v.cpp164
-rw-r--r--src/video/sdl2_opengl_v.h52
3 files changed, 222 insertions, 0 deletions
diff --git a/src/video/CMakeLists.txt b/src/video/CMakeLists.txt
index f0f31dac4..77b0b0302 100644
--- a/src/video/CMakeLists.txt
+++ b/src/video/CMakeLists.txt
@@ -26,6 +26,12 @@ if(NOT OPTION_DEDICATED)
)
add_files(
+ sdl2_opengl_v.cpp
+ sdl2_opengl_v.h
+ CONDITION SDL2_FOUND AND OPENGL_FOUND
+ )
+
+ add_files(
win32_v.cpp
win32_v.h
CONDITION WIN32
diff --git a/src/video/sdl2_opengl_v.cpp b/src/video/sdl2_opengl_v.cpp
new file mode 100644
index 000000000..a24d6cf2f
--- /dev/null
+++ b/src/video/sdl2_opengl_v.cpp
@@ -0,0 +1,164 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/** @file sdl2_opengl_v.cpp Implementation of the OpenGL backend for SDL2 video driver. */
+
+/* XXX -- Temporary hack for Windows compile */
+#define WINGDIAPI
+#define APIENTRY
+
+#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_opengl_v.h"
+#include <SDL.h>
+#include <mutex>
+#include <condition_variable>
+#include <GL/gl.h>
+#include "../3rdparty/opengl/glext.h"
+#include "opengl.h"
+#ifdef __EMSCRIPTEN__
+# include <emscripten.h>
+# include <emscripten/html5.h>
+#endif
+
+#include "../safeguards.h"
+
+static FVideoDriver_SDL_OpenGL iFVideoDriver_SDL_OpenGL;
+
+/** Platform-specific callback to get an OpenGL funtion pointer. */
+static OGLProc GetOGLProcAddressCallback(const char *proc)
+{
+ return reinterpret_cast<OGLProc>(SDL_GL_GetProcAddress(proc));
+}
+
+bool VideoDriver_SDL_OpenGL::CreateMainWindow(uint w, uint h, uint flags)
+{
+ return this->VideoDriver_SDL::CreateMainWindow(w, h, SDL_WINDOW_OPENGL);
+}
+
+const char *VideoDriver_SDL_OpenGL::Start(const StringList &param)
+{
+ const char *error = VideoDriver_SDL::Start(param);
+ if (error != nullptr) return error;
+
+ error = this->AllocateContext();
+ if (error != nullptr) {
+ this->Stop();
+ return error;
+ }
+
+ /* Now we have a OpenGL context, force a client-size-changed event,
+ * so all buffers are allocated correctly. */
+ int w, h;
+ SDL_GetWindowSize(this->sdl_window, &w, &h);
+ this->ClientSizeChanged(w, h, true);
+
+ SDL_GL_SetSwapInterval(GetDriverParamBool(param, "vsync") ? 1 : 0);
+ this->draw_threaded = false;
+
+ return nullptr;
+}
+
+void VideoDriver_SDL_OpenGL::Stop()
+{
+ this->DestroyContext();
+ this->VideoDriver_SDL::Stop();
+}
+
+void VideoDriver_SDL_OpenGL::DestroyContext()
+{
+ OpenGLBackend::Destroy();
+
+ if (this->gl_context != nullptr) {
+ SDL_GL_DeleteContext(this->gl_context);
+ this->gl_context = nullptr;
+ }
+}
+
+const char *VideoDriver_SDL_OpenGL::AllocateContext()
+{
+ this->gl_context = SDL_GL_CreateContext(this->sdl_window);
+ if (this->gl_context == nullptr) return "SDL2: Can't active GL context";
+
+ return OpenGLBackend::Create(&GetOGLProcAddressCallback);
+}
+
+void VideoDriver_SDL_OpenGL::ClearSystemSprites()
+{
+ OpenGLBackend::Get()->ClearCursorCache();
+}
+
+bool VideoDriver_SDL_OpenGL::AllocateBackingStore(int w, int h, bool force)
+{
+ if (this->gl_context == nullptr) return false;
+
+ if (_screen.dst_ptr != nullptr) this->ReleaseVideoPointer();
+
+ w = std::max(w, 64);
+ h = std::max(h, 64);
+ MemSetT(&this->dirty_rect, 0);
+
+ bool res = OpenGLBackend::Get()->Resize(w, h, force);
+ _screen.dst_ptr = this->GetVideoPointer();
+
+ _cur_palette.first_dirty = 0;
+ _cur_palette.count_dirty = 256;
+ this->local_palette = _cur_palette;
+
+ return res;
+}
+
+void *VideoDriver_SDL_OpenGL::GetVideoPointer()
+{
+ if (BlitterFactory::GetCurrentBlitter()->NeedsAnimationBuffer()) {
+ this->anim_buffer = OpenGLBackend::Get()->GetAnimBuffer();
+ }
+ return OpenGLBackend::Get()->GetVideoBuffer();
+}
+
+void VideoDriver_SDL_OpenGL::ReleaseVideoPointer()
+{
+ if (this->anim_buffer != nullptr) OpenGLBackend::Get()->ReleaseAnimBuffer(this->dirty_rect);
+ OpenGLBackend::Get()->ReleaseVideoBuffer(this->dirty_rect);
+ MemSetT(&this->dirty_rect, 0);
+ this->anim_buffer = nullptr;
+}
+
+void VideoDriver_SDL_OpenGL::Paint()
+{
+ PerformanceMeasurer framerate(PFE_VIDEO);
+
+ if (_cur_palette.count_dirty != 0) {
+ Blitter *blitter = BlitterFactory::GetCurrentBlitter();
+
+ /* Always push a changed palette to OpenGL. */
+ OpenGLBackend::Get()->UpdatePalette(this->local_palette.palette, this->local_palette.first_dirty, this->local_palette.count_dirty);
+ if (blitter->UsePaletteAnimation() == Blitter::PALETTE_ANIMATION_BLITTER) {
+ blitter->PaletteAnimate(this->local_palette);
+ }
+
+ _cur_palette.count_dirty = 0;
+ }
+
+ OpenGLBackend::Get()->Paint();
+ if (_cursor.in_window) OpenGLBackend::Get()->DrawMouseCursor();
+
+ SDL_GL_SwapWindow(this->sdl_window);
+}
diff --git a/src/video/sdl2_opengl_v.h b/src/video/sdl2_opengl_v.h
new file mode 100644
index 000000000..6aff3b5f5
--- /dev/null
+++ b/src/video/sdl2_opengl_v.h
@@ -0,0 +1,52 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+/** @file sdl2_opengl_v.h OpenGL backend of the SDL2 video driver. */
+
+#include "sdl2_v.h"
+
+/** The OpenGL video driver for windows. */
+class VideoDriver_SDL_OpenGL : public VideoDriver_SDL {
+public:
+ VideoDriver_SDL_OpenGL() : gl_context(nullptr), anim_buffer(nullptr) {}
+
+ const char *Start(const StringList &param) override;
+
+ void Stop() override;
+
+ bool HasEfficient8Bpp() const override { return true; }
+
+ bool UseSystemCursor() override { return true; }
+
+ void ClearSystemSprites() override;
+
+ bool HasAnimBuffer() override { return true; }
+ uint8 *GetAnimBuffer() override { return this->anim_buffer; }
+
+ const char *GetName() const override { return "sdl-opengl"; }
+
+protected:
+ bool AllocateBackingStore(int w, int h, bool force = false) override;
+ void *GetVideoPointer() override;
+ void ReleaseVideoPointer() override;
+ void Paint() override;
+ bool CreateMainWindow(uint w, uint h, uint flags) override;
+
+private:
+ void *gl_context; ///< OpenGL context.
+ uint8 *anim_buffer; ///< Animation buffer from OpenGL back-end.
+
+ const char *AllocateContext();
+ void DestroyContext();
+};
+
+/** The factory for SDL' OpenGL video driver. */
+class FVideoDriver_SDL_OpenGL : public DriverFactoryBase {
+public:
+ FVideoDriver_SDL_OpenGL() : DriverFactoryBase(Driver::DT_VIDEO, 8, "sdl-opengl", "SDL OpenGL Video Driver") {}
+ /* virtual */ Driver *CreateInstance() const override { return new VideoDriver_SDL_OpenGL(); }
+};