00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <iostream>
00024 #include <algorithm>
00025
00026
00027 #include <SDL.h>
00028 #include <SDL_video.h>
00029
00030
00031
00032
00033
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
00058 if (!isFullScreen() && rhs.isFullScreen()){
00059 return true;
00060 }
00061 else if (isFullScreen() && !rhs.isFullScreen()){
00062 return false;
00063 }
00064
00065
00066 if (m_bpp < rhs.getBPP()){
00067 return true;
00068 }
00069 else if (m_bpp > rhs.getBPP()){
00070 return false;
00071 }
00072
00073
00074 if (m_width == rhs.getWidth() && m_height == rhs.getHeight()){
00075 if (!(m_SDLFlags & SDL_HWSURFACE) && (rhs.getSDLFlags() & SDL_HWSURFACE)) {
00076
00077
00078
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
00138 #if defined( WIN32 )
00139 m_availableDrivers.push_back("directx");
00140 m_availableDrivers.push_back("windib");
00141 #endif
00142
00143
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
00152 const uint32_t bufferSize = 256;
00153 char buffer[bufferSize];
00154
00155
00156 reset();
00157
00158
00159 #ifdef HAVE_OPENGL
00160 const uint32_t numFlags = 6;
00161 uint32_t flags[numFlags];
00162
00163
00164 flags[0] = ScreenMode::HW_WINDOWED_OPENGL;
00165
00166 flags[1] = ScreenMode::HW_FULLSCREEN_OPENGL;
00167
00168 flags[2] = ScreenMode::WINDOWED_SDL;
00169
00170 flags[3] = ScreenMode::WINDOWED_SDL_DB_HW;
00171
00172 flags[4] = ScreenMode::FULLSCREEN_SDL;
00173
00174 flags[5] = ScreenMode::FULLSCREEN_SDL_DB_HW;
00175
00176 #else
00177 const uint32_tnumFlags = 4;
00178 uint32_t flags[numFlags];
00179
00180
00181 flags[0] = ScreenMode::WINDOWED_SDL;
00182
00183 flags[1] = ScreenMode::WINDOWED_SDL_DB_HW;
00184
00185 flags[2] = ScreenMode::FULLSCREEN_SDL;
00186
00187 flags[3] = ScreenMode::FULLSCREEN_SDL_DB_HW;
00188 #endif
00189
00190
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
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 {
00231
00232
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;
00237 }
00238 }
00239
00240 }
00241 }
00242 }
00243
00244
00245
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
00300 if (widthCheck && heightCheck && bppCheck && fsCheck && rendCheck) {
00301 mode = m_screenModes[i];
00302 foundMode = true;
00303 break;
00304 }
00305
00306
00307
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
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 }