FIFE  be64c707dea6b3250bd4355bf5c825d25920087d
devicecaps.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  * Copyright (C) 2005-2019 by the FIFE team *
3  * http://www.fifengine.net *
4  * This file is part of FIFE. *
5  * *
6  * FIFE is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU Lesser General Public *
8  * License as published by the Free Software Foundation; either *
9  * version 2.1 of the License, or (at your option) any later version. *
10  * *
11  * This library is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14  * Lesser General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU Lesser General Public *
17  * License along with this library; if not, write to the *
18  * Free Software Foundation, Inc., *
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
20  ***************************************************************************/
21 
22 // Standard C++ library includes
23 #include <iostream>
24 #include <algorithm>
25 
26 // 3rd party library includes
27 #include <SDL.h>
28 #include <SDL_video.h>
29 
30 // FIFE includes
31 // These includes are split up in two parts, separated by one empty line
32 // First block: files included from the FIFE root src directory
33 // Second block: files included from the same folder
34 #include "util/base/exception.h"
35 
36 #include "devicecaps.h"
37 
38 namespace FIFE {
39 
41  m_width(0), m_height(0), m_bpp(0), m_refreshRate(0), m_SDLFlags(0),
42  m_format(0), m_display(0), m_renderDriver(""), m_renderDriverIndex(-1) {
43  }
44 
45  ScreenMode::ScreenMode(uint16_t width, uint16_t height, uint16_t bpp, uint32_t SDLFlags) :
46  m_width(width), m_height(height), m_bpp(bpp), m_refreshRate(0), m_SDLFlags(SDLFlags),
48  }
49 
50  ScreenMode::ScreenMode(uint16_t width, uint16_t height, uint16_t bpp, uint16_t rate, uint32_t SDLFlags) :
51  m_width(width), m_height(height), m_bpp(bpp), m_refreshRate(rate), m_SDLFlags(SDLFlags),
53  }
54 
56  m_width = rhs.getWidth();
57  m_height = rhs.getHeight();
58  m_bpp = rhs.getBPP();
59  m_SDLFlags = rhs.getSDLFlags();
61  m_format = rhs.getFormat();
62  m_display = rhs.getDisplay();
65  }
66 
67  bool ScreenMode::operator <(const ScreenMode& rhs) const {
68  // first by display, from lower to higher
69  if (m_display > rhs.getDisplay()){
70  return true;
71  }
72  else if (m_display < rhs.getDisplay()){
73  return false;
74  }
75 
76  //sort by fullscreen first
77  if (!isFullScreen() && rhs.isFullScreen()){
78  return true;
79  }
80  else if (isFullScreen() && !rhs.isFullScreen()){
81  return false;
82  }
83 
84  //next by bpp
85  if (m_bpp < rhs.getBPP()){
86  return true;
87  }
88  else if (m_bpp > rhs.getBPP()){
89  return false;
90  }
91 
92  //then by screen dimensions
93  if (m_width < rhs.getWidth() || m_height < rhs.getHeight()) {
94  return true;
95  } else if (m_width > rhs.getWidth() || m_height > rhs.getHeight()) {
96  return false;
97  }
98  //last by refresh rate
99  if (m_refreshRate < rhs.getRefreshRate()) {
100  return true;
101  }
102 
103  return false;
104  }
105 
107  m_videoDriverName("dummy"),
108  m_renderDriverName(""),
109  m_renderDriverIndex(-1) {
110  }
111 
113  }
114 
116  m_screenModes.clear();
117  m_renderDriverName = "";
118  m_renderDriverIndex = -1;
119 
121  }
122 
124  // video driver section (x11, windows, dummy, ...)
125  m_availableVideoDrivers.clear();
126  uint8_t driverCount = SDL_GetNumVideoDrivers();
127  for (uint8_t i = 0; i != driverCount; i++) {
128  std::string driver(SDL_GetVideoDriver(i));
129  m_availableVideoDrivers.push_back(driver);
130  }
131  m_videoDriverName = std::string(SDL_GetCurrentVideoDriver());
132 
133  // render driver section (opengl, direct3d, software, ...)
134  m_availableRenderDrivers.clear();
135  SDL_RendererInfo info;
136  driverCount = SDL_GetNumRenderDrivers();
137  for (uint8_t i = 0; i != driverCount; i++) {
138  SDL_GetRenderDriverInfo(i, &info);
139  std::string name(info.name);
140  m_availableRenderDrivers.push_back(name);
141  }
142  }
143 
145  //clear in case this is called twice
146  m_screenModes.clear();
148  //FLAGS
149 #ifdef HAVE_OPENGL
150  const uint32_t numFlags = 4;
151  uint32_t flags[numFlags];
152 
153  //OpenGL, windowed
154  flags[0] = ScreenMode::WINDOWED_OPENGL;
155  //OpenGL, fullscreen
157  //SDL, windowed
158  flags[2] = ScreenMode::WINDOWED_SDL;
159  //SDL, fullscreen
160  flags[3] = ScreenMode::FULLSCREEN_SDL;
161 
162 #else
163  const uint32_t numFlags = 2;
164  uint32_t flags[numFlags];
165 
166  //SDL, windowed
167  flags[0] = ScreenMode::WINDOWED_SDL;
168  //SDL, fullscreen
169  flags[1] = ScreenMode::FULLSCREEN_SDL;
170 #endif
171 
172  //BITS PER PIXEL
173  const uint32_t numBPP = 3;
174  uint16_t bpps[numBPP];
175 
176  bpps[0] = 16;
177  bpps[1] = 24;
178  bpps[2] = 32;
179 
180  bool renderDriver = m_renderDriverIndex != -1;
181  uint8_t displayCount = SDL_GetNumVideoDisplays();
182  for (uint8_t i = 0; i != displayCount; i++) {
183  SDL_DisplayMode mode;
184  uint8_t displayModes = SDL_GetNumDisplayModes(i);
185  for (uint8_t m = 0; m != displayModes; m++) {
186  if (SDL_GetDisplayMode(i, m, &mode) == 0) {
187  for (uint32_t ii = 0; ii < numBPP; ++ii){
188  for (uint32_t j = 0; j < numFlags; ++j) {
189  //m_screenModes.push_back(ScreenMode(mode.w, mode.h, SDL_BITSPERPIXEL(mode.format), mode.refresh_rate, flags[j]));
190  ScreenMode m(mode.w, mode.h, bpps[ii], mode.refresh_rate, flags[j]);
191  m.setFormat(mode.format);
192  m.setDisplay(i);
193  if (renderDriver) {
196  }
197  m_screenModes.push_back(m);
198  }
199  }
200  } else {
201  throw SDLException(SDL_GetError());
202  }
203  }
204  }
205 
206  //sort the list to keep the most preferred modes at the top of the selection process
207  std::sort(m_screenModes.begin(), m_screenModes.end());
208  std::reverse(m_screenModes.begin(), m_screenModes.end());
209  }
210 
211  ScreenMode DeviceCaps::getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string& renderer, bool fs) const {
212  // refresh rate is set to 0 so that desktop setting is used and the first display is used
213  return getNearestScreenMode(width, height, bpp, renderer, fs, 0, 0);
214  }
215 
216  ScreenMode DeviceCaps::getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string& renderer, bool fs, uint16_t refresh, uint8_t display) const {
217  ScreenMode mode;
218  SDL_DisplayMode target, closest;
219  bool foundMode = false;
220 
221  // Set the desired resolution, etc.
222  target.w = width;
223  target.h = height;
224  if (bpp == 0) {
225  target.format = 0; // don't care, should be desktop bpp
226  } else if (bpp == 16) {
227  target.format = SDL_PIXELFORMAT_RGB565;
228  } else {
229  target.format = SDL_PIXELFORMAT_RGB888;
230  }
231  target.refresh_rate = refresh;
232  target.driverdata = 0; // initialize to 0
233 
234  // only first display
235  if (SDL_GetClosestDisplayMode(display, &target, &closest)) {
236  uint32_t flags = 0;
237  if (renderer == "OpenGL") {
238  if (fs) {
239  flags = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
240  } else {
241  flags = SDL_WINDOW_OPENGL;
242  }
243  } else {
244  if (fs) {
245  flags = SDL_WINDOW_FULLSCREEN;
246  }
247  }
248  mode = ScreenMode(closest.w, closest.h, bpp, closest.refresh_rate, flags);
249  mode.setFormat(closest.format);
250  mode.setDisplay(display);
251  if (m_renderDriverIndex != -1) {
254  }
255  foundMode = true;
256  }
257 
258  if (!foundMode) {
259  throw NotSupported("Could not find a matching screen mode for the values given!");
260  }
261 
262  return mode;
263  }
264 
265  void DeviceCaps::setRenderDriverName(const std::string& driver) {
266  bool found = false;
267  uint8_t driverCount = m_availableRenderDrivers.size();
268  for (uint8_t i = 0; i != driverCount; i++) {
269  if (driver == m_availableRenderDrivers[i]) {
270  m_renderDriverName = driver;
272  found = true;
273  break;
274  }
275  }
276  if (!found) {
277  if (driver != "") {
278  throw NotSupported("Could not find a matching render driver!");
279  }
280  m_renderDriverName = "";
281  m_renderDriverIndex = -1;
282  }
283  // refill
284  fillDeviceCaps();
285  }
286 
288  uint8_t displayCount = SDL_GetNumVideoDisplays();
289  return displayCount;
290  }
291 
292  std::string DeviceCaps::getDisplayName(uint8_t display) const {
293  if (display >= getDisplayCount()) {
294  throw NotSupported("Could not find a matching display!");
295  return std::string("Invalid");
296  }
297  std::string displayName(SDL_GetDisplayName(display));
298  return displayName;
299  }
300 
302  SDL_DisplayMode mode;
303  if (SDL_GetDesktopDisplayMode(display, &mode) != 0) {
304  throw SDLException(SDL_GetError());
305  }
306  return mode.format;
307  }
308 
310  SDL_DisplayMode mode;
311  if (SDL_GetDesktopDisplayMode(display, &mode) != 0) {
312  throw SDLException(SDL_GetError());
313  }
314  return mode.refresh_rate;
315  }
316 
317  int32_t DeviceCaps::getDesktopWidth(uint8_t display) const {
318  SDL_DisplayMode mode;
319  if (SDL_GetDesktopDisplayMode(display, &mode) != 0) {
320  throw SDLException(SDL_GetError());
321  }
322  return mode.w;
323  }
324 
325  int32_t DeviceCaps::getDesktopHeight(uint8_t display) const {
326  SDL_DisplayMode mode;
327  if (SDL_GetDesktopDisplayMode(display, &mode) != 0) {
328  throw SDLException(SDL_GetError());
329  }
330  return mode.h;
331  }
332 
334  SDL_Rect srec;
335  if (SDL_GetDisplayBounds(display, &srec) != 0) {
336  throw SDLException(SDL_GetError());
337  }
338  Rect rec(srec.x, srec.y, srec.w, srec.h);
339  return rec;
340  }
341 
342 } //FIFE
uint8_t m_display
Definition: devicecaps.h:142
uint8_t getDisplay() const
Returns the display index.
Definition: devicecaps.h:108
uint16_t getHeight() const
Returns the height of the screen mode.
Definition: devicecaps.h:68
std::vector< std::string > m_availableVideoDrivers
Definition: devicecaps.h:233
uint32_t getSDLFlags() const
Returns the SDL flags used when testing this mode.
Definition: devicecaps.h:80
int8_t getRenderDriverIndex() const
Returns the index of the render driver.
Definition: devicecaps.h:124
std::string m_renderDriverName
Definition: devicecaps.h:235
uint16_t m_bpp
Definition: devicecaps.h:138
int32_t getDesktopHeight(uint8_t display=0) const
Returns the height of the desktop resolution for the given display index.
Definition: devicecaps.cpp:325
std::string m_videoDriverName
Definition: devicecaps.h:232
Rect getDisplayBounds(uint8_t display=0) const
Returns the bounding points for the given display index.
Definition: devicecaps.cpp:333
uint32_t m_SDLFlags
Definition: devicecaps.h:140
uint32_t getFormat() const
Returns the pixel format enum.
Definition: devicecaps.h:100
bool operator<(const ScreenMode &rhs) const
Definition: devicecaps.cpp:67
void setFormat(uint32_t format)
Sets the pixel format enum.
Definition: devicecaps.h:96
void setRenderDriverName(const std::string driver)
Sets the render driver name.
Definition: devicecaps.h:112
uint32_t getDesktopFormat(uint8_t display=0) const
Returns the SDL_PixelFormatEnum of the desktop for the given display index.
Definition: devicecaps.cpp:301
int32_t getDesktopWidth(uint8_t display=0) const
Returns the width of the desktop resolution for the given display index.
Definition: devicecaps.cpp:317
uint8_t getDisplayCount() const
Returns the number of displays.
Definition: devicecaps.cpp:287
void fillAvailableDrivers()
Called in the constructor.
Definition: devicecaps.cpp:123
std::string getDisplayName(uint8_t display=0) const
Returns the display name for the given display index.
Definition: devicecaps.cpp:292
static const uint32_t WINDOWED_OPENGL
Definition: devicecaps.h:127
unsigned char uint8_t
Definition: core.h:38
ScreenMode()
Default Constructor.
Definition: devicecaps.cpp:40
static const uint32_t FULLSCREEN_SDL
Definition: devicecaps.h:133
uint16_t m_width
Definition: devicecaps.h:136
void reset()
Clears all information gathered for the device.
Definition: devicecaps.cpp:115
uint16_t getBPP() const
Returns the number of bits per pixel this mode uses.
Definition: devicecaps.h:72
int8_t m_renderDriverIndex
Definition: devicecaps.h:236
ScreenMode getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string &renderer, bool fs) const
Gets the nearest valid screen mode based on the arguments passed.
Definition: devicecaps.cpp:211
unsigned short uint16_t
Definition: core.h:39
uint16_t m_refreshRate
Definition: devicecaps.h:139
void setRenderDriverName(const std::string &driver)
Sets the name of the render driver.
Definition: devicecaps.cpp:265
void fillDeviceCaps()
Should be called AFTER SDL_Init() has been called.
Definition: devicecaps.cpp:144
static const uint32_t FULLSCREEN_OPENGL
Definition: devicecaps.h:129
int8_t m_renderDriverIndex
Definition: devicecaps.h:144
static const uint32_t WINDOWED_SDL
Definition: devicecaps.h:131
const std::string & getRenderDriverName() const
Returns the render driver name.
Definition: devicecaps.h:116
void setDisplay(uint8_t display)
Sets the display index.
Definition: devicecaps.h:104
std::string m_renderDriver
Definition: devicecaps.h:143
uint32_t m_format
Definition: devicecaps.h:141
void setRenderDriverIndex(int8_t index)
Sets the index of the render driver used by SDL.
Definition: devicecaps.h:120
uint16_t m_height
Definition: devicecaps.h:137
unsigned int uint32_t
Definition: core.h:40
uint16_t getWidth() const
Returns the width of the screen mode.
Definition: devicecaps.h:62
std::vector< ScreenMode > m_screenModes
Definition: devicecaps.h:231
uint16_t getRefreshRate() const
Returns the refresh rate in Hz of this mode.
Definition: devicecaps.h:76
int32_t getDesktopRefreshRate(uint8_t display=0) const
Returns the refresh rate in Hz of the desktop for the given display index.
Definition: devicecaps.cpp:309
~DeviceCaps()
Destructor.
Definition: devicecaps.cpp:112
DeviceCaps()
Constructor.
Definition: devicecaps.cpp:106
bool isFullScreen() const
True if this is a fullscreen mode.
Definition: devicecaps.h:84
std::vector< std::string > m_availableRenderDrivers
Definition: devicecaps.h:237