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_t numFlags = 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 = 16;
00200 uint16_t resolutions[numRes][2] = {
00201 {640, 480},
00202 {800, 600},
00203 {1024, 600},
00204 {1024, 768},
00205 {1152, 864},
00206 {1280, 768},
00207 {1280, 800},
00208 {1280, 960},
00209 {1280, 1024},
00210 {1366, 768},
00211 {1440, 900},
00212 {1600, 900},
00213 {1600, 1200},
00214 {1680, 1050},
00215 {1920, 1080},
00216 {1920, 1200}
00217 };
00218
00219
00220 for (uint32_t i = 0; i < numBPP; ++i){
00221 for (uint32_t j = 0; j < numFlags; ++j) {
00222 for ( uint32_t k = 0; k < numRes; ++k) {
00223 uint16_t bpp;
00224 if (flags[j] & SDL_FULLSCREEN) {
00225 bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
00226
00227 if (bpp > 0) {
00228 m_screenModes.push_back(ScreenMode(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]));
00229 }
00230 }
00231 else {
00232
00233
00234 bpp = SDL_VideoModeOK(resolutions[k][0],resolutions[k][1], bpps[i], flags[j]);
00235 if (bpp > 0) {
00236 m_screenModes.push_back(ScreenMode(0,0, bpps[i], flags[j]));
00237 break;
00238 }
00239 }
00240
00241 }
00242 }
00243 }
00244
00245
00246
00247 std::sort(m_screenModes.begin(), m_screenModes.end());
00248 std::reverse(m_screenModes.begin(), m_screenModes.end());
00249
00250 if(SDL_VideoDriverName(buffer, bufferSize) != NULL) {
00251 m_driverName = std::string(buffer);
00252 }
00253 else {
00254 m_driverName = "Unknown";
00255 }
00256
00257 const SDL_VideoInfo* vInfo = SDL_GetVideoInfo();
00258
00259 m_hwAvailable = vInfo->hw_available;
00260 m_wmAvailable = vInfo->wm_available;
00261 m_hwBlitAccel = vInfo->blit_hw;
00262 m_hwCCBlitAccel = vInfo->blit_hw_CC;
00263 m_hwToHwAlphaBlitAccel = vInfo->blit_hw_A;
00264 m_swToHwBlitAccel = vInfo->blit_sw;
00265 m_swToHwCCBlistAccel = vInfo->blit_sw_CC;
00266 m_swToHwAlphaBlitAccel = vInfo->blit_sw_A;
00267 m_BlitFillAccel = vInfo->blit_fill;
00268 m_videoMem = vInfo->video_mem;
00269 }
00270
00271 ScreenMode DeviceCaps::getNearestScreenMode(uint16_t width, uint16_t height, uint16_t bpp, const std::string& renderer, bool fs) const {
00272 ScreenMode mode;
00273 bool foundMode = false;
00274
00275 bool widthCheck = false;
00276 bool heightCheck = false;
00277 bool bppCheck = false;
00278 bool rendCheck = false;
00279 bool fsCheck = false;
00280
00281
00282 for (uint32_t i = 0; i < m_screenModes.size(); i++) {
00283 if (m_screenModes[i].getWidth() == width) {
00284 widthCheck = true;
00285 }
00286 if (m_screenModes[i].getHeight() == height) {
00287 heightCheck = true;
00288 }
00289 if (m_screenModes[i].getBPP() == bpp) {
00290 bppCheck = true;
00291 }
00292 if (m_screenModes[i].isFullScreen() == fs) {
00293 fsCheck = true;
00294 }
00295
00296 if ((m_screenModes[i].isOpenGL() && (renderer == "OpenGL" || renderer == "OpenGLe")) || (!m_screenModes[i].isOpenGL() && renderer == "SDL")){
00297 rendCheck = true;
00298 }
00299
00300
00301 if (widthCheck && heightCheck && bppCheck && fsCheck && rendCheck) {
00302 mode = m_screenModes[i];
00303 foundMode = true;
00304 break;
00305 }
00306
00307
00308
00309 if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0 && bppCheck && fsCheck && rendCheck) {
00310 mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
00311 foundMode = true;
00312 break;
00313 }
00314
00315
00316 if (widthCheck && heightCheck && bpp == 0 && fsCheck && rendCheck) {
00317 mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
00318 foundMode = true;
00319 break;
00320 }
00321
00322 if (m_screenModes[i].getWidth() == 0 && m_screenModes[i].getHeight() == 0 && bpp == 0 && fsCheck && rendCheck) {
00323 mode = ScreenMode(width, height, bpp, m_screenModes[i].getSDLFlags());
00324 foundMode = true;
00325 break;
00326 }
00327
00328
00329 widthCheck = false;
00330 heightCheck = false;
00331 bppCheck = false;
00332 rendCheck = false;
00333 fsCheck = false;
00334 }
00335
00336 if (!foundMode) {
00337 throw NotSupported("Could not find a maching screen mode for the values given!");
00338 }
00339
00340 return mode;
00341 }
00342
00343 }