First pass at implementing 'hidpi' mode. For now, it is available with 'hidpi' option only from the commandline.

- This is still a WIP, but is already very usable; I can finally see the UI on my 4k monitor :)
This commit is contained in:
Stephen Anthony 2019-05-11 14:33:07 -02:30
parent fccd62607b
commit e7759048ca
7 changed files with 75 additions and 29 deletions

View File

@ -613,7 +613,7 @@ FBInitStatus Console::initializeVideo(bool full)
const string& title = string("Stella ") + STELLA_VERSION +
": \"" + myProperties.get(PropType::Cart_Name) + "\"";
fbstatus = myOSystem.frameBuffer().createDisplay(title,
TIAConstants::viewableWidth, TIAConstants::viewableHeight);
TIAConstants::viewableWidth, TIAConstants::viewableHeight, false);
if(fbstatus != FBInitStatus::Success)
return fbstatus;

View File

@ -53,6 +53,7 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
myStatsEnabled(false),
myLastScanlines(0),
myGrabMouse(false),
myHiDPIEnabled(false),
myCurrentModeList(nullptr)
{
}
@ -79,8 +80,22 @@ bool FrameBuffer::initialize()
query_h = s.h;
}
// Various parts of the codebase assume a minimum screen size
myDesktopSize.w = std::max(query_w, FBMinimum::Width);
myDesktopSize.h = std::max(query_h, FBMinimum::Height);
myAbsDesktopSize.w = std::max(query_w, FBMinimum::Width);
myAbsDesktopSize.h = std::max(query_h, FBMinimum::Height);
myDesktopSize = myAbsDesktopSize;
// Check for HiDPI mode (is it activated, and can we use it?)
myHiDPIEnabled = myOSystem.settings().getBool("hidpi") &&
((myAbsDesktopSize.w / 2) >= FBMinimum::Width) &&
((myAbsDesktopSize.h / 2) >= FBMinimum::Height);
// In HiDPI mode, the desktop resolution is essentially halved
// Later, the output is scaled and rendered in 2x mode
if(hidpiEnabled())
{
myDesktopSize.w = myAbsDesktopSize.w / hidpiScaleFactor();
myDesktopSize.h = myAbsDesktopSize.h / hidpiScaleFactor();
}
#ifdef GUI_SUPPORT
////////////////////////////////////////////////////////////////////
@ -121,12 +136,11 @@ bool FrameBuffer::initialize()
#endif
// Determine possible TIA windowed zoom levels
uInt32 minZoom = 2 * hidpiScaleFactor();
uInt32 maxZoom = maxWindowSizeForScreen(
TIAConstants::viewableWidth, TIAConstants::viewableHeight,
myDesktopSize.w, myDesktopSize.h);
// Figure our the smallest zoom level we can use
for(uInt32 zoom = 2; zoom <= maxZoom; ++zoom)
myAbsDesktopSize.w, myAbsDesktopSize.h);
for(uInt32 zoom = minZoom; zoom <= maxZoom; ++zoom)
{
ostringstream desc;
desc << "Zoom " << zoom << "x";
@ -166,11 +180,19 @@ void FrameBuffer::setUIPalette()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FBInitStatus FrameBuffer::createDisplay(const string& title,
uInt32 width, uInt32 height)
uInt32 width, uInt32 height,
bool honourHiDPI)
{
++myInitializedCount;
myScreenTitle = title;
// In HiDPI mode, all created displays must be scaled by 2x
if(honourHiDPI && hidpiEnabled())
{
width *= hidpiScaleFactor();
height *= hidpiScaleFactor();
}
// A 'windowed' system is defined as one where the window size can be
// larger than the screen size, as there's some sort of window manager
// that takes care of it (all current desktop systems fall in this category)
@ -245,9 +267,10 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
myMsg.counter = 0;
// Create surfaces for TIA statistics and general messages
const GUI::Font& f = hidpiEnabled() ? infoFont() : font();
myStatsMsg.color = kColorInfo;
myStatsMsg.w = font().getMaxCharWidth() * 40 + 3;
myStatsMsg.h = (font().getFontHeight() + 2) * 3;
myStatsMsg.w = f.getMaxCharWidth() * 40 + 3;
myStatsMsg.h = (f.getFontHeight() + 2) * 3;
if(!myStatsMsg.surface)
{
@ -427,7 +450,7 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
myMsg.w = font().getStringWidth(myMsg.text) + 10;
myMsg.h = font().getFontHeight() + 8;
myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
myMsg.surface->setDstSize(myMsg.w, myMsg.h);
myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
myMsg.position = position;
myMsg.enabled = true;
#endif
@ -439,7 +462,8 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
#ifdef GUI_SUPPORT
const ConsoleInfo& info = myOSystem.console().about();
int xPos = 2, yPos = 0;
const int dy = font().getFontHeight() + 2;
const GUI::Font& f = hidpiEnabled() ? infoFont() : font();
const int dy = f.getFontHeight() + 2;
ostringstream ss;
@ -456,7 +480,7 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
<< "Hz => "
<< info.DisplayFormat;
myStatsMsg.surface->drawString(font(), ss.str(), xPos, yPos,
myStatsMsg.surface->drawString(f, ss.str(), xPos, yPos,
myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor);
yPos += dy;
@ -468,7 +492,7 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
<< std::fixed << std::setprecision(0) << 100 * myOSystem.settings().getFloat("speed")
<< "% speed";
myStatsMsg.surface->drawString(font(), ss.str(), xPos, yPos,
myStatsMsg.surface->drawString(f, ss.str(), xPos, yPos,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
yPos += dy;
@ -477,10 +501,12 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
ss << info.BankSwitch;
if (myOSystem.settings().getBool("dev.settings")) ss << "| Developer";
myStatsMsg.surface->drawString(font(), ss.str(), xPos, yPos,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
myStatsMsg.surface->drawString(f, ss.str(), xPos, yPos,
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
myStatsMsg.surface->setDstPos(myImageRect.x() + 10, myImageRect.y() + 8);
myStatsMsg.surface->setDstSize(myStatsMsg.w * hidpiScaleFactor(),
myStatsMsg.h * hidpiScaleFactor());
myStatsMsg.surface->render();
#endif
}
@ -850,8 +876,9 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
if(tiaMode)
{
// TIA windowed modes
uInt32 minZoom = 2 * hidpiScaleFactor();
uInt32 maxZoom = maxWindowSizeForScreen(baseWidth, baseHeight,
myDesktopSize.w, myDesktopSize.h);
myAbsDesktopSize.w, myAbsDesktopSize.h);
#if 0 // FIXME - does this apply any longer??
// Aspect ratio
@ -861,7 +888,7 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
#endif
// Determine all zoom levels
for(uInt32 zoom = 2; zoom <= maxZoom; ++zoom)
for(uInt32 zoom = minZoom; zoom <= maxZoom; ++zoom)
{
ostringstream desc;
desc << "Zoom " << zoom << "x";

View File

@ -104,10 +104,14 @@ class FrameBuffer
@param title The title of the application / window
@param width The width of the framebuffer
@param height The height of the framebuffer
@param honourHiDPI If true, consult the 'hidpi' setting and enlarge
the display size accordingly; if false, use the
exact dimensions as given
@return Status of initialization (see FBInitStatus 'enum')
*/
FBInitStatus createDisplay(const string& title, uInt32 width, uInt32 height);
FBInitStatus createDisplay(const string& title, uInt32 width, uInt32 height,
bool honourHiDPI = true);
/**
Updates the display, which depending on the current mode could mean
@ -255,6 +259,13 @@ class FrameBuffer
*/
void stateChanged(EventHandlerState state);
/**
Answer whether hidpi mode is enabled. In this mode, all FBSurfaces
are scaled to 2x normal size.
*/
bool hidpiEnabled() const { return myHiDPIEnabled; }
uInt32 hidpiScaleFactor() const { return myHiDPIEnabled ? 2 : 1; }
#ifdef GUI_SUPPORT
/**
Get the font object(s) of the framebuffer
@ -498,8 +509,13 @@ class FrameBuffer
Common::Size myScreenSize;
// Maximum dimensions of the desktop area
// Note that this takes 'hidpi' mode into account, so in some cases
// it will be less than the absolute desktop size
Common::Size myDesktopSize;
// Maximum absolute dimensions of the desktop area
Common::Size myAbsDesktopSize;
// The resolution of the attached displays in fullscreen mode
// The primary display is typically the first in the array
// Windowed modes use myDesktopSize directly
@ -546,6 +562,7 @@ class FrameBuffer
uInt32 myLastScanlines;
bool myGrabMouse;
bool myHiDPIEnabled;
// The list of all available video modes for this framebuffer
VideoModeList* myCurrentModeList;

View File

@ -41,6 +41,7 @@ Settings::Settings()
setPermanent("center", "false");
setPermanent("palette", "standard");
setPermanent("uimessages", "true");
setPermanent("hidpi", "false");
// TIA specific options
setPermanent("tia.zoom", "3");

View File

@ -100,6 +100,9 @@ void Dialog::open()
_surface = instance().frameBuffer().allocateSurface(_w, _h);
_layer = parent().addDialog(this);
if(instance().frameBuffer().hidpiEnabled())
_surface->setDstSize(_w*2, _h*2);
center();
if(_myTabList.size())

View File

@ -459,11 +459,8 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod)
// Control-R (reload ROM listing)
if(StellaModTest::isControl(mod) && key == KBDK_R)
updateListing();
// FIXME - use the R77 define in the final release
// use the '1' define for testing
#if defined(RETRON77)
// #if 1
else
#if defined(RETRON77)
// handle keys used by R77
switch(key)
{
@ -489,10 +486,9 @@ void LauncherDialog::handleKeyDown(StellaKey key, StellaMod mod)
Dialog::handleKeyDown(key, mod);
break;
}
#else
else
#else
Dialog::handleKeyDown(key, mod);
#endif
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -110,7 +110,8 @@ void RomInfoWidget::parseProperties(const FilesystemNode& node)
// Scale surface to available image area
const Common::Rect& src = mySurface->srcRect();
float scale = std::min(float(myAvail.w) / src.width(), float(myAvail.h) / src.height());
float scale = std::min(float(myAvail.w) / src.width(), float(myAvail.h) / src.height()) *
instance().frameBuffer().hidpiScaleFactor();
mySurface->setDstSize(uInt32(src.width() * scale), uInt32(src.height() * scale));
mySurfaceIsValid = true;
}
@ -179,8 +180,9 @@ void RomInfoWidget::drawWidget(bool hilite)
if(mySurfaceIsValid)
{
const Common::Rect& dst = mySurface->dstRect();
uInt32 x = _x + ((_w - dst.width()) >> 1);
uInt32 y = _y + ((yoff - dst.height()) >> 1);
const uInt32 scale = instance().frameBuffer().hidpiScaleFactor();
uInt32 x = _x*scale + ((_w*scale - dst.width()) >> 1);
uInt32 y = _y*scale + ((yoff*scale - dst.height()) >> 1);
// Make sure when positioning the snapshot surface that we take
// the dialog surface position into account