1 /* 2 SDL - Simple DirectMedia Layer 3 Copyright (C) 1997-2012 Sam Lantinga 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with this library; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 19 Sam Lantinga 20 slouken (at) libsdl.org 21 */ 22 #include "SDL_config.h" 23 24 #include "SDL_ph_modes_c.h" 25 26 static PgVideoModeInfo_t mode_info; 27 static PgVideoModes_t mode_list; 28 29 /* The current list of available video modes */ 30 SDL_Rect SDL_modelist[PH_MAX_VIDEOMODES]; 31 SDL_Rect* SDL_modearray[PH_MAX_VIDEOMODES]; 32 33 static int compare_modes_by_res(const void* mode1, const void* mode2) 34 { 35 PgVideoModeInfo_t mode1_info; 36 PgVideoModeInfo_t mode2_info; 37 38 if (PgGetVideoModeInfo(*(unsigned short*)mode1, &mode1_info) < 0) 39 { 40 return 0; 41 } 42 43 if (PgGetVideoModeInfo(*(unsigned short*)mode2, &mode2_info) < 0) 44 { 45 return 0; 46 } 47 48 if (mode1_info.width == mode2_info.width) 49 { 50 return mode2_info.height - mode1_info.height; 51 } 52 else 53 { 54 return mode2_info.width - mode1_info.width; 55 } 56 } 57 58 SDL_Rect **ph_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags) 59 { 60 int i = 0; 61 int j = 0; 62 SDL_Rect Amodelist[PH_MAX_VIDEOMODES]; 63 64 for (i=0; i<PH_MAX_VIDEOMODES; i++) 65 { 66 SDL_modearray[i]=&SDL_modelist[i]; 67 } 68 69 if (PgGetVideoModeList(&mode_list) < 0) 70 { 71 SDL_SetError("ph_ListModes(): PgGetVideoModeList() function failed !\n"); 72 return NULL; 73 } 74 75 mode_info.bits_per_pixel = 0; 76 77 for (i=0; i < mode_list.num_modes; i++) 78 { 79 if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) 80 { 81 SDL_SetError("ph_ListModes(): PgGetVideoModeInfo() function failed on mode: 0x%X.\n", mode_list.modes[i]); 82 return NULL; 83 } 84 if(mode_info.bits_per_pixel == format->BitsPerPixel) 85 { 86 Amodelist[j].w = mode_info.width; 87 Amodelist[j].h = mode_info.height; 88 Amodelist[j].x = 0; 89 Amodelist[j].y = 0; 90 j++; 91 } 92 } 93 94 /* reorder biggest for smallest, assume width dominates */ 95 96 for(i=0; i<j; i++) 97 { 98 SDL_modelist[i].w = Amodelist[j - i - 1].w; 99 SDL_modelist[i].h = Amodelist[j - i - 1].h; 100 SDL_modelist[i].x = Amodelist[j - i - 1].x; 101 SDL_modelist[i].y = Amodelist[j - i - 1].y; 102 } 103 SDL_modearray[j]=NULL; 104 105 return SDL_modearray; 106 } 107 108 void ph_FreeVideoModes(_THIS) 109 { 110 return; 111 } 112 113 /* return the mode associated with width, height and bpp */ 114 /* if there is no mode then zero is returned */ 115 int ph_GetVideoMode(int width, int height, int bpp) 116 { 117 int i; 118 int modestage=0; 119 int closestmode=0; 120 121 if (PgGetVideoModeList(&mode_list) < 0) 122 { 123 return -1; 124 } 125 126 /* special case for the double-sized 320x200 mode */ 127 if ((width==640) && (height==400)) 128 { 129 modestage=1; 130 } 131 132 /* search list for exact match */ 133 for (i=0; i<mode_list.num_modes; i++) 134 { 135 if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) 136 { 137 return 0; 138 } 139 140 if ((mode_info.width == width) && (mode_info.height == height) && 141 (mode_info.bits_per_pixel == bpp)) 142 { 143 return mode_list.modes[i]; 144 } 145 else 146 { 147 if ((modestage) && (mode_info.width == width) && (mode_info.height == height+80) && 148 (mode_info.bits_per_pixel == bpp)) 149 { 150 modestage=2; 151 closestmode=mode_list.modes[i]; 152 } 153 } 154 } 155 156 /* if we are here, then no 640x400xbpp mode found and we'll emulate it via 640x480xbpp mode */ 157 if (modestage==2) 158 { 159 return closestmode; 160 } 161 162 return (i == mode_list.num_modes) ? 0 : mode_list.modes[i]; 163 } 164 165 /* return the mode associated with width, height and bpp */ 166 /* if requested bpp is not found the mode with closest bpp is returned */ 167 int get_mode_any_format(int width, int height, int bpp) 168 { 169 int i, closest, delta, min_delta; 170 171 if (PgGetVideoModeList(&mode_list) < 0) 172 { 173 return -1; 174 } 175 176 SDL_qsort(mode_list.modes, mode_list.num_modes, sizeof(unsigned short), compare_modes_by_res); 177 178 for(i=0;i<mode_list.num_modes;i++) 179 { 180 if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) 181 { 182 return 0; 183 } 184 if ((mode_info.width == width) && (mode_info.height == height)) 185 { 186 break; 187 } 188 } 189 190 if (i<mode_list.num_modes) 191 { 192 /* get closest bpp */ 193 closest = i++; 194 if (mode_info.bits_per_pixel == bpp) 195 { 196 return mode_list.modes[closest]; 197 } 198 199 min_delta = abs(mode_info.bits_per_pixel - bpp); 200 201 while(1) 202 { 203 if (PgGetVideoModeInfo(mode_list.modes[i], &mode_info) < 0) 204 { 205 return 0; 206 } 207 208 if ((mode_info.width != width) || (mode_info.height != height)) 209 { 210 break; 211 } 212 else 213 { 214 if (mode_info.bits_per_pixel == bpp) 215 { 216 closest = i; 217 break; 218 } 219 else 220 { 221 delta = abs(mode_info.bits_per_pixel - bpp); 222 if (delta < min_delta) 223 { 224 closest = i; 225 min_delta = delta; 226 } 227 i++; 228 } 229 } 230 } 231 return mode_list.modes[closest]; 232 } 233 234 return 0; 235 } 236 237 int ph_ToggleFullScreen(_THIS, int on) 238 { 239 return -1; 240 } 241 242 int ph_EnterFullScreen(_THIS, SDL_Surface* screen, int fmode) 243 { 244 PgDisplaySettings_t settings; 245 int mode; 246 char* refreshrate; 247 int refreshratenum; 248 249 if (!currently_fullscreen) 250 { 251 /* Get the video mode and set it */ 252 if (screen->flags & SDL_ANYFORMAT) 253 { 254 if ((mode = get_mode_any_format(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) 255 { 256 SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); 257 return 0; 258 } 259 } 260 else 261 { 262 if ((mode = ph_GetVideoMode(screen->w, screen->h, screen->format->BitsPerPixel)) == 0) 263 { 264 SDL_SetError("ph_EnterFullScreen(): can't find appropriate video mode !\n"); 265 return 0; 266 } 267 if (PgGetVideoModeInfo(mode, &mode_info) < 0) 268 { 269 SDL_SetError("ph_EnterFullScreen(): can't get video mode capabilities !\n"); 270 return 0; 271 } 272 if (mode_info.height != screen->h) 273 { 274 if ((mode_info.height==480) && (screen->h==400)) 275 { 276 videomode_emulatemode=1; 277 } 278 } 279 else 280 { 281 videomode_emulatemode=0; 282 } 283 } 284 285 /* save old video mode caps */ 286 PgGetVideoMode(&settings); 287 old_video_mode=settings.mode; 288 old_refresh_rate=settings.refresh; 289 290 /* setup new video mode */ 291 settings.mode = mode; 292 settings.refresh = 0; 293 settings.flags = 0; 294 295 refreshrate=SDL_getenv("SDL_PHOTON_FULLSCREEN_REFRESH"); 296 if (refreshrate!=NULL) 297 { 298 if (SDL_sscanf(refreshrate, "%d", &refreshratenum)==1) 299 { 300 settings.refresh = refreshratenum; 301 } 302 } 303 304 if (PgSetVideoMode(&settings) < 0) 305 { 306 SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n"); 307 return 0; 308 } 309 310 if (this->screen) 311 { 312 if ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL) 313 { 314 #if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) 315 return 0; /* 6.3.0 */ 316 #endif 317 } 318 } 319 320 if (fmode==0) 321 { 322 if (OCImage.direct_context==NULL) 323 { 324 OCImage.direct_context=(PdDirectContext_t*)PdCreateDirectContext(); 325 if (!OCImage.direct_context) 326 { 327 SDL_SetError("ph_EnterFullScreen(): Can't create direct context !\n"); 328 ph_LeaveFullScreen(this); 329 return 0; 330 } 331 } 332 OCImage.oldDC=PdDirectStart(OCImage.direct_context); 333 } 334 335 currently_fullscreen = 1; 336 } 337 PgFlush(); 338 339 return 1; 340 } 341 342 int ph_LeaveFullScreen(_THIS) 343 { 344 PgDisplaySettings_t oldmode_settings; 345 346 if (currently_fullscreen) 347 { 348 if ((this->screen) && ((this->screen->flags & SDL_OPENGL)==SDL_OPENGL)) 349 { 350 #if !SDL_VIDEO_OPENGL || (_NTO_VERSION < 630) 351 return 0; 352 #endif 353 } 354 355 /* release routines starts here */ 356 { 357 if (OCImage.direct_context) 358 { 359 PdDirectStop(OCImage.direct_context); 360 PdReleaseDirectContext(OCImage.direct_context); 361 OCImage.direct_context=NULL; 362 } 363 if (OCImage.oldDC) 364 { 365 PhDCSetCurrent(OCImage.oldDC); 366 OCImage.oldDC=NULL; 367 } 368 369 currently_fullscreen=0; 370 371 /* Restore old video mode */ 372 if (old_video_mode != -1) 373 { 374 oldmode_settings.mode = (unsigned short) old_video_mode; 375 oldmode_settings.refresh = (unsigned short) old_refresh_rate; 376 oldmode_settings.flags = 0; 377 378 if (PgSetVideoMode(&oldmode_settings) < 0) 379 { 380 SDL_SetError("Ph_LeaveFullScreen(): PgSetVideoMode() function failed !\n"); 381 return 0; 382 } 383 } 384 385 old_video_mode=-1; 386 old_refresh_rate=-1; 387 } 388 } 389 return 1; 390 } 391