FIFE 2008.0
|
00001 /*************************************************************************** 00002 * Copyright (C) 2005-2010 by the FIFE team * 00003 * http://www.fifengine.net * 00004 * This file is part of FIFE. * 00005 * * 00006 * FIFE is free software; you can redistribute it and/or * 00007 * modify it under the terms of the GNU Lesser General Public * 00008 * License as published by the Free Software Foundation; either * 00009 * version 2.1 of the License, or (at your option) any later version. * 00010 * * 00011 * This library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * Lesser General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU Lesser General Public * 00017 * License along with this library; if not, write to the * 00018 * Free Software Foundation, Inc., * 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * 00020 ***************************************************************************/ 00021 00022 // Standard C++ library includes 00023 #include <iostream> 00024 #include <algorithm> 00025 00026 // 3rd party library includes 00027 #include <SDL.h> 00028 #include <SDL_video.h> 00029 00030 // FIFE includes 00031 // These includes are split up in two parts, separated by one empty line 00032 // First block: files included from the FIFE root src directory 00033 // Second block: files included from the same folder 00034 #include "util/base/exception.h" 00035 00036 #include "devicecaps.h" 00037 00038 namespace FIFE { 00039 00040 ScreenMode::ScreenMode() : 00041 m_width(0), m_height(0), m_bpp(0), m_SDLFlags(0){ 00042 } 00043 00044 ScreenMode::ScreenMode(uint16_t width, uint16_t height, uint16_t bpp, uint32_t SDLFlags) : 00045 m_width(width), m_height(height), m_bpp(bpp), m_SDLFlags(SDLFlags){ 00046 } 00047 00048 ScreenMode::ScreenMode(const ScreenMode& rhs){ 00049 m_width = rhs.getWidth(); 00050 m_height = rhs.getHeight(); 00051 m_bpp = rhs.getBPP(); 00052 m_SDLFlags = rhs.getSDLFlags(); 00053 } 00054 00055 bool ScreenMode::operator <(const ScreenMode& rhs) const { 00056 00057 //sort by fullscreen first 00058 if (!isFullScreen() && rhs.isFullScreen()){ 00059 return true; 00060 } 00061 else if (isFullScreen() && !rhs.isFullScreen()){ 00062 return false; 00063 } 00064 00065 //next by bpp 00066 if (m_bpp < rhs.getBPP()){ 00067 return true; 00068 } 00069 else if (m_bpp > rhs.getBPP()){ 00070 return false; 00071 } 00072 00073 //then by screen dimentions 00074 if (m_width == rhs.getWidth() && m_height == rhs.getHeight()){ 00075 if (!(m_SDLFlags & SDL_HWSURFACE) && (rhs.getSDLFlags() & SDL_HWSURFACE)) { 00076 //I would like return true so that we prefer hardware surfaces but 00077 //it really slows the engine down in fullscreen. See the SDL FAQ for an 00078 //explanation. 00079 return false; 00080 } 00081 } 00082 00083 else if (m_width < rhs.getWidth() || m_height < rhs.getHeight()) { 00084 return true; 00085 } 00086 00087 return false; 00088 } 00089 00090 DeviceCaps::DeviceCaps() : 00091 m_driverName("Invalid"), 00092 m_hwAvailable(false), 00093 m_wmAvailable(false), 00094 m_hwBlitAccel(false), 00095 m_hwCCBlitAccel(false), 00096 m_hwToHwAlphaBlitAccel(false), 00097 m_swToHwBlitAccel(false), 00098 m_swToHwCCBlistAccel(false), 00099 m_swToHwAlphaBlitAccel(false), 00100 m_BlitFillAccel(false), 00101 m_videoMem(0) { 00102 00103 fillAvailableDrivers(); 00104 } 00105 00106 00107 DeviceCaps::~DeviceCaps() { 00108 } 00109 00110 void DeviceCaps::reset() { 00111 m_screenModes.clear(); 00112 m_driverName = "Invalid"; 00113 m_hwAvailable = false; 00114 m_wmAvailable = false; 00115 m_hwBlitAccel = false; 00116 m_hwCCBlitAccel = false; 00117 m_hwToHwAlphaBlitAccel = false; 00118 m_swToHwBlitAccel = false; 00119 m_swToHwCCBlistAccel = false; 00120 m_swToHwAlphaBlitAccel = false; 00121 m_BlitFillAccel = false; 00122 m_videoMem = 0; 00123 } 00124 00125 00126 void DeviceCaps::fillAvailableDrivers() { 00127 m_availableDrivers.clear(); 00128 #if defined( __unix__ ) 00129 m_availableDrivers.push_back("x11"); 00130 m_availableDrivers.push_back("nanox"); 00131 m_availableDrivers.push_back("qtopia"); 00132 m_availableDrivers.push_back("fbcon"); 00133 m_availableDrivers.push_back("directfb"); 00134 m_availableDrivers.push_back("svgalib"); 00135 #endif 00136 00137 // Win32 00138 #if defined( WIN32 ) 00139 m_availableDrivers.push_back("directx"); 00140 m_availableDrivers.push_back("windib"); 00141 #endif 00142 00143 // Macintosh 00144 #if defined( __APPLE_CC__ ) 00145 m_availableDrivers.push_back("Quartz"); 00146 m_availableDrivers.push_back("x11"); 00147 #endif 00148 } 00149 00150 void DeviceCaps::fillDeviceCaps() { 00151 //buffer to store driver name 00152 const uint32_t bufferSize = 256; 00153 char buffer[bufferSize]; 00154 00155 //clear in case this is called twice 00156 reset(); 00157 00158 //FLAGS 00159 #ifdef HAVE_OPENGL 00160 const uint32_t numFlags = 6; 00161 uint32_t flags[numFlags]; 00162 00163 //OpenGL, windowed, hw accel 00164 flags[0] = ScreenMode::HW_WINDOWED_OPENGL; 00165 //OpenGL, fullscree, hw accel 00166 flags[1] = ScreenMode::HW_FULLSCREEN_OPENGL; 00167 //SDL, windowed 00168 flags[2] = ScreenMode::WINDOWED_SDL; 00169 //SDL, windowed, hw surface, double buffer 00170 flags[3] = ScreenMode::WINDOWED_SDL_DB_HW; 00171 //SDL, fullscreen 00172 flags[4] = ScreenMode::FULLSCREEN_SDL; 00173 //SDL, fullscreen, hw surface, double buffer 00174 flags[5] = ScreenMode::FULLSCREEN_SDL_DB_HW; 00175 00176 #else 00177 const uint32_tnumFlags = 4; 00178 uint32_t flags[numFlags]; 00179 00180 //SDL, windowed 00181 flags[0] = ScreenMode::WINDOWED_SDL; 00182 //SDL, windowed, hw surface, double buffer 00183 flags[1] = ScreenMode::WINDOWED_SDL_DB_HW; 00184 //SDL, fullscreen 00185 flags[2] = ScreenMode::FULLSCREEN_SDL; 00186 //SDL, fullscreen, hw surface, double buffer 00187 flags[3] = ScreenMode::FULLSCREEN_SDL_DB_HW; 00188 #endif 00189 00190 //BITS PER PIXEL 00191 const uint32_t numBPP = 3; 00192 uint16_t bpps[numBPP]; 00193 00194 bpps[0] = 16; 00195 bpps[1] = 24; 00196 bpps[2] = 32; 00197 00198 //COMMON FS RESOLUTIONS 00199 const uint32_t numRes = 15; 00200 uint16_t resolutions[numRes][2] = { 00201 {640, 480}, 00202 {800, 600}, 00203 {1024, 768}, 00204 {1152, 864}, 00205 {1280, 768}, 00206 {1280, 800}, 00207 {1280, 960}, 00208 {1280, 1024}, 00209 {1366, 768}, 00210 {1440, 900}, 00211 {1600, 900}, 00212 {1600, 1200}, 00213 {1680, 1050}, 00214 {1920, 1080}, 00215 {1920, 1200} 00216 }; 00217 00218 00219 for (uint32_t i = 0; i < numBPP; ++i){ 00220 for (uint32_t j = 0; j < numFlags; ++j) { 00221 for ( uint32_t k = 0; k < numRes; ++k) { 00222 uint16_t bpp; 00223 if (flags[j] & SDL_FULLSCREEN) { 00224 bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]); 00225 00226 if (bpp > 0) { 00227 m_screenModes.push_back(ScreenMode(resolutions[k][0],resolutions[k][1], bpps[i], flags[j])); 00228 } 00229 } 00230 else { //windowed mode 00231 //check an arbitrary value as we know all resolutions are supported in windowed mode. 00232 //we are checking to make sure the bpp is supported here. 00233 bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]); 00234 if (bpp > 0) { 00235 m_screenModes.push_back(ScreenMode(0,0, bpps[i], flags[j])); 00236 break; //insert windowed mode once as all resolutions are supported. 00237 } 00238 } 00239 00240 } 00241 } 00242 } 00243 00244 //sort the list to keep the most preferred modes at the top of the selection process 00245 //in getNearestScreenMode() 00246 std::sort(m_screenModes.begin(), m_screenModes.end()); 00247 std::reverse(m_screenModes.begin(), m_screenModes.end()); 00248 00249 if(SDL_VideoDriverName(buffer, bufferSize) != NULL) { 00250 m_driverName = std::string(buffer); 00251 } 00252 else { 00253 m_driverName = "Unknown"; 00254 } 00255 00256 const SDL_VideoInfo* vInfo = SDL_GetVideoInfo(); 00257 00258 m_hwAvailable = vInfo->hw_available; 00259 m_wmAvailable = vInfo->wm_available; 00260 m_hwBlitAccel = vInfo->blit_hw; 00261 m_hwCCBlitAccel = vInfo->blit_hw_CC; 00262 m_hwToHwAlphaBlitAccel = vInfo->blit_hw_A; 00263 m_swToHwBlitAccel = vInfo->blit_sw; 00264 m_swToHwCCBlistAccel = vInfo->blit_sw_CC; 00265 m_swToHwAlphaBlitAccel = vInfo->blit_sw_A; 00266 m_BlitFillAccel = vInfo->blit_fill; 00267 m_videoMem = vInfo->video_mem; 00268 } 00269 00270 ScreenMode DeviceCaps::getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string& renderer, bool fs) const { 00271 ScreenMode mode; 00272 bool foundMode = false; 00273 00274 bool widthCheck = false; 00275 bool heightCheck = false; 00276 bool bppCheck = false; 00277 bool rendCheck = false; 00278 bool fsCheck = false; 00279 00280 00281 for (uint32_t i = 0; i < m_screenModes.size(); i++) { 00282 if (m_screenModes[i].getWidth() == width) { 00283 widthCheck = true; 00284 } 00285 if (m_screenModes[i].getHeight() == height) { 00286 heightCheck = true; 00287 } 00288 if (m_screenModes[i].getBPP() == bpp) { 00289 bppCheck = true; 00290 } 00291 if (m_screenModes[i].isFullScreen() == fs) { 00292 fsCheck = true; 00293 } 00294 00295 if ((m_screenModes[i].isOpenGL() && renderer == "OpenGL") || (!m_screenModes[i].isOpenGL() && renderer == "SDL")){ 00296 rendCheck = true; 00297 } 00298 00299 //check for exact match 00300 if (widthCheck && heightCheck && bppCheck && fsCheck && rendCheck) { 00301 mode = m_screenModes[i]; 00302 foundMode = true; 00303 break; 00304 } 00305 00306 //@note When the width and height to 0 that means that all 00307 //resolutions are supported 00308 if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0 && bppCheck && fsCheck && rendCheck) { 00309 mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags()); 00310 foundMode = true; 00311 break; 00312 } 00313 00314 //current screen bpp selected 00315 if (widthCheck && heightCheck && bpp == 0 && fsCheck && rendCheck) { 00316 mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags()); 00317 foundMode = true; 00318 break; 00319 } 00320 00321 if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0 && bpp == 0 && fsCheck && rendCheck) { 00322 mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags()); 00323 foundMode = true; 00324 break; 00325 } 00326 00327 00328 widthCheck = false; 00329 heightCheck = false; 00330 bppCheck = false; 00331 rendCheck = false; 00332 fsCheck = false; 00333 } 00334 00335 if (!foundMode) { 00336 throw NotSupported("Could not find a maching screen mode for the values given!"); 00337 } 00338 00339 return mode; 00340 } 00341 00342 } //FIFE