first try

This commit is contained in:
thrust26 2023-08-17 18:18:15 +02:00
parent 8f0ea1a70b
commit 9e268dda0c
9 changed files with 106 additions and 19 deletions

View File

@ -268,6 +268,9 @@ class FBBackendSDL2 : public FBBackend
// Center setting of current window
bool myCenter{false};
// Flag for bezel mode
bool myShowBezel{false};
// Does the renderer support render targets?
bool myRenderTargetSupport{false};

View File

@ -48,6 +48,7 @@ FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
: myBackend{backend},
myInterpolationMode{inter}
{
//cerr << width << " x " << height << endl;
createSurface(width, height, staticData);
}
@ -233,6 +234,7 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
mySurface = SDL_CreateRGBSurface(0, width, height,
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
//SDL_SetSurfaceBlendMode(mySurface, SDL_BLENDMODE_ADD); // default: SDL_BLENDMODE_BLEND
// We start out with the src and dst rectangles containing the same
// dimensions, indicating no scaling or re-positioning

View File

@ -35,6 +35,7 @@ PNGLibrary::PNGLibrary(OSystem& osystem)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PNGLibrary::loadImage(const string& filename, FBSurface& surface, VariantList& metaData)
{
png_structp png_ptr{nullptr};
png_infop info_ptr{nullptr};
png_uint_32 iwidth{0}, iheight{0};

View File

@ -33,9 +33,10 @@ void VideoModeHandler::setDisplaySize(const Common::Size& display, Int32 fsIndex
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const VideoModeHandler::Mode&
VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
{
const bool windowedRequested = myFSIndex == -1;
const bool showBezel = inTIAMode&& settings.getBool("showbezel");
// TIA mode allows zooming at non-integral factors in most cases
if(inTIAMode)
@ -49,14 +50,14 @@ VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
// 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);
myFSIndex, desc.str(), zoom, showBezel);
}
else
{
const float overscan = 1 - settings.getInt("tia.fs_overscan") / 100.0;
// First calculate maximum zoom that keeps aspect ratio
const float scaleX = static_cast<float>(myImage.w) / myDisplay.w,
const float scaleX = myImage.w / myDisplay.w,
scaleY = static_cast<float>(myImage.h) / myDisplay.h;
float zoom = 1.F / std::max(scaleX, scaleY);
@ -67,17 +68,19 @@ VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
if(!settings.getBool("tia.fs_stretch")) // preserve aspect, use all space
{
myMode = Mode(myImage.w * zoom, myImage.h * zoom,
myMode = Mode(myImage.w * zoom, myImage.h * zoom,
myDisplay.w, myDisplay.h,
Mode::Stretch::Preserve, myFSIndex,
"Fullscreen: Preserve aspect, no stretch", zoom, overscan);
"Fullscreen: Preserve aspect, no stretch",
zoom, overscan, showBezel);
}
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);
"Fullscreen: Ignore aspect, full stretch",
zoom, overscan, showBezel);
}
}
}
@ -96,38 +99,41 @@ VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode,
Int32 fsindex, string_view desc,
float zoomLevel)
: Mode(iw, ih, iw, ih, smode, fsindex, desc, zoomLevel)
float zoomLevel, bool showBezel)
: Mode(iw, ih, iw, ih, smode, fsindex, desc, zoomLevel, 1.F, showBezel)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
Stretch smode, Int32 fsindex, string_view desc,
float zoomLevel, float overscan)
float zoomLevel, float overscan, bool showBezel)
: screenS{sw, sh},
stretch{smode},
description{desc},
zoom{zoomLevel},
fsIndex{fsindex}
{
const float scaleW = showBezel ? (16.F / 9.F) / (4.F / 3.F) : 1;
//const Int32 imageW = iw * scaleW;
//screenS.w = screenS.w * scaleW;
// Now resize based on windowed/fullscreen mode and stretch factor
if(fsIndex != -1) // fullscreen mode
{
switch(stretch)
{
case Stretch::Preserve:
iw *= overscan;
iw *= overscan / scaleW;
ih *= overscan;
break;
case Stretch::Fill:
// Scale to all available space
iw = screenS.w * overscan;
iw = screenS.w * (overscan / scaleW);
ih = screenS.h * overscan;
break;
case Stretch::None:
case Stretch::None: // UI Mode
// Don't do any scaling at all
iw = std::min(iw, screenS.w) * overscan;
ih = std::min(ih, screenS.h) * overscan;
@ -142,11 +148,11 @@ VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
{
case Stretch::Preserve:
case Stretch::Fill:
screenS.w = iw;
screenS.w = iw * scaleW;
screenS.h = ih;
break;
case Stretch::None:
case Stretch::None: // UI Mode
break; // Do not change image or screen rects whatsoever
}
}

View File

@ -50,9 +50,9 @@ class VideoModeHandler
Mode() = default;
Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode,
Int32 fsindex = -1, string_view desc = "",
float zoomLevel = 1.F, float overscan = 1.F);
float zoomLevel = 1.F, float overscan = 1.F, bool showBezel = false);
Mode(uInt32 iw, uInt32 ih, Stretch smode, Int32 fsindex = -1,
string_view desc = "", float zoomLevel = 1.F);
string_view desc = "", float zoomLevel = 1.F, bool showBezel = false);
friend ostream& operator<<(ostream& os, const Mode& vm)
{

View File

@ -27,6 +27,7 @@
#include "Sound.hxx"
#include "AudioSettings.hxx"
#include "MediaFactory.hxx"
#include "PNGLibrary.hxx"
#include "FBSurface.hxx"
#include "TIASurface.hxx"
@ -70,6 +71,8 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::~FrameBuffer() // NOLINT (we need an empty d'tor)
{
if(myBezelSurface)
deallocateSurface(myBezelSurface);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -605,6 +608,7 @@ void FrameBuffer::updateInEmulationMode(float framesPerSecond)
if(myMsg.enabled)
drawMessage();
myBezelSurface->render();
// Push buffers to screen
myBackend->renderToScreen();
}
@ -1303,6 +1307,23 @@ FBInitStatus FrameBuffer::applyVideoMode()
myOSystem.settings().setValue("tia.zoom", myActiveVidMode.zoom);
}
if(inTIAMode)
{
if(myBezelSurface)
deallocateSurface(myBezelSurface);
myBezelSurface = allocateSurface(
myActiveVidMode.screenS.w,
myActiveVidMode.screenS.h);
// Get a valid filename representing a snapshot file for this rom and load the snapshot
const string& path = myOSystem.snapshotLoadDir().getPath();
//loadBezel(path + "Atari-2600.png");
//loadBezel(path + "Combat.png");
loadBezel(path + "Asteroids (USA).png");
}
resetSurfaces();
setCursorState();
myPendingRender = true;
@ -1316,16 +1337,61 @@ FBInitStatus FrameBuffer::applyVideoMode()
return status;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::loadBezel(const string& fileName)
{
try
{
VariantList metaData;
myOSystem.png().loadImage(fileName, *myBezelSurface, metaData);
// Scale surface to available image area
const Common::Rect& src = myBezelSurface->srcRect();
const float scale = std::min(
static_cast<float>(myActiveVidMode.screenS.w) / src.w(),
static_cast<float>(myActiveVidMode.screenS.h) / src.h()
) * myOSystem.frameBuffer().hidpiScaleFactor();
myBezelSurface->setDstSize(
static_cast<uInt32>(std::round(src.w() * scale)),
static_cast<uInt32>(round(src.h() * scale)));
//myActiveVidMode.screenS.w,
//myActiveVidMode.screenS.h);
myBezelSurface->setScalingInterpolation(ScalingInterpolation::sharp);
//Int32 w = round(src.w() * scale);
//Int32 h = round(src.h() * scale);
//cerr << scale << ": " << w << " x " << h << endl;
//// temp workaround:
//FBSurface::Attributes& attr = myBezelSurface->attributes();
//attr.blendalpha = 50; // 0..100
//attr.blending = true;
//myBezelSurface->applyAttributes();
////SDL_SetSurfaceBlendMode(myBezelSurface, SDL_BLENDMODE_BLEND);
if(myBezelSurface)
myBezelSurface->setVisible(true);
}
catch(const runtime_error&)
{
return false;
}
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
float FrameBuffer::maxWindowZoom() const
{
const int display = displayId(BufferType::Emulator);
float multiplier = 1;
const bool showBezel = myOSystem.settings().getBool("showbezel");
const double scaleW = showBezel ? (16. / 9.) / (4. / 3.) : 1; // = 1.333
for(;;)
{
// Figure out the zoomed size of the window
const uInt32 width = TIAConstants::viewableWidth * multiplier;
const uInt32 width = TIAConstants::viewableWidth * multiplier * scaleW;
const uInt32 height = TIAConstants::viewableHeight * multiplier;
if((width > myAbsDesktopSize[display].w) || (height > myAbsDesktopSize[display].h))

View File

@ -443,6 +443,11 @@ class FrameBuffer
*/
FBInitStatus applyVideoMode();
/**
Load the bezel for the given ROM filename.
*/
bool loadBezel(const string& romFileName);
/**
Calculate the maximum level by which the base window can be zoomed and
still fit in the desktop screen.
@ -519,7 +524,10 @@ class FrameBuffer
#endif
// The TIASurface class takes responsibility for TIA rendering
unique_ptr<TIASurface> myTIASurface;
shared_ptr<TIASurface> myTIASurface;
// The BezelSurface class takes responsibility for TIA rendering
shared_ptr<FBSurface> myBezelSurface;
// Used for onscreen messages and frame statistics
// (scanline count and framerate)

View File

@ -62,6 +62,7 @@ Settings::Settings()
setPermanent("display", 0);
setPermanent("uimessages", "true");
setPermanent("pausedim", "true");
setPermanent("showbezel", "true");
// TIA specific options
setPermanent("tia.inter", "false");
setPermanent("tia.zoom", "3");

View File

@ -432,7 +432,7 @@ void TIASurface::createScanlineSurface()
mySLineSurface = myFB.allocateSurface(width, height,
interpolationModeFromSettings(myOSystem.settings()), data.data());
mySLineSurface->setSrcSize(mySLineSurface->width(), height);
//mySLineSurface->setSrcSize(mySLineSurface->width(), height);
mySLineSurface->setDstRect(myTiaSurface->dstRect());
updateSurfaceSettings();