mirror of https://github.com/stella-emu/stella.git
Started cleanup of FrameBuffer class.
- Moved Video mode stuff into separate class - Fix bug with aspect correction in fullscreen mode still giving graphical artifacts
This commit is contained in:
parent
7eece4e994
commit
e15d27dc96
|
@ -225,7 +225,8 @@ Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||
bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||
const VideoModeHandler::Mode& mode)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
|
|
@ -179,7 +179,8 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool setVideoMode(const string& title, const VideoMode& mode) override;
|
||||
bool activateVideoMode(const string& title,
|
||||
const VideoModeHandler::Mode& mode) override;
|
||||
|
||||
/**
|
||||
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef VERSION_HXX
|
||||
#define VERSION_HXX
|
||||
|
||||
#define STELLA_VERSION "6.3"
|
||||
#define STELLA_VERSION "6.4_pre"
|
||||
#define STELLA_BUILD "6180"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,164 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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
|
||||
screen = 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 = screen.w * overscan;
|
||||
ih = screen.h * overscan;
|
||||
break;
|
||||
|
||||
case Stretch::None:
|
||||
// Don't do any scaling at all
|
||||
iw = std::min(iw, screen.w) * overscan;
|
||||
ih = std::min(ih, screen.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:
|
||||
screen.w = iw;
|
||||
screen.h = ih;
|
||||
break;
|
||||
case Stretch::None:
|
||||
break; // Do not change image or screen rects whatsoever
|
||||
}
|
||||
}
|
||||
|
||||
// Now re-calculate the dimensions
|
||||
iw = std::min(iw, screen.w);
|
||||
ih = std::min(ih, screen.h);
|
||||
|
||||
image.moveTo((screen.w - iw) >> 1, (screen.h - ih) >> 1);
|
||||
image.setWidth(iw);
|
||||
image.setHeight(ih);
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
//============================================================================
|
||||
//
|
||||
// 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.
|
||||
//============================================================================
|
||||
|
||||
#ifndef VIDEO_MODE_HANDLER_HXX
|
||||
#define VIDEO_MODE_HANDLER_HXX
|
||||
|
||||
class Settings;
|
||||
|
||||
#include "Rect.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class VideoModeHandler
|
||||
{
|
||||
public:
|
||||
// Contains all relevant info for the dimensions of a video screen
|
||||
// Also takes care of the case when the image should be 'centered'
|
||||
// within the given screen:
|
||||
// 'image' is the image dimensions into the screen
|
||||
// 'screen' are the dimensions of the screen itself
|
||||
struct Mode
|
||||
{
|
||||
enum class Stretch {
|
||||
Preserve, // Stretch to fill all available space; preserve aspect ratio
|
||||
Fill, // Stretch to fill all available space
|
||||
None // No stretching (1x zoom)
|
||||
};
|
||||
|
||||
Common::Rect image;
|
||||
Common::Size screen;
|
||||
Stretch stretch{Mode::Stretch::None};
|
||||
string description;
|
||||
float zoom{1.F};
|
||||
Int32 fsIndex{-1}; // -1 indicates windowed mode
|
||||
|
||||
Mode() = default;
|
||||
Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode,
|
||||
Int32 fsindex = -1, const string& desc = "",
|
||||
float zoomLevel = 1.F, float overscan = 1.F);
|
||||
Mode(uInt32 iw, uInt32 ih, Stretch smode, Int32 fsindex = -1,
|
||||
const string& desc = "", float zoomLevel = 1.F);
|
||||
|
||||
friend ostream& operator<<(ostream& os, const Mode& vm)
|
||||
{
|
||||
os << "image=" << vm.image << " screen=" << vm.screen
|
||||
<< " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" :
|
||||
vm.stretch == Stretch::Fill ? "fill" : "none")
|
||||
<< " desc=" << vm.description << " zoom=" << vm.zoom
|
||||
<< " fsIndex= " << vm.fsIndex;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
VideoModeHandler() = default;
|
||||
|
||||
/**
|
||||
Set the base size of the image. Scaling can be applied to this,
|
||||
which will change the effective size.
|
||||
|
||||
@param image The base dimensions of the image
|
||||
*/
|
||||
void setImageSize(const Common::Size& image);
|
||||
|
||||
/**
|
||||
Set the size of the display. This could be either the desktop size,
|
||||
or the size of the monitor currently active.
|
||||
|
||||
@param display The dimensions of the enclosing display
|
||||
@param fsIndex Fullscreen mode in use (-1 indicates windowed mode)
|
||||
*/
|
||||
void setDisplaySize(const Common::Size& display, Int32 fsIndex = -1);
|
||||
|
||||
/**
|
||||
Build a video mode based on the given parameters, assuming that
|
||||
setImageSize and setDisplaySize have been previously called.
|
||||
|
||||
@param settings Used to query various options that affect video mode
|
||||
@param inTIAMode Whether the video mode is being used for TIA emulation
|
||||
|
||||
@return A video mode based on the given criteria
|
||||
*/
|
||||
const VideoModeHandler::Mode& buildMode(const Settings& settings, bool inTIAMode);
|
||||
|
||||
private:
|
||||
Common::Size myImage, myDisplay;
|
||||
Int32 myFSIndex{-1};
|
||||
|
||||
Mode myMode;
|
||||
|
||||
private:
|
||||
VideoModeHandler(const VideoModeHandler&) = delete;
|
||||
VideoModeHandler(VideoModeHandler&&) = delete;
|
||||
VideoModeHandler& operator=(const VideoModeHandler&) = delete;
|
||||
VideoModeHandler& operator=(const VideoModeHandler&&) = delete;
|
||||
};
|
||||
|
||||
#endif // VIDEO_MODE_HANDLER_HXX
|
|
@ -1,9 +1,12 @@
|
|||
MODULE := src/common
|
||||
|
||||
MODULE_OBJS := \
|
||||
src/common/AudioQueue.o \
|
||||
src/common/AudioSettings.o \
|
||||
src/common/Base.o \
|
||||
src/common/EventHandlerSDL2.o \
|
||||
src/common/FBSurfaceSDL2.o \
|
||||
src/common/FpsMeter.o \
|
||||
src/common/FrameBufferSDL2.o \
|
||||
src/common/FSNodeZIP.o \
|
||||
src/common/JoyMap.o \
|
||||
|
@ -19,14 +22,12 @@ MODULE_OBJS := \
|
|||
src/common/PNGLibrary.o \
|
||||
src/common/RewindManager.o \
|
||||
src/common/SoundSDL2.o \
|
||||
src/common/StateManager.o \
|
||||
src/common/TimerManager.o \
|
||||
src/common/ZipHandler.o \
|
||||
src/common/AudioQueue.o \
|
||||
src/common/AudioSettings.o \
|
||||
src/common/FpsMeter.o \
|
||||
src/common/ThreadDebugging.o \
|
||||
src/common/StaggeredLogger.o \
|
||||
src/common/StateManager.o \
|
||||
src/common/ThreadDebugging.o \
|
||||
src/common/TimerManager.o \
|
||||
src/common/VideoModeHandler.o \
|
||||
src/common/ZipHandler.o \
|
||||
src/common/repository/KeyValueRepositoryConfigfile.o \
|
||||
src/common/sdl_blitter/BilinearBlitter.o \
|
||||
src/common/sdl_blitter/QisBlitter.o \
|
||||
|
|
|
@ -622,6 +622,10 @@ FBInitStatus Console::initializeVideo(bool full)
|
|||
|
||||
if(full)
|
||||
{
|
||||
auto size = myOSystem.settings().getBool("tia.correct_aspect") ?
|
||||
Common::Size(TIAConstants::viewableWidth, TIAConstants::viewableHeight) :
|
||||
Common::Size(2 * myTIA->width(), myTIA->height());
|
||||
|
||||
uInt32 width, height;
|
||||
if (!myOSystem.settings().getBool("tia.correct_aspect")) {
|
||||
width = 2 * myTIA->width();
|
||||
|
|
|
@ -411,7 +411,7 @@ AdjustFunction EventHandler::getAdjustSetting(AdjustSetting setting)
|
|||
{
|
||||
// Audio & Video settings
|
||||
std::bind(&Sound::adjustVolume, &myOSystem.sound(), _1),
|
||||
std::bind(&FrameBuffer::selectVidMode, &myOSystem.frameBuffer(), _1),
|
||||
std::bind(&FrameBuffer::switchVideoMode, &myOSystem.frameBuffer(), _1),
|
||||
std::bind(&FrameBuffer::toggleFullscreen, &myOSystem.frameBuffer(), _1),
|
||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||
std::bind(&FrameBuffer::toggleAdaptRefresh, &myOSystem.frameBuffer(), _1),
|
||||
|
@ -693,7 +693,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
|
|||
case Event::VidmodeDecrease:
|
||||
if(pressed)
|
||||
{
|
||||
myOSystem.frameBuffer().selectVidMode(-1);
|
||||
myOSystem.frameBuffer().switchVideoMode(-1);
|
||||
myAdjustSetting = AdjustSetting::ZOOM;
|
||||
myAdjustActive = true;
|
||||
}
|
||||
|
@ -702,7 +702,7 @@ void EventHandler::handleEvent(Event::Type event, Int32 value, bool repeated)
|
|||
case Event::VidmodeIncrease:
|
||||
if(pressed)
|
||||
{
|
||||
myOSystem.frameBuffer().selectVidMode(+1);
|
||||
myOSystem.frameBuffer().switchVideoMode(+1);
|
||||
myAdjustSetting = AdjustSetting::ZOOM;
|
||||
myAdjustActive = true;
|
||||
}
|
||||
|
|
|
@ -104,9 +104,11 @@ bool FrameBuffer::initialize()
|
|||
#endif
|
||||
|
||||
// Determine possible TIA windowed zoom levels
|
||||
myTIAMaxZoom = maxZoomForScreen(
|
||||
TIAConstants::viewableWidth, TIAConstants::viewableHeight,
|
||||
myAbsDesktopSize.w, myAbsDesktopSize.h);
|
||||
myTIAMaxZoom = maxWindowZoom(TIAConstants::viewableWidth,
|
||||
TIAConstants::viewableHeight);
|
||||
float currentTIAZoom = myOSystem.settings().getFloat("tia.zoom");
|
||||
myOSystem.settings().setValue("tia.zoom",
|
||||
BSPF::clampw(currentTIAZoom, supportedTIAMinZoom(), myTIAMaxZoom));
|
||||
|
||||
setUIPalette();
|
||||
|
||||
|
@ -173,13 +175,13 @@ void FrameBuffer::setupFonts()
|
|||
// However, we have to make sure all Dialogs are sized using the fontsize.
|
||||
int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height;
|
||||
int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth;
|
||||
myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4.F, 2.F); // round to 25% steps, >= 200%
|
||||
// round to 25% steps, >= 200%
|
||||
myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4.F, 2.F);
|
||||
}
|
||||
|
||||
// The font used by the ROM launcher
|
||||
const string& lf = myOSystem.settings().getString("launcherfont");
|
||||
|
||||
|
||||
myLauncherFont = make_unique<GUI::Font>(getFontDesc(lf)); // 8x13
|
||||
}
|
||||
|
||||
|
@ -215,7 +217,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
|||
++myInitializedCount;
|
||||
myScreenTitle = title;
|
||||
|
||||
// In HiDPI mode, all created displays must be scaled by 2x
|
||||
// In HiDPI mode, all created displays must be scaled appropriately
|
||||
if(honourHiDPI && hidpiEnabled())
|
||||
{
|
||||
width *= hidpiScaleFactor();
|
||||
|
@ -232,7 +234,6 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
|||
// If the WINDOWED_SUPPORT macro is defined, we treat the system as the
|
||||
// former type; if not, as the latter type
|
||||
|
||||
bool useFullscreen = false;
|
||||
#ifdef WINDOWED_SUPPORT
|
||||
// We assume that a desktop of at least minimum acceptable size means that
|
||||
// we're running on a 'large' system, and the window size requirements
|
||||
|
@ -241,40 +242,37 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
|||
if(myDesktopSize.w < FBMinimum::Width && myDesktopSize.h < FBMinimum::Height &&
|
||||
(myDesktopSize.w < width || myDesktopSize.h < height))
|
||||
return FBInitStatus::FailTooLarge;
|
||||
|
||||
useFullscreen = myOSystem.settings().getBool("fullscreen");
|
||||
#else
|
||||
// Make sure this mode is even possible
|
||||
// We only really need to worry about it in non-windowed environments,
|
||||
// where requesting a window that's too large will probably cause a crash
|
||||
if(myDesktopSize.w < width || myDesktopSize.h < height)
|
||||
return FBInitStatus::FailTooLarge;
|
||||
|
||||
useFullscreen = true;
|
||||
#endif
|
||||
|
||||
// Set the available video modes for this framebuffer
|
||||
setAvailableVidModes(width, height);
|
||||
// Initialize video mode handler, so it can know what video modes are
|
||||
// appropriate for this framebuffer
|
||||
myVidModeHandler.setImageSize(Common::Size(width, height));
|
||||
|
||||
// Initialize video subsystem (make sure we get a valid mode)
|
||||
string pre_about = about();
|
||||
const FrameBuffer::VideoMode& mode = getSavedVidMode(useFullscreen);
|
||||
if(width <= mode.screen.w && height <= mode.screen.h)
|
||||
myActiveVidMode = buildVideoMode();
|
||||
if(width <= myActiveVidMode.screen.w && height <= myActiveVidMode.screen.h)
|
||||
{
|
||||
// Changing the video mode can take some time, during which the last
|
||||
// sound played may get 'stuck'
|
||||
// So we mute the sound until the operation completes
|
||||
bool oldMuteState = myOSystem.sound().mute(true);
|
||||
if(setVideoMode(myScreenTitle, mode))
|
||||
if(activateVideoMode(myScreenTitle, myActiveVidMode))
|
||||
{
|
||||
myImageRect = mode.image;
|
||||
myScreenSize = mode.screen;
|
||||
myScreenRect = Common::Rect(mode.screen);
|
||||
myImageRect = myActiveVidMode.image;
|
||||
myScreenSize = myActiveVidMode.screen;
|
||||
myScreenRect = Common::Rect(myActiveVidMode.screen);
|
||||
|
||||
// Inform TIA surface about new mode
|
||||
if(myOSystem.eventHandler().state() != EventHandlerState::LAUNCHER &&
|
||||
myOSystem.eventHandler().state() != EventHandlerState::DEBUGGER)
|
||||
myTIASurface->initialize(myOSystem.console(), mode);
|
||||
myTIASurface->initialize(myOSystem.console(), myActiveVidMode);
|
||||
|
||||
// Did we get the requested fullscreen state?
|
||||
myOSystem.settings().setValue("fullscreen", fullScreen());
|
||||
|
@ -835,8 +833,9 @@ void FrameBuffer::setPauseDelay()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
shared_ptr<FBSurface> FrameBuffer::allocateSurface(int w, int h, ScalingInterpolation interpolation,
|
||||
const uInt32* data)
|
||||
shared_ptr<FBSurface> FrameBuffer::allocateSurface(
|
||||
int w, int h, ScalingInterpolation interpolation, const uInt32* data
|
||||
)
|
||||
{
|
||||
// Add new surface to the list
|
||||
mySurfaceList.push_back(createSurface(w, h, interpolation, data));
|
||||
|
@ -1011,17 +1010,18 @@ void FrameBuffer::setFullscreen(bool enable)
|
|||
// So we mute the sound until the operation completes
|
||||
bool oldMuteState = myOSystem.sound().mute(true);
|
||||
|
||||
const VideoMode& mode = getSavedVidMode(enable);
|
||||
if(setVideoMode(myScreenTitle, mode))
|
||||
myOSystem.settings().setValue("fullscreen", enable);
|
||||
myActiveVidMode = buildVideoMode();
|
||||
if(activateVideoMode(myScreenTitle, myActiveVidMode))
|
||||
{
|
||||
myImageRect = mode.image;
|
||||
myScreenSize = mode.screen;
|
||||
myScreenRect = Common::Rect(mode.screen);
|
||||
myImageRect = myActiveVidMode.image;
|
||||
myScreenSize = myActiveVidMode.screen;
|
||||
myScreenRect = Common::Rect(myActiveVidMode.screen);
|
||||
|
||||
// Inform TIA surface about new mode
|
||||
if(myOSystem.eventHandler().state() != EventHandlerState::LAUNCHER &&
|
||||
myOSystem.eventHandler().state() != EventHandlerState::DEBUGGER)
|
||||
myTIASurface->initialize(myOSystem.console(), mode);
|
||||
myTIASurface->initialize(myOSystem.console(), myActiveVidMode);
|
||||
|
||||
// Did we get the requested fullscreen state?
|
||||
myOSystem.settings().setValue("fullscreen", fullScreen());
|
||||
|
@ -1035,7 +1035,7 @@ void FrameBuffer::setFullscreen(bool enable)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::toggleFullscreen(bool toggle)
|
||||
{
|
||||
switch (myOSystem.eventHandler().state())
|
||||
switch(myOSystem.eventHandler().state())
|
||||
{
|
||||
case EventHandlerState::LAUNCHER:
|
||||
case EventHandlerState::EMULATION:
|
||||
|
@ -1043,20 +1043,17 @@ void FrameBuffer::toggleFullscreen(bool toggle)
|
|||
case EventHandlerState::DEBUGGER:
|
||||
{
|
||||
const bool isFullscreen = toggle ? !fullScreen() : fullScreen();
|
||||
|
||||
setFullscreen(isFullscreen);
|
||||
|
||||
if (myBufferType != BufferType::Launcher)
|
||||
if(myBufferType != BufferType::Launcher)
|
||||
{
|
||||
ostringstream msg;
|
||||
const VideoMode& mode = getSavedVidMode(isFullscreen);
|
||||
|
||||
msg << "Fullscreen ";
|
||||
if(isFullscreen)
|
||||
msg << "enabled (" << refreshRate() << " Hz, ";
|
||||
else
|
||||
msg << "disabled (";
|
||||
msg << "Zoom " << mode.zoom * 100 << "%)";
|
||||
msg << "Zoom " << myActiveVidMode.zoom * 100 << "%)";
|
||||
|
||||
showMessage(msg.str());
|
||||
}
|
||||
|
@ -1122,7 +1119,7 @@ void FrameBuffer::changeOverscan(int direction)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::selectVidMode(int direction)
|
||||
void FrameBuffer::switchVideoMode(int direction)
|
||||
{
|
||||
EventHandlerState state = myOSystem.eventHandler().state();
|
||||
bool tiaMode = (state != EventHandlerState::DEBUGGER &&
|
||||
|
@ -1132,10 +1129,27 @@ void FrameBuffer::selectVidMode(int direction)
|
|||
if(!tiaMode)
|
||||
return;
|
||||
|
||||
if(direction == +1)
|
||||
myCurrentModeList->next();
|
||||
else if(direction == -1)
|
||||
myCurrentModeList->previous();
|
||||
if(!fullScreen())
|
||||
{
|
||||
// Windowed TIA modes support variable zoom levels
|
||||
float zoom = myOSystem.settings().getFloat("tia.zoom");
|
||||
if(direction == +1) zoom += ZOOM_STEPS;
|
||||
else if(direction == -1) zoom -= ZOOM_STEPS;
|
||||
|
||||
// Make sure the level is within the allowable desktop size
|
||||
zoom = BSPF::clampw(zoom, supportedTIAMinZoom(), myTIAMaxZoom);
|
||||
myOSystem.settings().setValue("tia.zoom", zoom);
|
||||
}
|
||||
else
|
||||
{
|
||||
// In fullscreen mode, there are only two modes, so direction
|
||||
// is irrelevant
|
||||
if(direction == +1 || direction == -1)
|
||||
{
|
||||
bool stretch = myOSystem.settings().getBool("tia.fs_stretch");
|
||||
myOSystem.settings().setValue("tia.fs_stretch", !stretch);
|
||||
}
|
||||
}
|
||||
|
||||
saveCurrentWindowPosition();
|
||||
|
||||
|
@ -1144,34 +1158,75 @@ void FrameBuffer::selectVidMode(int direction)
|
|||
// So we mute the sound until the operation completes
|
||||
bool oldMuteState = myOSystem.sound().mute(true);
|
||||
|
||||
const VideoMode& mode = myCurrentModeList->current();
|
||||
if(setVideoMode(myScreenTitle, mode))
|
||||
myActiveVidMode = buildVideoMode();
|
||||
if(activateVideoMode(myScreenTitle, myActiveVidMode))
|
||||
{
|
||||
myImageRect = mode.image;
|
||||
myScreenSize = mode.screen;
|
||||
myScreenRect = Common::Rect(mode.screen);
|
||||
myImageRect = myActiveVidMode.image;
|
||||
myScreenSize = myActiveVidMode.screen;
|
||||
myScreenRect = Common::Rect(myActiveVidMode.screen);
|
||||
|
||||
// Inform TIA surface about new mode
|
||||
myTIASurface->initialize(myOSystem.console(), mode);
|
||||
myTIASurface->initialize(myOSystem.console(), myActiveVidMode);
|
||||
|
||||
resetSurfaces();
|
||||
if(fullScreen())
|
||||
showMessage(mode.description);
|
||||
showMessage(myActiveVidMode.description);
|
||||
else
|
||||
showMessage("Zoom", mode.description, mode.zoom, supportedTIAMinZoom(), myTIAMaxZoom);
|
||||
showMessage("Zoom", myActiveVidMode.description, myActiveVidMode.zoom,
|
||||
supportedTIAMinZoom(), myTIAMaxZoom);
|
||||
myOSystem.sound().mute(oldMuteState);
|
||||
|
||||
// Error check: were the settings applied as requested?
|
||||
if(fullScreen())
|
||||
myOSystem.settings().setValue("tia.fs_stretch",
|
||||
mode.stretch == VideoMode::Stretch::Fill);
|
||||
myActiveVidMode.stretch == VideoModeHandler::Mode::Stretch::Fill);
|
||||
else
|
||||
myOSystem.settings().setValue("tia.zoom", mode.zoom);
|
||||
myOSystem.settings().setValue("tia.zoom", myActiveVidMode.zoom);
|
||||
|
||||
return;
|
||||
}
|
||||
myOSystem.sound().mute(oldMuteState);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const VideoModeHandler::Mode& FrameBuffer::buildVideoMode()
|
||||
{
|
||||
// Update display size, in case windowed/fullscreen mode has changed
|
||||
const Settings& s = myOSystem.settings();
|
||||
if(s.getBool("fullscreen"))
|
||||
{
|
||||
Int32 fsIndex = std::max(getCurrentDisplayIndex(), 0);
|
||||
myVidModeHandler.setDisplaySize(myFullscreenDisplays[fsIndex], fsIndex);
|
||||
}
|
||||
else
|
||||
myVidModeHandler.setDisplaySize(myAbsDesktopSize);
|
||||
|
||||
// And now build the new mode based on current settings
|
||||
const bool tiaMode =
|
||||
myOSystem.eventHandler().state() != EventHandlerState::DEBUGGER &&
|
||||
myOSystem.eventHandler().state() != EventHandlerState::LAUNCHER;
|
||||
|
||||
return myVidModeHandler.buildMode(s, tiaMode);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float FrameBuffer::maxWindowZoom(uInt32 baseWidth, uInt32 baseHeight) const
|
||||
{
|
||||
float multiplier = 1;
|
||||
for(;;)
|
||||
{
|
||||
// Figure out the zoomed size of the window
|
||||
uInt32 width = baseWidth * multiplier;
|
||||
uInt32 height = baseHeight * multiplier;
|
||||
|
||||
if((width > myAbsDesktopSize.w) || (height > myAbsDesktopSize.h))
|
||||
break;
|
||||
|
||||
multiplier += ZOOM_STEPS;
|
||||
}
|
||||
return multiplier > 1 ? multiplier - ZOOM_STEPS : 1;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::setCursorState()
|
||||
{
|
||||
|
@ -1234,296 +1289,6 @@ void FrameBuffer::toggleGrabMouse()
|
|||
: "Grab mouse not allowed while cursor shown");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float FrameBuffer::maxZoomForScreen(uInt32 baseWidth, uInt32 baseHeight,
|
||||
uInt32 screenWidth, uInt32 screenHeight) const
|
||||
{
|
||||
float multiplier = 1;
|
||||
for(;;)
|
||||
{
|
||||
// Figure out the zoomed size of the window
|
||||
uInt32 width = baseWidth * multiplier;
|
||||
uInt32 height = baseHeight * multiplier;
|
||||
|
||||
if((width > screenWidth) || (height > screenHeight))
|
||||
break;
|
||||
|
||||
multiplier += ZOOM_STEPS;
|
||||
}
|
||||
return multiplier > 1 ? multiplier - ZOOM_STEPS : 1;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
|
||||
{
|
||||
myWindowedModeList.clear();
|
||||
|
||||
for(auto& mode: myFullscreenModeLists)
|
||||
mode.clear();
|
||||
for(size_t i = myFullscreenModeLists.size(); i < myFullscreenDisplays.size(); ++i)
|
||||
myFullscreenModeLists.emplace_back(VideoModeList());
|
||||
|
||||
// Check if zooming is allowed for this state (currently only allowed
|
||||
// for TIA screens)
|
||||
EventHandlerState state = myOSystem.eventHandler().state();
|
||||
bool tiaMode = (state != EventHandlerState::DEBUGGER &&
|
||||
state != EventHandlerState::LAUNCHER);
|
||||
float overscan = 1 - myOSystem.settings().getInt("tia.fs_overscan") / 100.0;
|
||||
|
||||
// TIA mode allows zooming at integral factors in windowed modes,
|
||||
// and also non-integral factors in fullscreen mode
|
||||
if(tiaMode)
|
||||
{
|
||||
// TIA windowed modes
|
||||
float minZoom = supportedTIAMinZoom();
|
||||
myTIAMaxZoom = maxZoomForScreen(baseWidth, baseHeight,
|
||||
myAbsDesktopSize.w, myAbsDesktopSize.h);
|
||||
// Determine all zoom levels
|
||||
for(float zoom = minZoom; zoom <= myTIAMaxZoom; zoom += ZOOM_STEPS)
|
||||
{
|
||||
ostringstream desc;
|
||||
desc << (zoom * 100) << "%";
|
||||
|
||||
VideoMode mode(baseWidth*zoom, baseHeight*zoom, baseWidth*zoom, baseHeight*zoom,
|
||||
VideoMode::Stretch::Fill, 1.0, desc.str(), zoom);
|
||||
myWindowedModeList.add(mode);
|
||||
}
|
||||
|
||||
// TIA fullscreen mode
|
||||
for(uInt32 i = 0; i < myFullscreenDisplays.size(); ++i)
|
||||
{
|
||||
myTIAMaxZoom = maxZoomForScreen(baseWidth, baseHeight,
|
||||
myFullscreenDisplays[i].w * overscan,
|
||||
myFullscreenDisplays[i].h * overscan);
|
||||
|
||||
// Add both normal aspect and filled modes
|
||||
// It's easier to define them both now, and simply switch between
|
||||
// them when necessary
|
||||
VideoMode mode1(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom,
|
||||
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
|
||||
VideoMode::Stretch::Preserve, overscan,
|
||||
"Fullscreen: Preserve aspect, no stretch", myTIAMaxZoom, i);
|
||||
myFullscreenModeLists[i].add(mode1);
|
||||
VideoMode mode2(baseWidth * myTIAMaxZoom, baseHeight * myTIAMaxZoom,
|
||||
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
|
||||
VideoMode::Stretch::Fill, overscan,
|
||||
"Fullscreen: Ignore aspect, full stretch", myTIAMaxZoom, i);
|
||||
myFullscreenModeLists[i].add(mode2);
|
||||
}
|
||||
}
|
||||
else // UI mode
|
||||
{
|
||||
// Windowed and fullscreen mode differ only in screen size
|
||||
myWindowedModeList.add(
|
||||
VideoMode(baseWidth, baseHeight, baseWidth, baseHeight,
|
||||
VideoMode::Stretch::None)
|
||||
);
|
||||
for(uInt32 i = 0; i < myFullscreenDisplays.size(); ++i)
|
||||
{
|
||||
myFullscreenModeLists[i].add(
|
||||
VideoMode(baseWidth, baseHeight,
|
||||
myFullscreenDisplays[i].w, myFullscreenDisplays[i].h,
|
||||
VideoMode::Stretch::None, 1.0, "", 1, i)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
|
||||
{
|
||||
if(fullscreen)
|
||||
{
|
||||
Int32 i = getCurrentDisplayIndex();
|
||||
if(i < 0)
|
||||
{
|
||||
// default to the first display
|
||||
i = 0;
|
||||
}
|
||||
myCurrentModeList = &myFullscreenModeLists[i];
|
||||
}
|
||||
else
|
||||
myCurrentModeList = &myWindowedModeList;
|
||||
|
||||
// Now select the best resolution depending on the state
|
||||
// UI modes (launcher and debugger) have only one supported resolution
|
||||
// so the 'current' one is the only valid one
|
||||
EventHandlerState state = myOSystem.eventHandler().state();
|
||||
if(state == EventHandlerState::DEBUGGER || state == EventHandlerState::LAUNCHER)
|
||||
myCurrentModeList->setByZoom(1);
|
||||
else // TIA mode
|
||||
{
|
||||
if(fullscreen)
|
||||
myCurrentModeList->setByStretch(myOSystem.settings().getBool("tia.fs_stretch")
|
||||
? VideoMode::Stretch::Fill : VideoMode::Stretch::Preserve);
|
||||
else
|
||||
myCurrentModeList->setByZoom(myOSystem.settings().getFloat("tia.zoom"));
|
||||
}
|
||||
|
||||
return myCurrentModeList->current();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
//
|
||||
// VideoMode implementation
|
||||
//
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
|
||||
Stretch smode, float overscan, const string& desc,
|
||||
float zoomLevel, Int32 fsindex)
|
||||
: stretch(smode),
|
||||
description(desc),
|
||||
zoom(zoomLevel),
|
||||
fsIndex(fsindex)
|
||||
{
|
||||
// First set default size and positioning
|
||||
sw = std::max(sw, TIAConstants::viewableWidth);
|
||||
sh = std::max(sh, TIAConstants::viewableHeight);
|
||||
iw = std::min(iw, sw);
|
||||
ih = std::min(ih, sh);
|
||||
int ix = (sw - iw) >> 1;
|
||||
int iy = (sh - ih) >> 1;
|
||||
image = Common::Rect(ix, iy, ix+iw, iy+ih);
|
||||
screen = Common::Size(sw, sh);
|
||||
|
||||
// Now resize based on windowed/fullscreen mode and stretch factor
|
||||
iw = image.w();
|
||||
ih = image.h();
|
||||
|
||||
if(fsIndex != -1)
|
||||
{
|
||||
switch(stretch)
|
||||
{
|
||||
case Stretch::Preserve:
|
||||
{
|
||||
float stretchFactor = 1.0;
|
||||
float scaleX = float(iw) / screen.w;
|
||||
float scaleY = float(ih) / screen.h;
|
||||
|
||||
// Scale to all available space, keep aspect correct
|
||||
if(scaleX > scaleY)
|
||||
stretchFactor = float(screen.w) / iw;
|
||||
else
|
||||
stretchFactor = float(screen.h) / ih;
|
||||
|
||||
iw = uInt32(stretchFactor * iw) * overscan;
|
||||
ih = uInt32(stretchFactor * ih) * overscan;
|
||||
break;
|
||||
}
|
||||
|
||||
case Stretch::Fill:
|
||||
// Scale to all available space
|
||||
iw = screen.w * overscan;
|
||||
ih = screen.h * overscan;
|
||||
break;
|
||||
|
||||
case Stretch::None:
|
||||
// Don't do any scaling at all, but obey overscan
|
||||
iw = std::min(iw, screen.w) * overscan;
|
||||
ih = std::min(ih, screen.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:
|
||||
screen.w = iw;
|
||||
screen.h = ih;
|
||||
break;
|
||||
case Stretch::None:
|
||||
break; // Do not change image or screen rects whatsoever
|
||||
}
|
||||
}
|
||||
|
||||
// Now re-calculate the dimensions
|
||||
iw = std::min(iw, screen.w);
|
||||
ih = std::min(ih, screen.h);
|
||||
|
||||
image.moveTo((screen.w - iw) >> 1, (screen.h - ih) >> 1);
|
||||
image.setWidth(iw);
|
||||
image.setHeight(ih);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
//
|
||||
// VideoModeList implementation
|
||||
//
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::VideoModeList::add(const VideoMode& mode)
|
||||
{
|
||||
myModeList.emplace_back(mode);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::VideoModeList::clear()
|
||||
{
|
||||
myModeList.clear();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBuffer::VideoModeList::empty() const
|
||||
{
|
||||
return myModeList.empty();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 FrameBuffer::VideoModeList::size() const
|
||||
{
|
||||
return uInt32(myModeList.size());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::VideoModeList::previous()
|
||||
{
|
||||
--myIdx;
|
||||
if(myIdx < 0) myIdx = int(myModeList.size()) - 1;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const FrameBuffer::VideoMode& FrameBuffer::VideoModeList::current() const
|
||||
{
|
||||
return myModeList[myIdx];
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::VideoModeList::next()
|
||||
{
|
||||
myIdx = (myIdx + 1) % myModeList.size();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::VideoModeList::setByZoom(float zoom)
|
||||
{
|
||||
for(uInt32 i = 0; i < myModeList.size(); ++i)
|
||||
{
|
||||
if(myModeList[i].zoom == zoom)
|
||||
{
|
||||
myIdx = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
myIdx = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::VideoModeList::setByStretch(FrameBuffer::VideoMode::Stretch stretch)
|
||||
{
|
||||
for(uInt32 i = 0; i < myModeList.size(); ++i)
|
||||
{
|
||||
if(myModeList[i].stretch == stretch)
|
||||
{
|
||||
myIdx = i;
|
||||
return;
|
||||
}
|
||||
}
|
||||
myIdx = 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
/*
|
||||
Palette is defined as follows:
|
||||
|
|
|
@ -35,6 +35,7 @@ class TIASurface;
|
|||
#include "TIAConstants.hxx"
|
||||
#include "FrameBufferConstants.hxx"
|
||||
#include "EventHandlerConstants.hxx"
|
||||
#include "VideoModeHandler.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
/**
|
||||
|
@ -50,38 +51,7 @@ class TIASurface;
|
|||
class FrameBuffer
|
||||
{
|
||||
public:
|
||||
// Contains all relevant info for the dimensions of a video screen
|
||||
// Also takes care of the case when the image should be 'centered'
|
||||
// within the given screen:
|
||||
// 'image' is the image dimensions into the screen
|
||||
// 'screen' are the dimensions of the screen itself
|
||||
struct VideoMode
|
||||
{
|
||||
enum class Stretch { Preserve, Fill, None };
|
||||
|
||||
Common::Rect image;
|
||||
Common::Size screen;
|
||||
Stretch stretch{VideoMode::Stretch::None};
|
||||
string description;
|
||||
float zoom{1.F};
|
||||
Int32 fsIndex{-1};
|
||||
|
||||
VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
|
||||
Stretch smode, float overscan = 1.F,
|
||||
const string& desc = "", float zoomLevel = 1, Int32 fsindex = -1);
|
||||
|
||||
friend ostream& operator<<(ostream& os, const VideoMode& vm)
|
||||
{
|
||||
os << "image=" << vm.image << " screen=" << vm.screen
|
||||
<< " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" :
|
||||
vm.stretch == Stretch::Fill ? "fill" : "none")
|
||||
<< " desc=" << vm.description << " zoom=" << vm.zoom
|
||||
<< " fsIndex= " << vm.fsIndex;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
struct DisplayMode
|
||||
struct DisplayMode // FIXME - is this needed?
|
||||
{
|
||||
uInt32 display;
|
||||
Common::Size size;
|
||||
|
@ -259,11 +229,6 @@ class FrameBuffer
|
|||
*/
|
||||
TIASurface& tiaSurface() const { return *myTIASurface; }
|
||||
|
||||
/**
|
||||
Enables/disables fullscreen mode.
|
||||
*/
|
||||
void setFullscreen(bool enable);
|
||||
|
||||
/**
|
||||
Toggles between fullscreen and window mode.
|
||||
*/
|
||||
|
@ -285,15 +250,15 @@ class FrameBuffer
|
|||
|
||||
/**
|
||||
This method is called when the user wants to switch to the next
|
||||
available video mode. In windowed mode, this typically means going to
|
||||
the next/previous zoom level. In fullscreen mode, this typically means
|
||||
switching between normal aspect and fully filling the screen.
|
||||
available TIA video mode. In windowed mode, this typically means going
|
||||
to the next/previous zoom level. In fullscreen mode, this typically
|
||||
means switching between normal aspect and fully filling the screen.
|
||||
direction = -1 means go to the next lower video mode
|
||||
direction = +1 means go to the next higher video mode
|
||||
|
||||
@param direction +1 indicates increase, -1 indicates decrease.
|
||||
*/
|
||||
void selectVidMode(int direction = +1);
|
||||
void switchVideoMode(int direction = +1);
|
||||
|
||||
/**
|
||||
Sets the state of the cursor (hidden or grabbed) based on the
|
||||
|
@ -453,7 +418,6 @@ class FrameBuffer
|
|||
virtual int scaleY(int y) const { return y; }
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
This method is called to query and initialize the video hardware
|
||||
for desktop and fullscreen resolution information. Since several
|
||||
|
@ -475,8 +439,8 @@ class FrameBuffer
|
|||
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
virtual bool setVideoMode(const string& title,
|
||||
const FrameBuffer::VideoMode& mode) = 0;
|
||||
virtual bool activateVideoMode(const string& title,
|
||||
const VideoModeHandler::Mode& mode) = 0;
|
||||
|
||||
/**
|
||||
This method is called to create a surface with the given attributes.
|
||||
|
@ -547,6 +511,28 @@ class FrameBuffer
|
|||
*/
|
||||
bool drawMessage();
|
||||
|
||||
// Draws the frame stats overlay
|
||||
void drawFrameStats(float framesPerSecond);
|
||||
|
||||
/**
|
||||
Build an applicable video mode based on the current settings in
|
||||
effect, whether TIA mode is active, etc.
|
||||
Note that this only creates the video mode definition itself;
|
||||
to apply it, we need to call 'activateVideoMode()'.
|
||||
*/
|
||||
const VideoModeHandler::Mode& buildVideoMode();
|
||||
|
||||
/**
|
||||
Calculate the maximum level by which the base window can be zoomed and
|
||||
still fit in the desktop screen.
|
||||
*/
|
||||
float maxWindowZoom(uInt32 baseWidth, uInt32 baseHeight) const;
|
||||
|
||||
/**
|
||||
Enables/disables fullscreen mode.
|
||||
*/
|
||||
void setFullscreen(bool enable);
|
||||
|
||||
/**
|
||||
Frees and reloads all surfaces that the framebuffer knows about.
|
||||
*/
|
||||
|
@ -559,60 +545,6 @@ class FrameBuffer
|
|||
void setupFonts();
|
||||
#endif
|
||||
|
||||
/**
|
||||
Calculate the maximum level by which the base window can be zoomed and
|
||||
still fit in the given screen dimensions.
|
||||
*/
|
||||
float maxZoomForScreen(uInt32 baseWidth, uInt32 baseHeight,
|
||||
uInt32 screenWidth, uInt32 screenHeight) const;
|
||||
|
||||
/**
|
||||
Set all possible video modes (both windowed and fullscreen) available for
|
||||
this framebuffer based on given image dimensions and maximum window size.
|
||||
*/
|
||||
void setAvailableVidModes(uInt32 basewidth, uInt32 baseheight);
|
||||
|
||||
/**
|
||||
Returns an appropriate video mode based on the current eventhandler
|
||||
state, taking into account the maximum size of the window.
|
||||
|
||||
@param fullscreen Whether to use a windowed or fullscreen mode
|
||||
@return A valid VideoMode for this framebuffer
|
||||
*/
|
||||
const FrameBuffer::VideoMode& getSavedVidMode(bool fullscreen);
|
||||
|
||||
private:
|
||||
/**
|
||||
This class implements an iterator around an array of VideoMode objects.
|
||||
*/
|
||||
class VideoModeList
|
||||
{
|
||||
public:
|
||||
void add(const FrameBuffer::VideoMode& mode);
|
||||
void clear();
|
||||
|
||||
bool empty() const;
|
||||
uInt32 size() const;
|
||||
|
||||
void previous();
|
||||
const FrameBuffer::VideoMode& current() const;
|
||||
void next();
|
||||
|
||||
void setByZoom(float zoom);
|
||||
void setByStretch(FrameBuffer::VideoMode::Stretch stretch);
|
||||
|
||||
friend ostream& operator<<(ostream& os, const VideoModeList& l)
|
||||
{
|
||||
for(const auto& vm: l.myModeList)
|
||||
os << "-----\n" << vm << endl << "-----\n";
|
||||
return os;
|
||||
}
|
||||
|
||||
private:
|
||||
vector<FrameBuffer::VideoMode> myModeList;
|
||||
int myIdx{-1};
|
||||
};
|
||||
|
||||
protected:
|
||||
// Title of the main window/screen
|
||||
string myScreenTitle;
|
||||
|
@ -629,9 +561,6 @@ class FrameBuffer
|
|||
vector<Common::Size> myFullscreenDisplays;
|
||||
|
||||
private:
|
||||
// Draws the frame stats overlay
|
||||
void drawFrameStats(float framesPerSecond);
|
||||
|
||||
// Indicates the number of times the framebuffer was initialized
|
||||
uInt32 myInitializedCount{0};
|
||||
|
||||
|
@ -659,6 +588,10 @@ class FrameBuffer
|
|||
// Supported renderers
|
||||
VariantList myRenderers;
|
||||
|
||||
// The VideoModeHandler class takes responsibility for all video mode functionality
|
||||
VideoModeHandler myVidModeHandler;
|
||||
VideoModeHandler::Mode myActiveVidMode;
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
// The font object to use for the normal in-game GUI
|
||||
unique_ptr<GUI::Font> myFont;
|
||||
|
@ -699,11 +632,6 @@ class FrameBuffer
|
|||
bool myHiDPIAllowed{false};
|
||||
bool myHiDPIEnabled{false};
|
||||
|
||||
// The list of all available video modes for this framebuffer
|
||||
VideoModeList* myCurrentModeList{nullptr};
|
||||
VideoModeList myWindowedModeList;
|
||||
vector<VideoModeList> myFullscreenModeLists;
|
||||
|
||||
// Minimum TIA zoom level that can be used for this framebuffer
|
||||
float myTIAMinZoom{2.F};
|
||||
// Maximum TIA zoom level that can be used for this framebuffer
|
||||
|
@ -714,7 +642,7 @@ class FrameBuffer
|
|||
|
||||
FullPaletteArray myFullPalette;
|
||||
// Holds UI palette data (for each variation)
|
||||
static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette,
|
||||
static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette,
|
||||
ourLightUIPalette, ourDarkUIPalette;
|
||||
|
||||
private:
|
||||
|
|
|
@ -91,7 +91,7 @@ TIASurface::~TIASurface()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIASurface::initialize(const Console& console,
|
||||
const FrameBuffer::VideoMode& mode)
|
||||
const VideoModeHandler::Mode& mode)
|
||||
{
|
||||
myTIA = &(console.tia());
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ class TIASurface
|
|||
/**
|
||||
Set the TIA object, which is needed for actually rendering the TIA image.
|
||||
*/
|
||||
void initialize(const Console& console, const FrameBuffer::VideoMode& mode);
|
||||
void initialize(const Console& console, const VideoModeHandler::Mode& mode);
|
||||
|
||||
/**
|
||||
Set the palette for TIA rendering. This currently consists of two
|
||||
|
|
|
@ -147,7 +147,8 @@ class FrameBufferLIBRETRO : public FrameBuffer
|
|||
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool setVideoMode(const string& title, const VideoMode& mode) override { return true; }
|
||||
bool activateVideoMode(const string& title,
|
||||
const VideoModeHandler::Mode& mode) override { return true; }
|
||||
|
||||
/**
|
||||
This method is called to create a surface with the given attributes.
|
||||
|
|
|
@ -33,6 +33,7 @@ SOURCES_CXX := \
|
|||
$(CORE_DIR)/common/StaggeredLogger.cxx \
|
||||
$(CORE_DIR)/common/StateManager.cxx \
|
||||
$(CORE_DIR)/common/TimerManager.cxx \
|
||||
$(CORE_DIR)/common/VideoModeHandler.cxx \
|
||||
$(CORE_DIR)/common/tv_filters/AtariNTSC.cxx \
|
||||
$(CORE_DIR)/common/tv_filters/NTSCFilter.cxx \
|
||||
$(CORE_DIR)/emucore/AtariVox.cxx \
|
||||
|
|
Loading…
Reference in New Issue