mirror of https://github.com/stella-emu/stella.git
166 lines
5.2 KiB
C++
166 lines
5.2 KiB
C++
//============================================================================
|
|
//
|
|
// SSSS tt lll lll
|
|
// SS SS tt ll ll
|
|
// SS tttttt eeee ll ll aaaa
|
|
// SSSS tt ee ee ll ll aa
|
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
// SS SS tt ee ll ll aa aa
|
|
// SSSS ttt eeeee llll llll aaaaa
|
|
//
|
|
// Copyright (c) 1995-2020 by Bradford W. Mott, Stephen Anthony
|
|
// and the Stella Team
|
|
//
|
|
// See the file "License.txt" for information on usage and redistribution of
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
//============================================================================
|
|
|
|
#include "Settings.hxx"
|
|
#include "VideoModeHandler.hxx"
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void VideoModeHandler::setImageSize(const Common::Size& image)
|
|
{
|
|
myImage = image;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
void VideoModeHandler::setDisplaySize(const Common::Size& display, Int32 fsIndex)
|
|
{
|
|
myDisplay = display;
|
|
myFSIndex = fsIndex;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
const VideoModeHandler::Mode&
|
|
VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
|
|
{
|
|
const bool windowedRequested = myFSIndex == -1;
|
|
|
|
// TIA mode allows zooming at non-integral factors in most cases
|
|
if(inTIAMode)
|
|
{
|
|
if(windowedRequested)
|
|
{
|
|
const float zoom = settings.getFloat("tia.zoom");
|
|
ostringstream desc;
|
|
desc << (zoom * 100) << "%";
|
|
|
|
// Image and screen (aka window) dimensions are the same
|
|
// Overscan is not applicable in this mode
|
|
myMode = Mode(myImage.w * zoom, myImage.h * zoom, Mode::Stretch::Fill,
|
|
myFSIndex, desc.str(), zoom);
|
|
}
|
|
else
|
|
{
|
|
const float overscan = 1 - settings.getInt("tia.fs_overscan") / 100.0;
|
|
|
|
// First calculate maximum zoom that keeps aspect ratio
|
|
const float scaleX = float(myImage.w) / myDisplay.w,
|
|
scaleY = float(myImage.h) / myDisplay.h;
|
|
float zoom = 1.F / std::max(scaleX, scaleY);
|
|
|
|
// When aspect ratio correction is off, we want pixel-exact images,
|
|
// so we default to integer zooming
|
|
if(!settings.getBool("tia.correct_aspect"))
|
|
zoom = static_cast<uInt32>(zoom);
|
|
|
|
if(!settings.getBool("tia.fs_stretch")) // preserve aspect, use all space
|
|
{
|
|
myMode = Mode(myImage.w * zoom, myImage.h * zoom,
|
|
myDisplay.w, myDisplay.h,
|
|
Mode::Stretch::Preserve, myFSIndex,
|
|
"Fullscreen: Preserve aspect, no stretch", zoom, overscan);
|
|
}
|
|
else // ignore aspect, use all space
|
|
{
|
|
myMode = Mode(myImage.w * zoom, myImage.h * zoom,
|
|
myDisplay.w, myDisplay.h,
|
|
Mode::Stretch::Fill, myFSIndex,
|
|
"Fullscreen: Ignore aspect, full stretch", zoom, overscan);
|
|
}
|
|
}
|
|
}
|
|
else // UI mode (no zooming)
|
|
{
|
|
if(windowedRequested)
|
|
myMode = Mode(myImage.w, myImage.h, Mode::Stretch::None);
|
|
else
|
|
myMode = Mode(myImage.w, myImage.h, myDisplay.w, myDisplay.h,
|
|
Mode::Stretch::None, myFSIndex);
|
|
}
|
|
|
|
return myMode;
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode,
|
|
Int32 fsindex, const string& desc,
|
|
float zoomLevel)
|
|
: Mode(iw, ih, iw, ih, smode, fsindex, desc, zoomLevel)
|
|
{
|
|
}
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
|
|
Stretch smode, Int32 fsindex, const string& desc,
|
|
float zoomLevel, float overscan)
|
|
: stretch(smode),
|
|
description(desc),
|
|
zoom(zoomLevel),
|
|
fsIndex(fsindex)
|
|
{
|
|
// First set default size and positioning
|
|
screenS = Common::Size(sw, sh);
|
|
|
|
// Now resize based on windowed/fullscreen mode and stretch factor
|
|
if(fsIndex != -1) // fullscreen mode
|
|
{
|
|
switch(stretch)
|
|
{
|
|
case Stretch::Preserve:
|
|
iw *= overscan;
|
|
ih *= overscan;
|
|
break;
|
|
|
|
case Stretch::Fill:
|
|
// Scale to all available space
|
|
iw = screenS.w * overscan;
|
|
ih = screenS.h * overscan;
|
|
break;
|
|
|
|
case Stretch::None:
|
|
// Don't do any scaling at all
|
|
iw = std::min(iw, screenS.w) * overscan;
|
|
ih = std::min(ih, screenS.h) * overscan;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// In windowed mode, currently the size is scaled to the screen
|
|
// TODO - this may be updated if/when we allow variable-sized windows
|
|
switch(stretch)
|
|
{
|
|
case Stretch::Preserve:
|
|
case Stretch::Fill:
|
|
screenS.w = iw;
|
|
screenS.h = ih;
|
|
break;
|
|
|
|
case Stretch::None:
|
|
break; // Do not change image or screen rects whatsoever
|
|
}
|
|
}
|
|
|
|
// Now re-calculate the dimensions
|
|
iw = std::min(iw, screenS.w);
|
|
ih = std::min(ih, screenS.h);
|
|
|
|
imageR.moveTo((screenS.w - iw) >> 1, (screenS.h - ih) >> 1);
|
|
imageR.setWidth(iw);
|
|
imageR.setHeight(ih);
|
|
|
|
screenR = Common::Rect(screenS);
|
|
}
|