summaryrefslogtreecommitdiff
path: root/src/video/win32_v.cpp
diff options
context:
space:
mode:
authorMichael Lutz <michi@icosahedron.de>2021-01-16 16:43:04 +0100
committerMichael Lutz <michi@icosahedron.de>2021-02-22 22:16:07 +0100
commitef478ade649add1ab1706370ff53bcb0c32798d1 (patch)
treebf39b20030319377edec1b654fe4e8c7ba4594a3 /src/video/win32_v.cpp
parentaf4d32357cc4cea6878c61c366378477e62915d0 (diff)
downloadopenttd-ef478ade649add1ab1706370ff53bcb0c32798d1.tar.xz
Add: [Win32] Video driver that uses OpenGL to transfer the video buffer to the screen.
Diffstat (limited to 'src/video/win32_v.cpp')
-rw-r--r--src/video/win32_v.cpp153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/video/win32_v.cpp b/src/video/win32_v.cpp
index 7ebac069d..c97dccf44 100644
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -1114,6 +1114,7 @@ float VideoDriver_Win32Base::GetDPIScale()
bool VideoDriver_Win32Base::LockVideoBuffer()
{
if (_draw_threaded) this->draw_lock.lock();
+ _screen.dst_ptr = _wnd.buffer_bits;
return true;
}
@@ -1319,3 +1320,155 @@ void VideoDriver_Win32GDI::PaintThread()
return _fooctr++;
}
#endif
+
+#ifdef WITH_OPENGL
+
+#include <GL/gl.h>
+#include "../3rdparty/opengl/glext.h"
+#include "opengl.h"
+
+#ifndef PFD_SUPPORT_COMPOSITION
+# define PFD_SUPPORT_COMPOSITION 0x00008000
+#endif
+
+static FVideoDriver_Win32OpenGL iFVideoDriver_Win32OpenGL;
+
+const char *VideoDriver_Win32OpenGL::Start(const StringList &param)
+{
+ if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 32) return "Only 32bpp blitters supported";
+
+ Dimension old_res = _cur_resolution; // Save current screen resolution in case of errors, as MakeWindow invalidates it.
+
+ this->Initialize();
+ this->MakeWindow(_fullscreen);
+
+ /* Create and initialize OpenGL context. */
+ const char *err = this->AllocateContext();
+ if (err != nullptr) {
+ this->Stop();
+ _cur_resolution = old_res;
+ return err;
+ }
+
+ this->ClientSizeChanged(_wnd.width, _wnd.height);
+
+ _draw_threaded = false;
+ MarkWholeScreenDirty();
+
+ return nullptr;
+}
+
+void VideoDriver_Win32OpenGL::Stop()
+{
+ this->DestroyContext();
+ this->VideoDriver_Win32Base::Stop();
+}
+
+void VideoDriver_Win32OpenGL::DestroyContext()
+{
+ OpenGLBackend::Destroy();
+
+ wglMakeCurrent(nullptr, nullptr);
+ if (this->gl_rc != nullptr) {
+ wglDeleteContext(this->gl_rc);
+ this->gl_rc = nullptr;
+ }
+ if (this->dc != nullptr) {
+ ReleaseDC(this->main_wnd, this->dc);
+ this->dc = nullptr;
+ }
+}
+
+const char *VideoDriver_Win32OpenGL::AllocateContext()
+{
+ PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of this struct.
+ 1, // Version of this struct.
+ PFD_DRAW_TO_WINDOW | // Require window support.
+ PFD_SUPPORT_OPENGL | // Require OpenGL support.
+ PFD_DOUBLEBUFFER | // Use double buffering.
+ PFD_DEPTH_DONTCARE,
+ PFD_TYPE_RGBA, // Request RGBA format.
+ 24, // 24 bpp (excluding alpha).
+ 0, 0, 0, 0, 0, 0, 0, 0, // Colour bits and shift ignored.
+ 0, 0, 0, 0, 0, // No accumulation buffer.
+ 0, 0, // No depth/stencil buffer.
+ 0, // No aux buffers.
+ PFD_MAIN_PLANE, // Main layer.
+ 0, 0, 0, 0 // Ignored/reserved.
+ };
+
+ if (IsWindowsVistaOrGreater()) pfd.dwFlags |= PFD_SUPPORT_COMPOSITION; // Make OpenTTD compatible with Aero.
+
+ this->dc = GetDC(this->main_wnd);
+
+ /* Choose a suitable pixel format. */
+ int format = ChoosePixelFormat(this->dc, &pfd);
+ if (format == 0) return "No suitable pixel format found";
+ if (!SetPixelFormat(this->dc, format, &pfd)) return "Can't set pixel format";
+
+ /* Create OpenGL device context. */
+ this->gl_rc = wglCreateContext(this->dc);
+ if (this->gl_rc == 0) return "Can't create OpenGL context";
+ if (!wglMakeCurrent(this->dc, this->gl_rc)) return "Can't active GL context";
+
+ return OpenGLBackend::Create();
+}
+
+bool VideoDriver_Win32OpenGL::ToggleFullscreen(bool full_screen)
+{
+ this->DestroyContext();
+ bool res = this->VideoDriver_Win32Base::ToggleFullscreen(full_screen);
+ res &= this->AllocateContext() == nullptr;
+ this->ClientSizeChanged(_wnd.width, _wnd.height);
+ return res;
+}
+
+bool VideoDriver_Win32OpenGL::AfterBlitterChange()
+{
+ assert(BlitterFactory::GetCurrentBlitter()->GetScreenDepth() != 0);
+ this->ClientSizeChanged(_wnd.width, _wnd.height);
+ return true;
+}
+
+bool VideoDriver_Win32OpenGL::AllocateBackingStore(int w, int h, bool force)
+{
+ if (!force && w == _screen.width && h == _screen.height) return false;
+
+ _wnd.width = w = std::max(w, 64);
+ _wnd.height = h = std::max(h, 64);
+
+ if (this->gl_rc == nullptr) return false;
+
+ bool res = OpenGLBackend::Get()->Resize(w, h);
+ _wnd.buffer_bits = OpenGLBackend::Get()->GetVideoBuffer();
+ return res;
+}
+
+void VideoDriver_Win32OpenGL::Paint()
+{
+ PerformanceMeasurer framerate(PFE_VIDEO);
+
+ if (_cur_palette.count_dirty != 0) {
+ Blitter *blitter = BlitterFactory::GetCurrentBlitter();
+
+ switch (blitter->UsePaletteAnimation()) {
+ case Blitter::PALETTE_ANIMATION_BLITTER:
+ blitter->PaletteAnimate(_local_palette);
+ break;
+
+ case Blitter::PALETTE_ANIMATION_VIDEO_BACKEND:
+ case Blitter::PALETTE_ANIMATION_NONE:
+ break;
+
+ default:
+ NOT_REACHED();
+ }
+ _cur_palette.count_dirty = 0;
+ }
+
+ OpenGLBackend::Get()->Paint();
+ SwapBuffers(this->dc);
+}
+
+#endif /* WITH_OPENGL */