ManaPlus
sdl2helper.cpp
Go to the documentation of this file.
1 /*
2  * The ManaPlus Client
3  * Copyright (C) 2013-2019 The ManaPlus Developers
4  * Copyright (C) 2019-2021 Andrei Karas
5  *
6  * This file is part of The ManaPlus Client.
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #ifdef USE_SDL2
23 
24 #include "utils/sdl2helper.h"
25 
26 #include "logger.h"
27 
28 #include "utils/foreach.h"
29 #include "utils/sdl2logger.h"
30 #include "utils/stringutils.h"
31 
32 #include <algorithm>
33 
34 PRAGMA48(GCC diagnostic push)
35 PRAGMA48(GCC diagnostic ignored "-Wshadow")
36 #include <SDL_events.h>
37 #include <SDL_hints.h>
38 #include <SDL_render.h>
39 #include <SDL_syswm.h>
40 PRAGMA48(GCC diagnostic pop)
41 
42 #include "debug.h"
43 
44 bool SDL::getAllVideoModes(StringVect &modeList)
45 {
46  std::set<std::string> modes;
47  const int numDisplays = SDL_GetNumVideoDisplays();
48  for (int display = 0; display < numDisplays; display ++)
49  {
50  const int numModes = SDL_GetNumDisplayModes(display);
51  if (numModes > 0)
52  {
53  for (int f = 0; f < numModes; f ++)
54  {
55  SDL_DisplayMode mode;
56  SDL_GetDisplayMode(display, f, &mode);
57  const int w = mode.w;
58  const int h = mode.h;
59  logger->log("%dx%dx%d", w, h, mode.refresh_rate);
60  modes.insert(strprintf("%dx%d", w, h));
61  }
62  }
63  }
64  FOR_EACH (std::set<std::string>::const_iterator, it, modes)
65  modeList.push_back(*it);
66  return true;
67 }
68 
69 void SDL::SetWindowTitle(SDL_Window *const window, const char *const title)
70 {
71  SDL_SetWindowTitle(window, title);
72 }
73 
74 void SDL::SetWindowIcon(SDL_Window *const window, SDL_Surface *const icon)
75 {
76  SDL_SetWindowIcon(window, icon);
77 }
78 
79 void SDL::grabInput(SDL_Window *const window, const bool grab)
80 {
81  SDL_SetWindowGrab(window, grab ? SDL_TRUE : SDL_FALSE);
82 }
83 
84 void SDL::setGamma(SDL_Window *const window, const float gamma)
85 {
86  SDL_SetWindowBrightness(window, gamma);
87 }
88 
89 void SDL::setVsync(const int val)
90 {
91  SDL_GL_SetSwapInterval(val);
92 }
93 
94 bool SDL::getWindowWMInfo(SDL_Window *const window, SDL_SysWMinfo *const info)
95 {
96  return SDL_GetWindowWMInfo(window, info);
97 }
98 
99 SDL_Thread *SDL::createThread(SDL_ThreadFunction fn,
100  const char *restrict const name,
101  void *restrict const data)
102 {
103  return SDL_CreateThread(fn, name, data);
104 }
105 
106 void *SDL::createGLContext(SDL_Window *const window,
107  const int major,
108  const int minor,
109  const int profile)
110 {
111  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major);
112  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor);
113  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile);
114 // SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
115  SDL_ClearError();
116  void *context = SDL_GL_CreateContext(window);
117  if (context == nullptr)
118  {
119  logger->log("Error to switch to context %d.%d: %s",
120  major,
121  minor,
122  SDL_GetError());
123  }
124  if (context == nullptr && (major > 3 || (major == 3 && minor > 3)))
125  {
126  logger->log("Try fallback to OpenGL 3.3 context");
127  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
128  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
129  SDL_ClearError();
130  context = SDL_GL_CreateContext(window);
131  if (context == nullptr)
132  {
133  logger->log("Error to switch to context 3.3: %s",
134  SDL_GetError());
135  }
136  if (context == nullptr && profile == 0x01)
137  {
138  logger->log("Try fallback to OpenGL 3.3 compatibility context");
139  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
140  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
141  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0x02);
142  SDL_ClearError();
143  context = SDL_GL_CreateContext(window);
144  if (context == nullptr)
145  {
146  logger->log("Error to switch to compatibility context 3.3: %s",
147  SDL_GetError());
148  }
149  }
150  }
151  if (context == nullptr && (major > 3 || (major == 3 && minor > 0)))
152  {
153  logger->log("Error to switch to core context %d.%d: %s",
154  major,
155  minor,
156  SDL_GetError());
157  logger->log("Try fallback to OpenGL 3.0 core context");
158  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
159  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
160  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile);
161  context = SDL_GL_CreateContext(window);
162  if (context == nullptr)
163  {
164  logger->log("Error to switch to core context 3.0: %s",
165  SDL_GetError());
166  }
167  }
168  if (context == nullptr && (major > 2 || (major == 2 && minor > 1)))
169  {
170  logger->log("Try fallback to OpenGL 2.1 compatibility context");
171  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
172  SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
173  SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0x02);
174  context = SDL_GL_CreateContext(window);
175  if (context == nullptr)
176  {
177  logger->log("Error to switch to compatibility context 2.1: %s",
178  SDL_GetError());
179  }
180  }
181  if (context == nullptr)
182  {
183  logger->log("Cant find working context.");
184  }
185  return context;
186 }
187 
188 void SDL::makeCurrentContext(void *const context A_UNUSED)
189 {
190 }
191 
192 void SDL::initLogger()
193 {
195 }
196 
197 void SDL::setLogLevel(const int level)
198 {
200 }
201 
202 void SDL::WaitThread(SDL_Thread *const thread)
203 {
204  if (thread != nullptr)
205  SDL_WaitThread(thread, nullptr);
206 }
207 
208 bool SDL::PollEvent(SDL_Event *event)
209 {
210  SDL_PumpEvents();
211  return SDL_PeepEvents(event,
212  1,
213  SDL_GETEVENT,
214  SDL_FIRSTEVENT,
215  SDL_LASTEVENT) > 0;
216 }
217 
218 void SDL::allowScreenSaver(const bool allow)
219 {
220  if (allow)
221  {
222 #if SDL_VERSION_ATLEAST(2, 0, 2)
223  SDL_SetHintWithPriority(SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
224  "1",
225  SDL_HINT_NORMAL);
226 #endif // SDL_VERSION_ATLEAST(2, 0, 2)
227  SDL_EnableScreenSaver();
228  }
229  else
230  {
231 #if SDL_VERSION_ATLEAST(2, 0, 2)
232  SDL_SetHintWithPriority(SDL_HINT_VIDEO_ALLOW_SCREENSAVER,
233  "0",
234  SDL_HINT_NORMAL);
235 #endif // SDL_VERSION_ATLEAST(2, 0, 2)
236  SDL_DisableScreenSaver();
237  }
238 }
239 
240 void SDL::getRenderers(StringVect &list,
241  const std::string &currentRenderer)
242 {
243  SDL_RendererInfo info;
244  const int num = SDL_GetNumRenderDrivers();
245  for (int f = 0; f < num; f ++)
246  {
247  if (!SDL_GetRenderDriverInfo(f, &info))
248  list.push_back(info.name);
249  }
250  if (!currentRenderer.empty())
251  {
252  bool found(false);
253  FOR_EACH (StringVectCIter, it, list)
254  {
255  if (*it == currentRenderer)
256  {
257  found = true;
258  break;
259  }
260  }
261  if (!found)
262  list.push_back(currentRenderer);
263  }
264  std::sort(list.begin(), list.end());
265 }
266 
267 void SDL::setRendererHint(const std::string &driver)
268 {
269  if (!driver.empty())
270  {
271  SDL_SetHintWithPriority(SDL_HINT_RENDER_DRIVER,
272  driver.c_str(),
273  SDL_HINT_NORMAL);
274  }
275 }
276 
277 #endif // USE_SDL2
void log(const char *const log_text,...)
Definition: logger.cpp:269
#define FOR_EACH(type, iter, array)
Definition: foreach.h:25
#define restrict
Definition: localconsts.h:165
#define PRAGMA48(str)
Definition: localconsts.h:199
#define A_UNUSED
Definition: localconsts.h:160
Logger * logger
Definition: logger.cpp:89
uint32_t data
bool info(InputEvent &event)
Definition: commands.cpp:57
void init()
Definition: playerinfo.cpp:434
SDL_Thread * createThread(int(*fn)(void *), const char *const name, void *const data)
Definition: sdlhelper.cpp:118
void SetWindowTitle(const SDL_Surface *const window, const char *const title)
Definition: sdlhelper.cpp:85
void initLogger()
Definition: sdlhelper.cpp:187
void WaitThread(SDL_Thread *const thread)
Definition: sdlhelper.cpp:195
bool PollEvent(SDL_Event *event)
Definition: sdlhelper.cpp:201
bool getWindowWMInfo(const SDL_Surface *const window, SDL_SysWMinfo *const info)
Definition: sdlhelper.cpp:112
void setLogLevel(const int level)
Definition: sdlhelper.cpp:191
void SetWindowIcon(const SDL_Surface *const window, SDL_Surface *const icon)
Definition: sdlhelper.cpp:91
void makeCurrentContext(void *const context)
Definition: sdlhelper.cpp:182
void grabInput(const SDL_Surface *const window, const bool grab)
Definition: sdlhelper.cpp:97
void setGamma(const SDL_Surface *const window, const float gamma)
Definition: sdlhelper.cpp:102
void setVsync(const int val)
Definition: sdlhelper.cpp:107
bool getAllVideoModes(StringVect &modeList)
Definition: sdlhelper.cpp:44
void allowScreenSaver(const bool allow)
Definition: sdlhelper.cpp:210
void * createGLContext(SDL_Surface *const window, const int major, const int minor, const int profile)
Definition: sdlhelper.cpp:174
#define SDL_Window
Definition: sdlshared.h:60
std::string strprintf(const char *const format,...)
StringVect::const_iterator StringVectCIter
Definition: stringvector.h:31
std::vector< std::string > StringVect
Definition: stringvector.h:29