FIFE  2008.0
devicecaps.cpp
1 /***************************************************************************
2  * Copyright (C) 2005-2011 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 
40  ScreenMode::ScreenMode() :
41  m_width(0), m_height(0), m_bpp(0), m_SDLFlags(0){
42  }
43 
44  ScreenMode::ScreenMode(uint16_t width, uint16_t height, uint16_t bpp, uint32_t SDLFlags) :
45  m_width(width), m_height(height), m_bpp(bpp), m_SDLFlags(SDLFlags){
46  }
47 
48  ScreenMode::ScreenMode(const ScreenMode& rhs){
49  m_width = rhs.getWidth();
50  m_height = rhs.getHeight();
51  m_bpp = rhs.getBPP();
52  m_SDLFlags = rhs.getSDLFlags();
53  }
54 
55  bool ScreenMode::operator <(const ScreenMode& rhs) const {
56 
57  //sort by fullscreen first
58  if (!isFullScreen() && rhs.isFullScreen()){
59  return true;
60  }
61  else if (isFullScreen() && !rhs.isFullScreen()){
62  return false;
63  }
64 
65  //next by bpp
66  if (m_bpp < rhs.getBPP()){
67  return true;
68  }
69  else if (m_bpp > rhs.getBPP()){
70  return false;
71  }
72 
73  //then by screen dimentions
74  if (m_width == rhs.getWidth() && m_height == rhs.getHeight()){
75  if (!(m_SDLFlags & SDL_HWSURFACE) && (rhs.getSDLFlags() & SDL_HWSURFACE)) {
76  //I would like return true so that we prefer hardware surfaces but
77  //it really slows the engine down in fullscreen. See the SDL FAQ for an
78  //explanation.
79  return false;
80  }
81  }
82 
83  else if (m_width < rhs.getWidth() || m_height < rhs.getHeight()) {
84  return true;
85  }
86 
87  return false;
88  }
89 
90  DeviceCaps::DeviceCaps() :
91  m_driverName("Invalid"),
92  m_hwAvailable(false),
93  m_wmAvailable(false),
94  m_hwBlitAccel(false),
95  m_hwCCBlitAccel(false),
96  m_hwToHwAlphaBlitAccel(false),
97  m_swToHwBlitAccel(false),
98  m_swToHwCCBlistAccel(false),
99  m_swToHwAlphaBlitAccel(false),
100  m_BlitFillAccel(false),
101  m_videoMem(0) {
102 
103  fillAvailableDrivers();
104  }
105 
106 
107  DeviceCaps::~DeviceCaps() {
108  }
109 
110  void DeviceCaps::reset() {
111  m_screenModes.clear();
112  m_driverName = "Invalid";
113  m_hwAvailable = false;
114  m_wmAvailable = false;
115  m_hwBlitAccel = false;
116  m_hwCCBlitAccel = false;
117  m_hwToHwAlphaBlitAccel = false;
118  m_swToHwBlitAccel = false;
119  m_swToHwCCBlistAccel = false;
120  m_swToHwAlphaBlitAccel = false;
121  m_BlitFillAccel = false;
122  m_videoMem = 0;
123  }
124 
125 
126  void DeviceCaps::fillAvailableDrivers() {
127  m_availableDrivers.clear();
128 #if defined( __unix__ )
129  m_availableDrivers.push_back("x11");
130  m_availableDrivers.push_back("nanox");
131  m_availableDrivers.push_back("qtopia");
132  m_availableDrivers.push_back("fbcon");
133  m_availableDrivers.push_back("directfb");
134  m_availableDrivers.push_back("svgalib");
135 #endif
136 
137 // Win32
138 #if defined( WIN32 )
139  m_availableDrivers.push_back("directx");
140  m_availableDrivers.push_back("windib");
141 #endif
142 
143 // Macintosh
144 #if defined( __APPLE_CC__ )
145  m_availableDrivers.push_back("Quartz");
146  m_availableDrivers.push_back("x11");
147 #endif
148  }
149 
150  void DeviceCaps::fillDeviceCaps() {
151  //buffer to store driver name
152  const uint32_t bufferSize = 256;
153  char buffer[bufferSize];
154 
155  //clear in case this is called twice
156  reset();
157 
158  //FLAGS
159 #ifdef HAVE_OPENGL
160  const uint32_t numFlags = 6;
161  uint32_t flags[numFlags];
162 
163  //OpenGL, windowed, hw accel
164  flags[0] = ScreenMode::HW_WINDOWED_OPENGL;
165  //OpenGL, fullscree, hw accel
166  flags[1] = ScreenMode::HW_FULLSCREEN_OPENGL;
167  //SDL, windowed
168  flags[2] = ScreenMode::WINDOWED_SDL;
169  //SDL, windowed, hw surface, double buffer
170  flags[3] = ScreenMode::WINDOWED_SDL_DB_HW;
171  //SDL, fullscreen
172  flags[4] = ScreenMode::FULLSCREEN_SDL;
173  //SDL, fullscreen, hw surface, double buffer
174  flags[5] = ScreenMode::FULLSCREEN_SDL_DB_HW;
175 
176 #else
177  const uint32_tnumFlags = 4;
178  uint32_t flags[numFlags];
179 
180  //SDL, windowed
181  flags[0] = ScreenMode::WINDOWED_SDL;
182  //SDL, windowed, hw surface, double buffer
183  flags[1] = ScreenMode::WINDOWED_SDL_DB_HW;
184  //SDL, fullscreen
185  flags[2] = ScreenMode::FULLSCREEN_SDL;
186  //SDL, fullscreen, hw surface, double buffer
187  flags[3] = ScreenMode::FULLSCREEN_SDL_DB_HW;
188 #endif
189 
190  //BITS PER PIXEL
191  const uint32_t numBPP = 3;
192  uint16_t bpps[numBPP];
193 
194  bpps[0] = 16;
195  bpps[1] = 24;
196  bpps[2] = 32;
197 
198  //COMMON FS RESOLUTIONS
199  const uint32_t numRes = 16;
200  uint16_t resolutions[numRes][2] = {
201  {640, 480},
202  {800, 600},
203  {1024, 600},
204  {1024, 768},
205  {1152, 864},
206  {1280, 768},
207  {1280, 800},
208  {1280, 960},
209  {1280, 1024},
210  {1366, 768},
211  {1440, 900},
212  {1600, 900},
213  {1600, 1200},
214  {1680, 1050},
215  {1920, 1080},
216  {1920, 1200}
217  };
218 
219 
220  for (uint32_t i = 0; i < numBPP; ++i){
221  for (uint32_t j = 0; j < numFlags; ++j) {
222  for ( uint32_t k = 0; k < numRes; ++k) {
223  uint16_t bpp;
224  if (flags[j] & SDL_FULLSCREEN) {
225  bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
226 
227  if (bpp > 0) {
228  m_screenModes.push_back(ScreenMode(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]));
229  }
230  }
231  else { //windowed mode
232  //check an arbitrary value as we know all resolutions are supported in windowed mode.
233  //we are checking to make sure the bpp is supported here.
234  bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
235  if (bpp > 0) {
236  m_screenModes.push_back(ScreenMode(0,0, bpps[i], flags[j]));
237  break; //insert windowed mode once as all resolutions are supported.
238  }
239  }
240 
241  }
242  }
243  }
244 
245  //sort the list to keep the most preferred modes at the top of the selection process
246  //in getNearestScreenMode()
247  std::sort(m_screenModes.begin(), m_screenModes.end());
248  std::reverse(m_screenModes.begin(), m_screenModes.end());
249 
250  if(SDL_VideoDriverName(buffer, bufferSize) != NULL) {
251  m_driverName = std::string(buffer);
252  }
253  else {
254  m_driverName = "Unknown";
255  }
256 
257  const SDL_VideoInfo* vInfo = SDL_GetVideoInfo();
258 
259  m_hwAvailable = vInfo->hw_available;
260  m_wmAvailable = vInfo->wm_available;
261  m_hwBlitAccel = vInfo->blit_hw;
262  m_hwCCBlitAccel = vInfo->blit_hw_CC;
263  m_hwToHwAlphaBlitAccel = vInfo->blit_hw_A;
264  m_swToHwBlitAccel = vInfo->blit_sw;
265  m_swToHwCCBlistAccel = vInfo->blit_sw_CC;
266  m_swToHwAlphaBlitAccel = vInfo->blit_sw_A;
267  m_BlitFillAccel = vInfo->blit_fill;
268  m_videoMem = vInfo->video_mem;
269  }
270 
271  ScreenMode DeviceCaps::getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string& renderer, bool fs) const {
272  ScreenMode mode;
273  bool foundMode = false;
274 
275  bool widthCheck = false;
276  bool heightCheck = false;
277  bool bppCheck = false;
278  bool rendCheck = false;
279  bool fsCheck = false;
280 
281 
282  for (uint32_t i = 0; i < m_screenModes.size(); i++) {
283  if (m_screenModes[i].getWidth() == width) {
284  widthCheck = true;
285  }
286  if (m_screenModes[i].getHeight() == height) {
287  heightCheck = true;
288  }
289  if (m_screenModes[i].getBPP() == bpp) {
290  bppCheck = true;
291  }
292  if (m_screenModes[i].isFullScreen() == fs) {
293  fsCheck = true;
294  }
295 
296  if ((m_screenModes[i].isOpenGL() && (renderer == "OpenGL" || renderer == "OpenGLe")) || (!m_screenModes[i].isOpenGL() && renderer == "SDL")){
297  rendCheck = true;
298  }
299 
300  //check for exact match
301  if (widthCheck && heightCheck && bppCheck && fsCheck && rendCheck) {
302  mode = m_screenModes[i];
303  foundMode = true;
304  break;
305  }
306 
307  //@note When the width and height to 0 that means that all
308  //resolutions are supported
309  if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0 && bppCheck && fsCheck && rendCheck) {
310  mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
311  foundMode = true;
312  break;
313  }
314 
315  //current screen bpp selected
316  if (widthCheck && heightCheck && bpp == 0 && fsCheck && rendCheck) {
317  mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
318  foundMode = true;
319  break;
320  }
321 
322  if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0 && bpp == 0 && fsCheck && rendCheck) {
323  mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
324  foundMode = true;
325  break;
326  }
327 
328 
329  widthCheck = false;
330  heightCheck = false;
331  bppCheck = false;
332  rendCheck = false;
333  fsCheck = false;
334  }
335 
336  if (!foundMode) {
337  throw NotSupported("Could not find a maching screen mode for the values given!");
338  }
339 
340  return mode;
341  }
342 
343 } //FIFE
credit to phoku for his NodeDisplay example which the visitor code is adapted from ( he coded the qua...
Definition: soundclip.cpp:39