From 2e8b31245662400d9a9abb9c3c8bd2ed2f963d4a Mon Sep 17 00:00:00 2001
From: Bertrand Augereau <tramb@schneck.localdomain>
Date: Sat, 8 Aug 2009 16:25:59 +0200
Subject: [PATCH] Option "desired_screen_aspect_ratio" for fullscreen mode in the SDL backend
Shortcoming: the picture is not centered
---
backends/platform/sdl/graphics.cpp | 58 ++++++++++++++++++++++++++++++++---
backends/platform/sdl/sdl.cpp | 26 ++++++++++++++++
backends/platform/sdl/sdl.h | 14 ++++++++
base/commandLine.cpp | 1 +
4 files changed, 94 insertions(+), 5 deletions(-)
diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp
index ffdcd67..e629425 100644
a
|
b
|
void OSystem_SDL::initSize(uint w, uint h) {
|
358 | 358 | _dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32)); |
359 | 359 | } |
360 | 360 | |
| 361 | |
| 362 | static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int *width, int *height) { |
| 363 | assert(width && height); |
| 364 | |
| 365 | if (desiredAspectRatio.isAuto()) |
| 366 | return; |
| 367 | |
| 368 | int kx = desiredAspectRatio.kw(); |
| 369 | int ky = desiredAspectRatio.kh(); |
| 370 | |
| 371 | const int w = *width; |
| 372 | const int h = *height; |
| 373 | |
| 374 | SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_SWSURFACE); //TODO : Maybe specify a pixel format |
| 375 | assert(availableModes); |
| 376 | |
| 377 | const SDL_Rect *bestMode = NULL; |
| 378 | uint bestMetric = (uint)-1; // Metric is wasted space |
| 379 | while (const SDL_Rect *mode = *availableModes++) { |
| 380 | if (mode->w < w) |
| 381 | continue; |
| 382 | if (mode->h < h) |
| 383 | continue; |
| 384 | if (mode->h * kx != mode->w * ky) |
| 385 | continue; |
| 386 | //printf("%d %d\n", mode->w, mode->h); |
| 387 | |
| 388 | uint metric = mode->w * mode->h - w * h; |
| 389 | if (metric > bestMetric) |
| 390 | continue; |
| 391 | |
| 392 | bestMetric = metric; |
| 393 | bestMode = mode; |
| 394 | } |
| 395 | |
| 396 | if (!bestMode) { |
| 397 | warning("Unable to enforce the desired aspect ratio!"); |
| 398 | return; |
| 399 | } |
| 400 | //printf("%d %d\n", bestMode->w, bestMode->h); |
| 401 | *width = bestMode->w; |
| 402 | *height = bestMode->h; |
| 403 | } |
| 404 | |
361 | 405 | bool OSystem_SDL::loadGFXMode() { |
362 | 406 | assert(_inited); |
363 | 407 | _forceFull = true; |
… |
… |
bool OSystem_SDL::loadGFXMode() {
|
374 | 418 | if (_videoMode.aspectRatioCorrection) |
375 | 419 | _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight); |
376 | 420 | |
377 | | hwW = _videoMode.screenWidth * _videoMode.scaleFactor; |
378 | | hwH = effectiveScreenHeight(); |
| 421 | _videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor; |
| 422 | _videoMode.hardwareHeight = effectiveScreenHeight(); |
379 | 423 | #else |
380 | | hwW = _videoMode.overlayWidth; |
381 | | hwH = _videoMode.overlayHeight; |
| 424 | _videoMode.hardwareWidth = _videoMode.overlayWidth; |
| 425 | _videoMode.hardwareHeight = _videoMode.overlayHeight; |
382 | 426 | #endif |
383 | 427 | |
384 | 428 | // |
… |
… |
bool OSystem_SDL::loadGFXMode() {
|
392 | 436 | // Create the surface that contains the scaled graphics in 16 bit mode |
393 | 437 | // |
394 | 438 | |
395 | | _hwscreen = SDL_SetVideoMode(hwW, hwH, 16, |
| 439 | if(_videoMode.fullscreen) { |
| 440 | fixupResolutionForAspectRatio(_videoMode.desiredAspectRatio, &_videoMode.hardwareWidth, &_videoMode.hardwareHeight); |
| 441 | } |
| 442 | |
| 443 | _hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, |
396 | 444 | _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE |
397 | 445 | ); |
398 | 446 | if (_hwscreen == NULL) { |
diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp
index 8972234..49b50f9 100644
a
|
b
|
static Uint32 timer_handler(Uint32 interval, void *param) {
|
85 | 85 | return interval; |
86 | 86 | } |
87 | 87 | |
| 88 | AspectRatio::AspectRatio(int w, int h) { |
| 89 | // TODO : Validation, primality testing and so on... |
| 90 | // Currently, we just ensure the program don't instantiate non-supported aspect ratios |
| 91 | _kw = w; |
| 92 | _kh = h; |
| 93 | } |
| 94 | |
| 95 | static const size_t AR_COUNT = 4; |
| 96 | static const char* desiredAspectRatioAsStrings[AR_COUNT] = { "auto", "4/3", "16/9", "16/10" }; |
| 97 | static const AspectRatio desiredAspectRatios[AR_COUNT] = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) }; |
| 98 | static AspectRatio retrieveDesiredAspectRatioFromConfig() { |
| 99 | Common::String desiredAspectRatio = ConfMan.get("desired_screen_aspect_ratio"); |
| 100 | |
| 101 | for (size_t i = 0; i < AR_COUNT; i++) { |
| 102 | assert(desiredAspectRatioAsStrings[i] != NULL); |
| 103 | |
| 104 | if (!scumm_stricmp(desiredAspectRatio.c_str(), desiredAspectRatioAsStrings[i])) { |
| 105 | return desiredAspectRatios[i]; |
| 106 | } |
| 107 | } |
| 108 | // TODO : Report a warning |
| 109 | return AspectRatio(0, 0); |
| 110 | } |
| 111 | |
88 | 112 | void OSystem_SDL::initBackend() { |
89 | 113 | assert(!_inited); |
90 | 114 | |
… |
… |
void OSystem_SDL::initBackend() {
|
124 | 148 | _videoMode.mode = GFX_DOUBLESIZE; |
125 | 149 | _videoMode.scaleFactor = 2; |
126 | 150 | _videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio"); |
| 151 | _videoMode.desiredAspectRatio = retrieveDesiredAspectRatioFromConfig(); |
127 | 152 | _scalerProc = Normal2x; |
128 | 153 | #else // for small screen platforms |
129 | 154 | _videoMode.mode = GFX_NORMAL; |
130 | 155 | _videoMode.scaleFactor = 1; |
131 | 156 | _videoMode.aspectRatioCorrection = false; |
| 157 | _videoMode.desiredAspectRatio = AR_AUTO; |
132 | 158 | _scalerProc = Normal1x; |
133 | 159 | #endif |
134 | 160 | _scalerType = 0; |
diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h
index 7498f48..2a5fda3 100644
a
|
b
|
enum {
|
70 | 70 | GFX_DOTMATRIX = 11 |
71 | 71 | }; |
72 | 72 | |
| 73 | class AspectRatio { |
| 74 | int _kw, _kh; |
| 75 | public: |
| 76 | AspectRatio() { _kw = _kh = 0; } |
| 77 | AspectRatio(int w, int h); |
| 78 | |
| 79 | bool isAuto() const { return (_kw | _kh) == 0; } |
| 80 | |
| 81 | int kw() const { return _kw; } |
| 82 | int kh() const { return _kh; } |
| 83 | }; |
| 84 | |
73 | 85 | |
74 | 86 | class OSystem_SDL : public BaseBackend { |
75 | 87 | public: |
… |
… |
protected:
|
268 | 280 | |
269 | 281 | bool fullscreen; |
270 | 282 | bool aspectRatioCorrection; |
| 283 | AspectRatio desiredAspectRatio; |
271 | 284 | |
272 | 285 | int mode; |
273 | 286 | int scaleFactor; |
274 | 287 | |
275 | 288 | int screenWidth, screenHeight; |
276 | 289 | int overlayWidth, overlayHeight; |
| 290 | int hardwareWidth, hardwareHeight; |
277 | 291 | }; |
278 | 292 | VideoState _videoMode, _oldVideoMode; |
279 | 293 | |
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 890d14d..086093e 100644
a
|
b
|
void registerDefaults() {
|
157 | 157 | ConfMan.registerDefault("aspect_ratio", false); |
158 | 158 | ConfMan.registerDefault("gfx_mode", "normal"); |
159 | 159 | ConfMan.registerDefault("render_mode", "default"); |
| 160 | ConfMan.registerDefault("desired_screen_aspect_ratio", "auto"); |
160 | 161 | |
161 | 162 | // Sound & Music |
162 | 163 | ConfMan.registerDefault("music_volume", 192); |