OpenTTD Source: src/video/sdl2_opengl_v.cpp Source File

OpenTTD Source 15.0-RC2

sdl2_opengl_v.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10/* XXX -- Temporary hack for Windows compile */
11#define WINGDIAPI
12#define APIENTRY
13
14#include "../stdafx.h"
15#include "../openttd.h"
16#include "../gfx_func.h"
17#include "../rev.h"
18#include "../blitter/factory.hpp"
19#include "../network/network.h"
20#include "../thread.h"
21#include "../progress.h"
22#include "../fileio_func.h"
23#include "../framerate_type.h"
24#include "../window_func.h"
25#include "sdl2_opengl_v.h"
26#include <SDL.h>
27#include <mutex>
28#include <condition_variable>
29#include <GL/gl.h>
30#include "../3rdparty/opengl/glext.h"
31#include "opengl.h"
32#ifdef __EMSCRIPTEN__
33# include <emscripten.h>
34# include <emscripten/html5.h>
35#endif
36
37#include "../safeguards.h"
38
39static FVideoDriver_SDL_OpenGL iFVideoDriver_SDL_OpenGL;
40
42 static OGLProc GetOGLProcAddressCallback(const char *proc)
43{
44 return reinterpret_cast<OGLProc>(SDL_GL_GetProcAddress(proc));
45}
46
47 bool VideoDriver_SDL_OpenGL::CreateMainWindow(uint w, uint h, uint flags)
48{
49 return this->VideoDriver_SDL_Base::CreateMainWindow(w, h, flags | SDL_WINDOW_OPENGL);
50}
51
52std::optional<std::string_view> VideoDriver_SDL_OpenGL::Start(const StringList &param)
53{
54 auto error = VideoDriver_SDL_Base::Start(param);
55 if (error) return error;
56
57 error = this->AllocateContext();
58 if (error) {
59 this->Stop();
60 return error;
61 }
62
63 this->driver_info += " (";
64 this->driver_info += OpenGLBackend::Get()->GetDriverName();
65 this->driver_info += ")";
66
67 /* Now we have a OpenGL context, force a client-size-changed event,
68 * so all buffers are allocated correctly. */
69 int w, h;
70 SDL_GetWindowSize(this->sdl_window, &w, &h);
71 this->ClientSizeChanged(w, h, true);
72 /* We should have a valid screen buffer now. If not, something went wrong and we should abort. */
73 if (_screen.dst_ptr == nullptr) {
74 this->Stop();
75 return "Can't get pointer to screen buffer";
76 }
77 /* Main loop expects to start with the buffer unmapped. */
78 this->ReleaseVideoPointer();
79
80 return std::nullopt;
81}
82
83 void VideoDriver_SDL_OpenGL::Stop()
84{
85 this->DestroyContext();
86 this->VideoDriver_SDL_Base::Stop();
87}
88
89void VideoDriver_SDL_OpenGL::DestroyContext()
90{
91 OpenGLBackend::Destroy();
92
93 if (this->gl_context != nullptr) {
94 SDL_GL_DeleteContext(this->gl_context);
95 this->gl_context = nullptr;
96 }
97}
98
99 void VideoDriver_SDL_OpenGL::ToggleVsync(bool vsync)
100{
101 SDL_GL_SetSwapInterval(vsync);
102}
103
104std::optional<std::string_view> VideoDriver_SDL_OpenGL::AllocateContext()
105{
106 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
107 SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
108 SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
109 SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
110 SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
111 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
112
113 if (_debug_driver_level >= 8) {
114 SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
115 }
116
117 this->gl_context = SDL_GL_CreateContext(this->sdl_window);
118 if (this->gl_context == nullptr) return "SDL2: Can't activate GL context";
119
120 ToggleVsync(_video_vsync);
121
122 return OpenGLBackend::Create(&GetOGLProcAddressCallback, this->GetScreenSize());
123}
124
125 void VideoDriver_SDL_OpenGL::PopulateSystemSprites()
126{
127 OpenGLBackend::Get()->PopulateCursorCache();
128}
129
130 void VideoDriver_SDL_OpenGL::ClearSystemSprites()
131{
132 OpenGLBackend::Get()->ClearCursorCache();
133}
134
135 bool VideoDriver_SDL_OpenGL::AllocateBackingStore(int w, int h, bool force)
136{
137 if (this->gl_context == nullptr) return false;
138
139 if (_screen.dst_ptr != nullptr) this->ReleaseVideoPointer();
140
141 w = std::max(w, 64);
142 h = std::max(h, 64);
143 this->dirty_rect = {};
144
145 bool res = OpenGLBackend::Get()->Resize(w, h, force);
146 SDL_GL_SwapWindow(this->sdl_window);
147 _screen.dst_ptr = this->GetVideoPointer();
148
149 CopyPalette(this->local_palette, true);
150
151 return res;
152}
153
154 void *VideoDriver_SDL_OpenGL::GetVideoPointer()
155{
156 if (BlitterFactory::GetCurrentBlitter()->NeedsAnimationBuffer()) {
157 this->anim_buffer = OpenGLBackend::Get()->GetAnimBuffer();
158 }
159 return OpenGLBackend::Get()->GetVideoBuffer();
160}
161
162 void VideoDriver_SDL_OpenGL::ReleaseVideoPointer()
163{
164 if (this->anim_buffer != nullptr) OpenGLBackend::Get()->ReleaseAnimBuffer(this->dirty_rect);
165 OpenGLBackend::Get()->ReleaseVideoBuffer(this->dirty_rect);
166 this->dirty_rect = {};
167 this->anim_buffer = nullptr;
168}
169
170 void VideoDriver_SDL_OpenGL::Paint()
171{
172 PerformanceMeasurer framerate(PFE_VIDEO);
173
174 if (this->local_palette.count_dirty != 0) {
175 Blitter *blitter = BlitterFactory::GetCurrentBlitter();
176
177 /* Always push a changed palette to OpenGL. */
178 OpenGLBackend::Get()->UpdatePalette(this->local_palette.palette, this->local_palette.first_dirty, this->local_palette.count_dirty);
179 if (blitter->UsePaletteAnimation() == Blitter::PaletteAnimation::Blitter) {
180 blitter->PaletteAnimate(this->local_palette);
181 }
182
183 this->local_palette.count_dirty = 0;
184 }
185
186 OpenGLBackend::Get()->Paint();
187 OpenGLBackend::Get()->DrawMouseCursor();
188
189 SDL_GL_SwapWindow(this->sdl_window);
190}
BlitterFactory::GetCurrentBlitter
static Blitter * GetCurrentBlitter()
Get the current active blitter (always set by calling SelectBlitter).
Definition factory.hpp:136
Blitter
How all blitters should look like.
Definition base.hpp:29
Blitter::UsePaletteAnimation
virtual Blitter::PaletteAnimation UsePaletteAnimation()=0
Check if the blitter uses palette animation at all.
Blitter::PaletteAnimate
virtual void PaletteAnimate(const Palette &palette)=0
Called when the 8bpp palette is changed; you should redraw all pixels on the screen that are equal to...
Blitter::PaletteAnimation::Blitter
@ Blitter
The blitter takes care of the palette animation.
FVideoDriver_SDL_OpenGL
The factory for SDL' OpenGL video driver.
Definition sdl2_opengl_v.h:52
OpenGLBackend::Paint
void Paint()
Render video buffer to the screen.
Definition opengl.cpp:1039
OpenGLBackend::GetAnimBuffer
uint8_t * GetAnimBuffer()
Get a pointer to the memory for the separate animation buffer.
Definition opengl.cpp:1170
OpenGLBackend::GetVideoBuffer
void * GetVideoBuffer()
Get a pointer to the memory for the video driver to draw to.
Definition opengl.cpp:1148
OpenGLBackend::Resize
bool Resize(int w, int h, bool force=false)
Change the size of the drawing window and allocate matching resources.
Definition opengl.cpp:913
OpenGLBackend::Create
static std::optional< std::string_view > Create(GetOGLProcAddressProc get_proc, const Dimension &screen_res)
Create and initialize the singleton back-end class.
Definition opengl.cpp:464
OpenGLBackend::UpdatePalette
void UpdatePalette(const Colour *pal, uint first, uint length)
Update the stored palette.
Definition opengl.cpp:1025
OpenGLBackend::ReleaseAnimBuffer
void ReleaseAnimBuffer(const Rect &update_rect)
Update animation buffer texture after the animation buffer was filled.
Definition opengl.cpp:1231
OpenGLBackend::ClearCursorCache
void ClearCursorCache()
Queue a request for cursor cache clear.
Definition opengl.cpp:1135
OpenGLBackend::Get
static OpenGLBackend * Get()
Get singleton instance of this class.
Definition opengl.h:83
OpenGLBackend::DrawMouseCursor
void DrawMouseCursor()
Draw mouse cursor on screen.
Definition opengl.cpp:1071
OpenGLBackend::ReleaseVideoBuffer
void ReleaseVideoBuffer(const Rect &update_rect)
Update video buffer texture after the video buffer was filled.
Definition opengl.cpp:1193
OpenGLBackend::Destroy
static void Destroy()
Free resources and destroy singleton back-end class.
Definition opengl.cpp:477
PerformanceMeasurer
RAII class for measuring simple elements of performance.
Definition framerate_type.h:91
VideoDriver_SDL_Base::Start
std::optional< std::string_view > Start(const StringList &param) override
Start this driver.
Definition sdl2_v.cpp:557
VideoDriver_SDL_Base::GetScreenSize
Dimension GetScreenSize() const override
Get the resolution of the main screen.
Definition sdl2_v.cpp:728
VideoDriver_SDL_Base::local_palette
Palette local_palette
Current palette to use for drawing.
Definition sdl2_v.h:48
VideoDriver_SDL_Base::driver_info
std::string driver_info
Information string about selected driver.
Definition sdl2_v.h:51
VideoDriver_SDL_Base::ClientSizeChanged
void ClientSizeChanged(int w, int h, bool force)
Indicate to the driver the client-side might have changed.
Definition sdl2_v.cpp:123
VideoDriver_SDL_Base::CreateMainWindow
virtual bool CreateMainWindow(uint w, uint h, uint flags=0)
Create the main window.
Definition sdl2_v.cpp:135
VideoDriver_SDL_Base::Stop
void Stop() override
Stop this driver.
Definition sdl2_v.cpp:601
VideoDriver_SDL_Base::dirty_rect
Rect dirty_rect
Rectangle encompassing the dirty area of the video buffer.
Definition sdl2_v.h:50
VideoDriver_SDL_Base::sdl_window
struct SDL_Window * sdl_window
Main SDL window.
Definition sdl2_v.h:47
VideoDriver_SDL_OpenGL::Paint
void Paint() override
Paint the window.
Definition sdl2_opengl_v.cpp:170
VideoDriver_SDL_OpenGL::ReleaseVideoPointer
void ReleaseVideoPointer() override
Hand video buffer back to the painting backend.
Definition sdl2_opengl_v.cpp:162
VideoDriver_SDL_OpenGL::gl_context
void * gl_context
OpenGL context.
Definition sdl2_opengl_v.h:44
VideoDriver_SDL_OpenGL::ToggleVsync
void ToggleVsync(bool vsync) override
Change the vsync setting.
Definition sdl2_opengl_v.cpp:99
VideoDriver_SDL_OpenGL::CreateMainWindow
bool CreateMainWindow(uint w, uint h, uint flags) override
Create the main window.
Definition sdl2_opengl_v.cpp:47
VideoDriver_SDL_OpenGL::GetVideoPointer
void * GetVideoPointer() override
Get a pointer to the video buffer.
Definition sdl2_opengl_v.cpp:154
VideoDriver_SDL_OpenGL::Stop
void Stop() override
Stop this driver.
Definition sdl2_opengl_v.cpp:83
VideoDriver_SDL_OpenGL::ClearSystemSprites
void ClearSystemSprites() override
Clear all cached sprites.
Definition sdl2_opengl_v.cpp:130
VideoDriver_SDL_OpenGL::AllocateBackingStore
bool AllocateBackingStore(int w, int h, bool force=false) override
(Re-)create the backing store.
Definition sdl2_opengl_v.cpp:135
VideoDriver_SDL_OpenGL::Start
std::optional< std::string_view > Start(const StringList &param) override
Start this driver.
Definition sdl2_opengl_v.cpp:52
VideoDriver_SDL_OpenGL::PopulateSystemSprites
void PopulateSystemSprites() override
Populate all sprites in cache.
Definition sdl2_opengl_v.cpp:125
VideoDriver_SDL_OpenGL::anim_buffer
uint8_t * anim_buffer
Animation buffer from OpenGL back-end.
Definition sdl2_opengl_v.h:45
PFE_VIDEO
@ PFE_VIDEO
Speed of painting drawn video buffer.
Definition framerate_type.h:58
opengl.h
OpenGL video driver support.
CopyPalette
bool CopyPalette(Palette &local_palette, bool force_copy)
Copy the current palette if the palette was updated.
Definition palette.cpp:225
GetOGLProcAddressCallback
static OGLProc GetOGLProcAddressCallback(const char *proc)
Platform-specific callback to get an OpenGL function pointer.
Definition sdl2_opengl_v.cpp:42
sdl2_opengl_v.h
OpenGL backend of the SDL2 video driver.
StringList
std::vector< std::string > StringList
Type for a list of strings.
Definition string_type.h:60
Palette::count_dirty
int count_dirty
The number of dirty elements.
Definition gfx_type.h:376
Palette::palette
Colour palette[256]
Current palette. Entry 0 has to be always fully transparent!
Definition gfx_type.h:374
_video_vsync
bool _video_vsync
Whether we should use vsync (only if active video driver supports HW acceleration).
Definition video_driver.cpp:28