mirror of https://github.com/stella-emu/stella.git
Fairly huge refactoring of FrameBuffer class into FBBackend and friends.
Only tested in Linux and libretro for now; Windows and Mac will follow soon.
This commit is contained in:
parent
d0448a431e
commit
b6d18845d8
|
@ -27,11 +27,11 @@
|
||||||
|
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "FBSurfaceSDL2.hxx"
|
#include "FBSurfaceSDL2.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
FBBackendSDL2::FBBackendSDL2(OSystem& osystem)
|
||||||
: FrameBuffer(osystem)
|
: myOSystem(osystem)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||||
Logger::error(buf.str());
|
Logger::error(buf.str());
|
||||||
throw runtime_error("FATAL ERROR");
|
throw runtime_error("FATAL ERROR");
|
||||||
}
|
}
|
||||||
Logger::debug("FrameBufferSDL2::FrameBufferSDL2 SDL_Init()");
|
Logger::debug("FBBackendSDL2::FBBackendSDL2 SDL_Init()");
|
||||||
|
|
||||||
// We need a pixel format for palette value calculations
|
// We need a pixel format for palette value calculations
|
||||||
// It's done this way (vs directly accessing a FBSurfaceSDL2 object)
|
// It's done this way (vs directly accessing a FBSurfaceSDL2 object)
|
||||||
|
@ -53,7 +53,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBufferSDL2::~FrameBufferSDL2()
|
FBBackendSDL2::~FBBackendSDL2()
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -61,12 +61,6 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
||||||
|
|
||||||
if(myRenderer)
|
if(myRenderer)
|
||||||
{
|
{
|
||||||
// Make sure to free surfaces/textures before destroying the renderer itself
|
|
||||||
// Most platforms are fine with doing this in either order, but it seems
|
|
||||||
// that OpenBSD in particular crashes when attempting to destroy textures
|
|
||||||
// *after* the renderer is already destroyed
|
|
||||||
freeSurfaces();
|
|
||||||
|
|
||||||
SDL_DestroyRenderer(myRenderer);
|
SDL_DestroyRenderer(myRenderer);
|
||||||
myRenderer = nullptr;
|
myRenderer = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -81,9 +75,9 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
void FBBackendSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
vector<Common::Size>& windowedRes,
|
vector<Common::Size>& windowedRes,
|
||||||
VariantList& renderers)
|
VariantList& renderers)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -105,7 +99,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
|
|
||||||
string lastRes = "";
|
string lastRes = "";
|
||||||
|
|
||||||
for (int m = 0; m < numModes; m++)
|
for(int m = 0; m < numModes; ++m)
|
||||||
{
|
{
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
ostringstream res;
|
ostringstream res;
|
||||||
|
@ -196,7 +190,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
bool FBBackendSDL2::isCurrentWindowPositioned() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -205,7 +199,7 @@ bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
Common::Point FBBackendSDL2::getCurrentWindowPos() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -217,7 +211,7 @@ Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
Int32 FBBackendSDL2::getCurrentDisplayIndex() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -225,8 +219,8 @@ Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::activateVideoMode(const string& title,
|
bool FBBackendSDL2::setVideoMode(const VideoModeHandler::Mode& mode,
|
||||||
const VideoModeHandler::Mode& mode)
|
int winIdx, const Common::Point& winPos)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -236,26 +230,22 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||||
|
|
||||||
const bool fullScreen = mode.fsIndex != -1;
|
const bool fullScreen = mode.fsIndex != -1;
|
||||||
bool forceCreateRenderer = false;
|
bool forceCreateRenderer = false;
|
||||||
|
Int32 displayIndex = std::min(myNumDisplays, winIdx);
|
||||||
// Get windowed window's last display
|
|
||||||
Int32 displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt(getDisplayKey()));
|
|
||||||
// Get windowed window's last position
|
|
||||||
myWindowedPos = myOSystem.settings().getPoint(getPositionKey());
|
|
||||||
|
|
||||||
int posX, posY;
|
int posX, posY;
|
||||||
|
|
||||||
myCenter = myOSystem.settings().getBool("center");
|
myCenter = myOSystem.settings().getBool("center");
|
||||||
if (myCenter)
|
if(myCenter)
|
||||||
posX = posY = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
posX = posY = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
posX = myWindowedPos.x;
|
posX = winPos.x;
|
||||||
posY = myWindowedPos.y;
|
posY = winPos.y;
|
||||||
|
|
||||||
// Make sure the window is at least partially visibile
|
// Make sure the window is at least partially visibile
|
||||||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
||||||
|
|
||||||
for (int display = SDL_GetNumVideoDisplays() - 1; display >= 0; display--)
|
for(int display = SDL_GetNumVideoDisplays() - 1; display >= 0; --display)
|
||||||
{
|
{
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
|
|
||||||
|
@ -273,16 +263,22 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||||
|
|
||||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||||
SDL_DisplayMode adaptedSdlMode;
|
SDL_DisplayMode adaptedSdlMode;
|
||||||
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
|
const int gameRefreshRate =
|
||||||
&& gameRefreshRate()
|
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||||
|
const bool shouldAdapt = fullScreen
|
||||||
|
&& myOSystem.settings().getBool("tia.fs_refresh")
|
||||||
|
&& gameRefreshRate
|
||||||
// take care of 59.94 Hz
|
// take care of 59.94 Hz
|
||||||
&& refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0;
|
&& refreshRate() % gameRefreshRate != 0
|
||||||
const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
|
&& refreshRate() % (gameRefreshRate - 1) != 0;
|
||||||
|
const bool adaptRefresh = shouldAdapt &&
|
||||||
|
adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||||
#else
|
#else
|
||||||
const bool adaptRefresh = false;
|
const bool adaptRefresh = false;
|
||||||
#endif
|
#endif
|
||||||
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
||||||
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN :
|
||||||
|
SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||||
|
|
||||||
// Don't re-create the window if its display and size hasn't changed,
|
// Don't re-create the window if its display and size hasn't changed,
|
||||||
// as it's not necessary, and causes flashing in fullscreen mode
|
// as it's not necessary, and causes flashing in fullscreen mode
|
||||||
|
@ -303,13 +299,13 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||||
if(myWindow)
|
if(myWindow)
|
||||||
{
|
{
|
||||||
// Even though window size stayed the same, the title may have changed
|
// Even though window size stayed the same, the title may have changed
|
||||||
SDL_SetWindowTitle(myWindow, title.c_str());
|
SDL_SetWindowTitle(myWindow, myScreenTitle.c_str());
|
||||||
SDL_SetWindowPosition(myWindow, posX, posY);
|
SDL_SetWindowPosition(myWindow, posX, posY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
forceCreateRenderer = true;
|
forceCreateRenderer = true;
|
||||||
myWindow = SDL_CreateWindow(title.c_str(), posX, posY,
|
myWindow = SDL_CreateWindow(myScreenTitle.c_str(), posX, posY,
|
||||||
mode.screenS.w, mode.screenS.h, flags);
|
mode.screenS.w, mode.screenS.h, flags);
|
||||||
if(myWindow == nullptr)
|
if(myWindow == nullptr)
|
||||||
{
|
{
|
||||||
|
@ -333,7 +329,8 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||||
{
|
{
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
|
|
||||||
msg << "Display refresh rate changed to " << adaptedSdlMode.refresh_rate << " Hz";
|
msg << "Display refresh rate changed to "
|
||||||
|
<< adaptedSdlMode.refresh_rate << " Hz";
|
||||||
Logger::info(msg.str());
|
Logger::info(msg.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,8 +340,11 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode)
|
bool FBBackendSDL2::adaptRefreshRate(Int32 displayIndex,
|
||||||
|
SDL_DisplayMode& adaptedSdlMode)
|
||||||
{
|
{
|
||||||
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
SDL_DisplayMode sdlMode;
|
SDL_DisplayMode sdlMode;
|
||||||
|
|
||||||
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
|
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
|
||||||
|
@ -354,7 +354,8 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
|
||||||
}
|
}
|
||||||
|
|
||||||
const int currentRefreshRate = sdlMode.refresh_rate;
|
const int currentRefreshRate = sdlMode.refresh_rate;
|
||||||
const int wantedRefreshRate = gameRefreshRate();
|
const int wantedRefreshRate =
|
||||||
|
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||||
// Take care of rounded refresh rates (e.g. 59.94 Hz)
|
// Take care of rounded refresh rates (e.g. 59.94 Hz)
|
||||||
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
|
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
|
||||||
float(currentRefreshRate) / (wantedRefreshRate - 1));
|
float(currentRefreshRate) / (wantedRefreshRate - 1));
|
||||||
|
@ -398,8 +399,10 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::createRenderer(bool force)
|
bool FBBackendSDL2::createRenderer(bool force)
|
||||||
{
|
{
|
||||||
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
// A new renderer is only created when necessary:
|
// A new renderer is only created when necessary:
|
||||||
// - new myWindow (force = true)
|
// - new myWindow (force = true)
|
||||||
// - no renderer existing
|
// - no renderer existing
|
||||||
|
@ -451,7 +454,7 @@ bool FrameBufferSDL2::createRenderer(bool force)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::setTitle(const string& title)
|
void FBBackendSDL2::setTitle(const string& title)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -462,7 +465,7 @@ void FrameBufferSDL2::setTitle(const string& title)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string FrameBufferSDL2::about() const
|
string FBBackendSDL2::about() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -484,7 +487,7 @@ string FrameBufferSDL2::about() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::showCursor(bool show)
|
void FBBackendSDL2::showCursor(bool show)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -492,7 +495,7 @@ void FrameBufferSDL2::showCursor(bool show)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::grabMouse(bool grab)
|
void FBBackendSDL2::grabMouse(bool grab)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -500,7 +503,7 @@ void FrameBufferSDL2::grabMouse(bool grab)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::fullScreen() const
|
bool FBBackendSDL2::fullScreen() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -512,7 +515,7 @@ bool FrameBufferSDL2::fullScreen() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int FrameBufferSDL2::refreshRate() const
|
int FBBackendSDL2::refreshRate() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -529,20 +532,7 @@ int FrameBufferSDL2::refreshRate() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int FrameBufferSDL2::gameRefreshRate() const
|
void FBBackendSDL2::renderToScreen()
|
||||||
{
|
|
||||||
if(myOSystem.hasConsole())
|
|
||||||
{
|
|
||||||
const string format = myOSystem.console().getFormatString();
|
|
||||||
const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60";
|
|
||||||
|
|
||||||
return isNtsc ? 60 : 50; // The code will take care of 59/49 Hz
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameBufferSDL2::renderToScreen()
|
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -551,7 +541,7 @@ void FrameBufferSDL2::renderToScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::setWindowIcon()
|
void FBBackendSDL2::setWindowIcon()
|
||||||
{
|
{
|
||||||
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
||||||
#include "stella_icon.hxx"
|
#include "stella_icon.hxx"
|
||||||
|
@ -565,19 +555,20 @@ void FrameBufferSDL2::setWindowIcon()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
unique_ptr<FBSurface> FrameBufferSDL2::createSurface(
|
unique_ptr<FBSurface> FBBackendSDL2::createSurface(
|
||||||
uInt32 w,
|
uInt32 w,
|
||||||
uInt32 h,
|
uInt32 h,
|
||||||
ScalingInterpolation interpolation,
|
ScalingInterpolation inter,
|
||||||
const uInt32* data
|
const uInt32* data
|
||||||
) const
|
) const
|
||||||
{
|
{
|
||||||
return make_unique<FBSurfaceSDL2>(const_cast<FrameBufferSDL2&>(*this), w, h, interpolation, data);
|
return make_unique<FBSurfaceSDL2>
|
||||||
|
(const_cast<FBBackendSDL2&>(*this), w, h, inter, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
void FBBackendSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||||
const Common::Rect& rect) const
|
const Common::Rect& rect) const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -589,7 +580,7 @@ void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::clear()
|
void FBBackendSDL2::clear()
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -597,49 +588,34 @@ void FrameBufferSDL2::clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SDL_Renderer* FrameBufferSDL2::renderer()
|
void FBBackendSDL2::detectFeatures()
|
||||||
{
|
|
||||||
return myRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameBufferSDL2::isInitialized() const
|
|
||||||
{
|
|
||||||
return myRenderer != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const SDL_PixelFormat& FrameBufferSDL2::pixelFormat() const
|
|
||||||
{
|
|
||||||
return *myPixelFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameBufferSDL2::detectFeatures()
|
|
||||||
{
|
{
|
||||||
myRenderTargetSupport = detectRenderTargetSupport();
|
myRenderTargetSupport = detectRenderTargetSupport();
|
||||||
|
|
||||||
if (myRenderer) {
|
if(myRenderer && !myRenderTargetSupport)
|
||||||
if (!myRenderTargetSupport) {
|
Logger::info("Render targets are not supported --- QIS not available");
|
||||||
Logger::info("Render targets are not supported --- QIS not available");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::detectRenderTargetSupport()
|
bool FBBackendSDL2::detectRenderTargetSupport()
|
||||||
{
|
{
|
||||||
if (myRenderer == nullptr) return false;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
if(myRenderer == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
SDL_RendererInfo info;
|
SDL_RendererInfo info;
|
||||||
|
|
||||||
SDL_GetRendererInfo(myRenderer, &info);
|
SDL_GetRendererInfo(myRenderer, &info);
|
||||||
|
|
||||||
if (!(info.flags & SDL_RENDERER_TARGETTEXTURE)) return false;
|
if(!(info.flags & SDL_RENDERER_TARGETTEXTURE))
|
||||||
|
return false;
|
||||||
|
|
||||||
SDL_Texture* tex = SDL_CreateTexture(myRenderer, myPixelFormat->format, SDL_TEXTUREACCESS_TARGET, 16, 16);
|
SDL_Texture* tex =
|
||||||
|
SDL_CreateTexture(myRenderer, myPixelFormat->format,
|
||||||
|
SDL_TEXTUREACCESS_TARGET, 16, 16);
|
||||||
|
|
||||||
if (!tex) return false;
|
if(!tex)
|
||||||
|
return false;
|
||||||
|
|
||||||
int sdlError = SDL_SetRenderTarget(myRenderer, tex);
|
int sdlError = SDL_SetRenderTarget(myRenderer, tex);
|
||||||
SDL_SetRenderTarget(myRenderer, nullptr);
|
SDL_SetRenderTarget(myRenderer, nullptr);
|
||||||
|
@ -650,20 +626,17 @@ bool FrameBufferSDL2::detectRenderTargetSupport()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::hasRenderTargetSupport() const
|
void FBBackendSDL2::determineDimensions()
|
||||||
{
|
{
|
||||||
return myRenderTargetSupport;
|
ASSERT_MAIN_THREAD;
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameBufferSDL2::determineDimensions()
|
|
||||||
{
|
|
||||||
SDL_GetWindowSize(myWindow, &myWindowW, &myWindowH);
|
SDL_GetWindowSize(myWindow, &myWindowW, &myWindowH);
|
||||||
|
|
||||||
if (myRenderer == nullptr) {
|
if(myRenderer == nullptr)
|
||||||
|
{
|
||||||
myRenderW = myWindowW;
|
myRenderW = myWindowW;
|
||||||
myRenderH = myWindowH;
|
myRenderH = myWindowH;
|
||||||
} else {
|
|
||||||
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
||||||
}
|
}
|
|
@ -15,8 +15,8 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#ifndef FRAMEBUFFER_SDL2_HXX
|
#ifndef FB_BACKEND_SDL2_HXX
|
||||||
#define FRAMEBUFFER_SDL2_HXX
|
#define FB_BACKEND_SDL2_HXX
|
||||||
|
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
|
||||||
|
@ -24,27 +24,55 @@ class OSystem;
|
||||||
class FBSurfaceSDL2;
|
class FBSurfaceSDL2;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FrameBuffer.hxx"
|
#include "FBBackend.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class implements a standard SDL2 2D, hardware accelerated framebuffer.
|
This class implements a standard SDL2 2D, hardware accelerated framebuffer
|
||||||
Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
backend. Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
*/
|
*/
|
||||||
class FrameBufferSDL2 : public FrameBuffer
|
class FBBackendSDL2 : public FBBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Creates a new SDL2 framebuffer
|
Creates a new SDL2 framebuffer
|
||||||
*/
|
*/
|
||||||
explicit FrameBufferSDL2(OSystem& osystem);
|
explicit FBBackendSDL2(OSystem& osystem);
|
||||||
~FrameBufferSDL2() override;
|
~FBBackendSDL2() override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
public:
|
||||||
// The following are derived from public methods in FrameBuffer.hxx
|
/**
|
||||||
//////////////////////////////////////////////////////////////////////
|
Get a pointer to the SDL renderer.
|
||||||
|
*/
|
||||||
|
SDL_Renderer* renderer() { return myRenderer; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Is the renderer initialized?
|
||||||
|
*/
|
||||||
|
bool isInitialized() const { return myRenderer != nullptr; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the SDL pixel format.
|
||||||
|
*/
|
||||||
|
const SDL_PixelFormat& pixelFormat() const { return *myPixelFormat; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Does the renderer support render targets?
|
||||||
|
*/
|
||||||
|
bool hasRenderTargetSupport() const { return myRenderTargetSupport; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Transform from window to renderer coordinates, x direction
|
||||||
|
*/
|
||||||
|
int scaleX(int x) const override { return (x * myRenderW) / myWindowW; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Transform from window to renderer coordinates, y direction
|
||||||
|
*/
|
||||||
|
int scaleY(int y) const override { return (y * myRenderH) / myWindowH; }
|
||||||
|
|
||||||
|
protected:
|
||||||
/**
|
/**
|
||||||
Updates window title.
|
Updates window title.
|
||||||
|
|
||||||
|
@ -93,7 +121,8 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
@param pitch The pitch (in bytes) for the pixel data
|
@param pitch The pitch (in bytes) for the pixel data
|
||||||
@param rect The bounding rectangle for the buffer
|
@param rect The bounding rectangle for the buffer
|
||||||
*/
|
*/
|
||||||
void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const override;
|
void readPixels(uInt8* buffer, uInt32 pitch,
|
||||||
|
const Common::Rect& rect) const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to query if the current window is not centered
|
This method is called to query if the current window is not centered
|
||||||
|
@ -110,6 +139,7 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
@return The position of the currently displayed window
|
@return The position of the currently displayed window
|
||||||
*/
|
*/
|
||||||
Common::Point getCurrentWindowPos() const override;
|
Common::Point getCurrentWindowPos() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to query the video hardware for the index
|
This method is called to query the video hardware for the index
|
||||||
of the display the current window is displayed on
|
of the display the current window is displayed on
|
||||||
|
@ -124,40 +154,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
*/
|
*/
|
||||||
void clear() override;
|
void clear() override;
|
||||||
|
|
||||||
/**
|
|
||||||
Get a pointer to the SDL renderer.
|
|
||||||
*/
|
|
||||||
SDL_Renderer* renderer();
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get the SDL pixel format.
|
|
||||||
*/
|
|
||||||
const SDL_PixelFormat& pixelFormat() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Is the renderer initialized?
|
|
||||||
*/
|
|
||||||
bool isInitialized() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Does the renderer support render targets?
|
|
||||||
*/
|
|
||||||
bool hasRenderTargetSupport() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Transform from window to renderer coordinates, x direction
|
|
||||||
*/
|
|
||||||
int scaleX(int x) const override { return (x * myRenderW) / myWindowW; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Transform from window to renderer coordinates, y direction
|
|
||||||
*/
|
|
||||||
int scaleY(int y) const override { return (y * myRenderH) / myWindowH; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// The following are derived from protected methods in FrameBuffer.hxx
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
/**
|
/**
|
||||||
This method is called to query and initialize the video hardware
|
This method is called to query and initialize the video hardware
|
||||||
for desktop and fullscreen resolution information. Since several
|
for desktop and fullscreen resolution information. Since several
|
||||||
|
@ -174,46 +170,28 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
/**
|
/**
|
||||||
This method is called to change to the given video mode.
|
This method is called to change to the given video mode.
|
||||||
|
|
||||||
@param title The title for the created window
|
@param mode The video mode to use
|
||||||
@param mode The video mode to use
|
@param winIdx The display/monitor that the window last opened on
|
||||||
|
@param winPos The position that the window last opened at
|
||||||
|
|
||||||
@return False on any errors, else true
|
@return False on any errors, else true
|
||||||
*/
|
*/
|
||||||
bool activateVideoMode(const string& title,
|
bool setVideoMode(const VideoModeHandler::Mode& mode,
|
||||||
const VideoModeHandler::Mode& mode) override;
|
int winIdx, const Common::Point& winPos) override;
|
||||||
|
|
||||||
/**
|
|
||||||
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
|
|
||||||
|
|
||||||
@param displayIndex The display which should be checked
|
|
||||||
@param adaptedSdlMode The best matching mode if the refresh rate should be changed
|
|
||||||
|
|
||||||
@return True if the refresh rate should be changed
|
|
||||||
*/
|
|
||||||
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
|
|
||||||
|
|
||||||
/**
|
|
||||||
Create a new renderer if required
|
|
||||||
|
|
||||||
@param force If true, force new renderer creation
|
|
||||||
|
|
||||||
@return False on any errors, else true
|
|
||||||
*/
|
|
||||||
bool createRenderer(bool force);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to create a surface with the given attributes.
|
This method is called to create a surface with the given attributes.
|
||||||
|
|
||||||
@param w The requested width of the new surface.
|
@param w The requested width of the new surface.
|
||||||
@param h The requested height of the new surface.
|
@param h The requested height of the new surface.
|
||||||
@param interpolation Interpolation mode
|
@param inter Interpolation mode
|
||||||
@param data If non-null, use the given data values as a static surface
|
@param data If non-null, use the given data values as a static surface
|
||||||
*/
|
*/
|
||||||
unique_ptr<FBSurface>
|
unique_ptr<FBSurface>
|
||||||
createSurface(
|
createSurface(
|
||||||
uInt32 w,
|
uInt32 w,
|
||||||
uInt32 h,
|
uInt32 h,
|
||||||
ScalingInterpolation interpolation,
|
ScalingInterpolation inter,
|
||||||
const uInt32* data
|
const uInt32* data
|
||||||
) const override;
|
) const override;
|
||||||
|
|
||||||
|
@ -223,28 +201,49 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
void grabMouse(bool grab) override;
|
void grabMouse(bool grab) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set the icon for the main SDL window.
|
This method is called to provide information about the backend.
|
||||||
*/
|
|
||||||
void setWindowIcon() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to provide information about the FrameBuffer.
|
|
||||||
*/
|
*/
|
||||||
string about() const override;
|
string about() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a new renderer if required.
|
||||||
|
|
||||||
|
@param force If true, force new renderer creation
|
||||||
|
|
||||||
|
@return False on any errors, else true
|
||||||
|
*/
|
||||||
|
bool createRenderer(bool force);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method must be called after all drawing is done, and indicates
|
This method must be called after all drawing is done, and indicates
|
||||||
that the buffers should be pushed to the physical screen.
|
that the buffers should be pushed to the physical screen.
|
||||||
*/
|
*/
|
||||||
void renderToScreen() override;
|
void renderToScreen() override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieve the current display's refresh rate, or 0 if no window.
|
||||||
|
*/
|
||||||
|
int refreshRate() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Checks if the display refresh rate should be adapted to game refresh
|
||||||
|
rate in (real) fullscreen mode.
|
||||||
|
|
||||||
|
@param displayIndex The display which should be checked
|
||||||
|
@param adaptedSdlMode The best matching mode if the refresh rate
|
||||||
|
should be changed
|
||||||
|
|
||||||
|
@return True if the refresh rate should be changed
|
||||||
|
*/
|
||||||
|
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
After the renderer has been created, detect the features it supports.
|
After the renderer has been created, detect the features it supports.
|
||||||
*/
|
*/
|
||||||
void detectFeatures();
|
void detectFeatures();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Detect render target support;
|
Detect render target support.
|
||||||
*/
|
*/
|
||||||
bool detectRenderTargetSupport();
|
bool detectRenderTargetSupport();
|
||||||
|
|
||||||
|
@ -254,16 +253,13 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
void determineDimensions();
|
void determineDimensions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Retrieve the current display's refresh rate, or 0 if no window
|
Set the icon for the main SDL window.
|
||||||
*/
|
*/
|
||||||
int refreshRate() const override;
|
void setWindowIcon();
|
||||||
|
|
||||||
/**
|
|
||||||
Retrieve the current game's refresh rate, or 60 if no game
|
|
||||||
*/
|
|
||||||
int gameRefreshRate() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
OSystem& myOSystem;
|
||||||
|
|
||||||
// The SDL video buffer
|
// The SDL video buffer
|
||||||
SDL_Window* myWindow{nullptr};
|
SDL_Window* myWindow{nullptr};
|
||||||
SDL_Renderer* myRenderer{nullptr};
|
SDL_Renderer* myRenderer{nullptr};
|
||||||
|
@ -274,22 +270,25 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
// Center setting of current window
|
// Center setting of current window
|
||||||
bool myCenter{false};
|
bool myCenter{false};
|
||||||
|
|
||||||
// last position of windowed window
|
|
||||||
Common::Point myWindowedPos;
|
|
||||||
|
|
||||||
// Does the renderer support render targets?
|
// Does the renderer support render targets?
|
||||||
bool myRenderTargetSupport{false};
|
bool myRenderTargetSupport{false};
|
||||||
|
|
||||||
|
// Title of the main window/screen
|
||||||
|
string myScreenTitle;
|
||||||
|
|
||||||
|
// Number of displays
|
||||||
|
int myNumDisplays{1};
|
||||||
|
|
||||||
// Window and renderer dimensions
|
// Window and renderer dimensions
|
||||||
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
FrameBufferSDL2() = delete;
|
FBBackendSDL2() = delete;
|
||||||
FrameBufferSDL2(const FrameBufferSDL2&) = delete;
|
FBBackendSDL2(const FBBackendSDL2&) = delete;
|
||||||
FrameBufferSDL2(FrameBufferSDL2&&) = delete;
|
FBBackendSDL2(FBBackendSDL2&&) = delete;
|
||||||
FrameBufferSDL2& operator=(const FrameBufferSDL2&) = delete;
|
FBBackendSDL2& operator=(const FBBackendSDL2&) = delete;
|
||||||
FrameBufferSDL2& operator=(FrameBufferSDL2&&) = delete;
|
FBBackendSDL2& operator=(FBBackendSDL2&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -22,9 +22,9 @@
|
||||||
#include "sdl_blitter/BlitterFactory.hxx"
|
#include "sdl_blitter/BlitterFactory.hxx"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
BlitterFactory::ScalingAlgorithm scalingAlgorithm(ScalingInterpolation interpolation)
|
BlitterFactory::ScalingAlgorithm scalingAlgorithm(ScalingInterpolation inter)
|
||||||
{
|
{
|
||||||
switch (interpolation) {
|
switch (inter) {
|
||||||
case ScalingInterpolation::none:
|
case ScalingInterpolation::none:
|
||||||
return BlitterFactory::ScalingAlgorithm::nearestNeighbour;
|
return BlitterFactory::ScalingAlgorithm::nearestNeighbour;
|
||||||
|
|
||||||
|
@ -41,12 +41,12 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||||
uInt32 width, uInt32 height,
|
uInt32 width, uInt32 height,
|
||||||
ScalingInterpolation interpolation,
|
ScalingInterpolation inter,
|
||||||
const uInt32* staticData)
|
const uInt32* staticData)
|
||||||
: myFB(buffer),
|
: myBackend(backend),
|
||||||
myInterpolationMode(interpolation)
|
myInterpolationMode(inter)
|
||||||
{
|
{
|
||||||
createSurface(width, height, staticData);
|
createSurface(width, height, staticData);
|
||||||
}
|
}
|
||||||
|
@ -214,7 +214,7 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
// Create a surface in the same format as the parent GL class
|
// Create a surface in the same format as the parent GL class
|
||||||
const SDL_PixelFormat& pf = myFB.pixelFormat();
|
const SDL_PixelFormat& pf = myBackend.pixelFormat();
|
||||||
|
|
||||||
mySurface = SDL_CreateRGBSurface(0, width, height,
|
mySurface = SDL_CreateRGBSurface(0, width, height,
|
||||||
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
||||||
|
@ -242,11 +242,13 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::reinitializeBlitter()
|
void FBSurfaceSDL2::reinitializeBlitter()
|
||||||
{
|
{
|
||||||
if (!myBlitter && myFB.isInitialized())
|
if (!myBlitter && myBackend.isInitialized())
|
||||||
myBlitter = BlitterFactory::createBlitter(myFB, scalingAlgorithm(myInterpolationMode));
|
myBlitter = BlitterFactory::createBlitter(
|
||||||
|
myBackend, scalingAlgorithm(myInterpolationMode));
|
||||||
|
|
||||||
if (myBlitter)
|
if (myBlitter)
|
||||||
myBlitter->reinitialize(mySrcR, myDstR, myAttributes, myIsStatic ? mySurface : nullptr);
|
myBlitter->reinitialize(mySrcR, myDstR, myAttributes,
|
||||||
|
myIsStatic ? mySurface : nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FBSurface.hxx"
|
#include "FBSurface.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "sdl_blitter/Blitter.hxx"
|
#include "sdl_blitter/Blitter.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,9 +32,8 @@
|
||||||
class FBSurfaceSDL2 : public FBSurface
|
class FBSurfaceSDL2 : public FBSurface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height,
|
FBSurfaceSDL2(FBBackendSDL2& backend, uInt32 width, uInt32 height,
|
||||||
ScalingInterpolation interpolation,
|
ScalingInterpolation inter, const uInt32* staticData);
|
||||||
const uInt32* staticData);
|
|
||||||
~FBSurfaceSDL2() override;
|
~FBSurfaceSDL2() override;
|
||||||
|
|
||||||
// Most of the surface drawing primitives are implemented in FBSurface;
|
// Most of the surface drawing primitives are implemented in FBSurface;
|
||||||
|
@ -95,7 +94,7 @@ class FBSurfaceSDL2 : public FBSurface
|
||||||
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameBufferSDL2& myFB;
|
FBBackendSDL2& myBackend;
|
||||||
|
|
||||||
unique_ptr<Blitter> myBlitter;
|
unique_ptr<Blitter> myBlitter;
|
||||||
ScalingInterpolation myInterpolationMode
|
ScalingInterpolation myInterpolationMode
|
||||||
|
|
|
@ -51,10 +51,10 @@
|
||||||
|
|
||||||
#if defined(__LIB_RETRO__)
|
#if defined(__LIB_RETRO__)
|
||||||
#include "EventHandlerLIBRETRO.hxx"
|
#include "EventHandlerLIBRETRO.hxx"
|
||||||
#include "FrameBufferLIBRETRO.hxx"
|
#include "FBBackendLIBRETRO.hxx"
|
||||||
#elif defined(SDL_SUPPORT)
|
#elif defined(SDL_SUPPORT)
|
||||||
#include "EventHandlerSDL2.hxx"
|
#include "EventHandlerSDL2.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#else
|
#else
|
||||||
#error Unsupported backend!
|
#error Unsupported backend!
|
||||||
#endif
|
#endif
|
||||||
|
@ -128,12 +128,12 @@ class MediaFactory
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static unique_ptr<FrameBuffer> createVideo(OSystem& osystem)
|
static unique_ptr<FBBackend> createVideoBackend(OSystem& osystem)
|
||||||
{
|
{
|
||||||
#if defined(__LIB_RETRO__)
|
#if defined(__LIB_RETRO__)
|
||||||
return make_unique<FrameBufferLIBRETRO>(osystem);
|
return make_unique<FBBackendLIBRETRO>(osystem);
|
||||||
#elif defined(SDL_SUPPORT)
|
#elif defined(SDL_SUPPORT)
|
||||||
return make_unique<FrameBufferSDL2>(osystem);
|
return make_unique<FBBackendSDL2>(osystem);
|
||||||
#else
|
#else
|
||||||
#error Unsupported platform for FrameBuffer!
|
#error Unsupported platform for FrameBuffer!
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,9 +5,9 @@ MODULE_OBJS := \
|
||||||
src/common/AudioSettings.o \
|
src/common/AudioSettings.o \
|
||||||
src/common/Base.o \
|
src/common/Base.o \
|
||||||
src/common/EventHandlerSDL2.o \
|
src/common/EventHandlerSDL2.o \
|
||||||
|
src/common/FBBackendSDL2.o \
|
||||||
src/common/FBSurfaceSDL2.o \
|
src/common/FBSurfaceSDL2.o \
|
||||||
src/common/FpsMeter.o \
|
src/common/FpsMeter.o \
|
||||||
src/common/FrameBufferSDL2.o \
|
|
||||||
src/common/FSNodeZIP.o \
|
src/common/FSNodeZIP.o \
|
||||||
src/common/JoyMap.o \
|
src/common/JoyMap.o \
|
||||||
src/common/KeyMap.o \
|
src/common/KeyMap.o \
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "BilinearBlitter.hxx"
|
#include "BilinearBlitter.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate)
|
BilinearBlitter::BilinearBlitter(FBBackendSDL2& fb, bool interpolate)
|
||||||
: myFB(fb),
|
: myFB(fb),
|
||||||
myInterpolate(interpolate)
|
myInterpolate(interpolate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef BILINEAR_BLITTER_HXX
|
#ifndef BILINEAR_BLITTER_HXX
|
||||||
#define BILINEAR_BLITTER_HXX
|
#define BILINEAR_BLITTER_HXX
|
||||||
|
|
||||||
class FrameBufferSDL2;
|
class FBBackendSDL2;
|
||||||
|
|
||||||
#include "Blitter.hxx"
|
#include "Blitter.hxx"
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
@ -27,7 +27,7 @@ class BilinearBlitter : public Blitter {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BilinearBlitter(FrameBufferSDL2& fb, bool interpolate);
|
BilinearBlitter(FBBackendSDL2& fb, bool interpolate);
|
||||||
|
|
||||||
~BilinearBlitter() override;
|
~BilinearBlitter() override;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class BilinearBlitter : public Blitter {
|
||||||
virtual void blit(SDL_Surface& surface) override;
|
virtual void blit(SDL_Surface& surface) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameBufferSDL2& myFB;
|
FBBackendSDL2& myFB;
|
||||||
|
|
||||||
SDL_Texture* myTexture{nullptr};
|
SDL_Texture* myTexture{nullptr};
|
||||||
SDL_Texture* mySecondaryTexture{nullptr};
|
SDL_Texture* mySecondaryTexture{nullptr};
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "BilinearBlitter.hxx"
|
#include "BilinearBlitter.hxx"
|
||||||
#include "QisBlitter.hxx"
|
#include "QisBlitter.hxx"
|
||||||
|
|
||||||
unique_ptr<Blitter> BlitterFactory::createBlitter(FrameBufferSDL2& fb, ScalingAlgorithm scaling)
|
unique_ptr<Blitter> BlitterFactory::createBlitter(FBBackendSDL2& fb, ScalingAlgorithm scaling)
|
||||||
{
|
{
|
||||||
if (!fb.isInitialized()) {
|
if (!fb.isInitialized()) {
|
||||||
throw runtime_error("BlitterFactory requires an initialized framebuffer!");
|
throw runtime_error("BlitterFactory requires an initialized framebuffer!");
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Blitter.hxx"
|
#include "Blitter.hxx"
|
||||||
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
|
||||||
|
|
||||||
class BlitterFactory {
|
class BlitterFactory {
|
||||||
public:
|
public:
|
||||||
|
@ -35,7 +35,7 @@ class BlitterFactory {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static unique_ptr<Blitter> createBlitter(FrameBufferSDL2& fb, ScalingAlgorithm scaling);
|
static unique_ptr<Blitter> createBlitter(FBBackendSDL2& fb, ScalingAlgorithm scaling);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BLITTER_FACTORY_HXX
|
#endif // BLITTER_FACTORY_HXX
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "QisBlitter.hxx"
|
#include "QisBlitter.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
QisBlitter::QisBlitter(FrameBufferSDL2& fb)
|
QisBlitter::QisBlitter(FBBackendSDL2& fb)
|
||||||
: myFB(fb)
|
: myFB(fb)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ QisBlitter::~QisBlitter()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool QisBlitter::isSupported(FrameBufferSDL2 &fb)
|
bool QisBlitter::isSupported(FBBackendSDL2& fb)
|
||||||
{
|
{
|
||||||
if (!fb.isInitialized()) throw runtime_error("framebuffer not initialized");
|
if (!fb.isInitialized()) throw runtime_error("framebuffer not initialized");
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef QIS_BLITTER_HXX
|
#ifndef QIS_BLITTER_HXX
|
||||||
#define QIS_BLITTER_HXX
|
#define QIS_BLITTER_HXX
|
||||||
|
|
||||||
class FrameBufferSDL2;
|
class FBBackendSDL2;
|
||||||
|
|
||||||
#include "Blitter.hxx"
|
#include "Blitter.hxx"
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
@ -27,9 +27,9 @@ class QisBlitter : public Blitter {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
explicit QisBlitter(FrameBufferSDL2& fb);
|
explicit QisBlitter(FBBackendSDL2& fb);
|
||||||
|
|
||||||
static bool isSupported(FrameBufferSDL2 &fb);
|
static bool isSupported(FBBackendSDL2& fb);
|
||||||
|
|
||||||
~QisBlitter() override;
|
~QisBlitter() override;
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class QisBlitter : public Blitter {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FrameBufferSDL2& myFB;
|
FBBackendSDL2& myFB;
|
||||||
|
|
||||||
SDL_Texture* mySrcTexture{nullptr};
|
SDL_Texture* mySrcTexture{nullptr};
|
||||||
SDL_Texture* mySecondarySrcTexture{nullptr};
|
SDL_Texture* mySecondarySrcTexture{nullptr};
|
||||||
|
|
|
@ -250,7 +250,6 @@ Console::~Console()
|
||||||
myOSystem.sound().close();
|
myOSystem.sound().close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Console::setConsoleTiming()
|
void Console::setConsoleTiming()
|
||||||
{
|
{
|
||||||
|
@ -728,7 +727,8 @@ void Console::changeVSizeAdjust(int direction)
|
||||||
|
|
||||||
ostringstream val;
|
ostringstream val;
|
||||||
|
|
||||||
val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ") << newAdjustVSize << "%";
|
val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ")
|
||||||
|
<< newAdjustVSize << "%";
|
||||||
myOSystem.frameBuffer().showMessage("V-Size", val.str(), newAdjustVSize, -5, 5);
|
myOSystem.frameBuffer().showMessage("V-Size", val.str(), newAdjustVSize, -5, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,7 +743,8 @@ void Console::toggleCorrectAspectRatio(bool toggle)
|
||||||
myOSystem.settings().setValue("tia.correct_aspect", enabled);
|
myOSystem.settings().setValue("tia.correct_aspect", enabled);
|
||||||
initializeVideo();
|
initializeVideo();
|
||||||
}
|
}
|
||||||
const string message = string("Correct aspect ratio ") + (enabled ? "enabled" : "disabled");
|
const string& message = string("Correct aspect ratio ") +
|
||||||
|
(enabled ? "enabled" : "disabled");
|
||||||
|
|
||||||
myOSystem.frameBuffer().showMessage(message);
|
myOSystem.frameBuffer().showMessage(message);
|
||||||
}
|
}
|
||||||
|
@ -755,8 +756,7 @@ void Console::setTIAProperties()
|
||||||
static_cast<Int32>(BSPF::stringToInt(myProperties.get(PropType::Display_VCenter))), TIAConstants::minVcenter, TIAConstants::maxVcenter
|
static_cast<Int32>(BSPF::stringToInt(myProperties.get(PropType::Display_VCenter))), TIAConstants::minVcenter, TIAConstants::maxVcenter
|
||||||
);
|
);
|
||||||
|
|
||||||
if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
if(gameRefreshRate() == 60)
|
||||||
myDisplayFormat == "SECAM60")
|
|
||||||
{
|
{
|
||||||
// Assume we've got ~262 scanlines (NTSC-like format)
|
// Assume we've got ~262 scanlines (NTSC-like format)
|
||||||
myTIA->setLayout(FrameLayout::ntsc);
|
myTIA->setLayout(FrameLayout::ntsc);
|
||||||
|
@ -805,17 +805,22 @@ void Console::setControllers(const string& romMd5)
|
||||||
|
|
||||||
myLeftControl = std::move(myCMHandler->leftController());
|
myLeftControl = std::move(myCMHandler->leftController());
|
||||||
myRightControl = std::move(myCMHandler->rightController());
|
myRightControl = std::move(myCMHandler->rightController());
|
||||||
myOSystem.eventHandler().defineKeyControllerMappings(Controller::Type::CompuMate, Controller::Jack::Left);
|
myOSystem.eventHandler().defineKeyControllerMappings(
|
||||||
myOSystem.eventHandler().defineJoyControllerMappings(Controller::Type::CompuMate, Controller::Jack::Left);
|
Controller::Type::CompuMate, Controller::Jack::Left);
|
||||||
|
myOSystem.eventHandler().defineJoyControllerMappings(
|
||||||
|
Controller::Type::CompuMate, Controller::Jack::Left);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Setup the controllers based on properties
|
// Setup the controllers based on properties
|
||||||
Controller::Type leftType = Controller::getType(myProperties.get(PropType::Controller_Left));
|
Controller::Type leftType =
|
||||||
Controller::Type rightType = Controller::getType(myProperties.get(PropType::Controller_Right));
|
Controller::getType(myProperties.get(PropType::Controller_Left));
|
||||||
|
Controller::Type rightType =
|
||||||
|
Controller::getType(myProperties.get(PropType::Controller_Right));
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
const ByteBuffer& image = myCart->getImage(size);
|
const ByteBuffer& image = myCart->getImage(size);
|
||||||
const bool swappedPorts = myProperties.get(PropType::Console_SwapPorts) == "YES";
|
const bool swappedPorts =
|
||||||
|
myProperties.get(PropType::Console_SwapPorts) == "YES";
|
||||||
|
|
||||||
// Try to detect controllers
|
// Try to detect controllers
|
||||||
if(image != nullptr && size != 0)
|
if(image != nullptr && size != 0)
|
||||||
|
@ -827,7 +832,8 @@ void Console::setControllers(const string& romMd5)
|
||||||
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, myOSystem.settings());
|
!swappedPorts ? Controller::Jack::Right : Controller::Jack::Left, myOSystem.settings());
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<Controller> leftC = getControllerPort(leftType, Controller::Jack::Left, romMd5),
|
unique_ptr<Controller>
|
||||||
|
leftC = getControllerPort(leftType, Controller::Jack::Left, romMd5),
|
||||||
rightC = getControllerPort(rightType, Controller::Jack::Right, romMd5);
|
rightC = getControllerPort(rightType, Controller::Jack::Right, romMd5);
|
||||||
|
|
||||||
// Swap the ports if necessary
|
// Swap the ports if necessary
|
||||||
|
@ -985,13 +991,21 @@ void Console::changeAutoFireRate(int direction)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
float Console::getFramerate() const
|
float Console::currentFrameRate() const
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
(myConsoleTiming == ConsoleTiming::ntsc ? 262.F * 60.F : 312.F * 50.F) /
|
(myConsoleTiming == ConsoleTiming::ntsc ? 262.F * 60.F : 312.F * 50.F) /
|
||||||
myTIA->frameBufferScanlinesLastFrame();
|
myTIA->frameBufferScanlinesLastFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
int Console::gameRefreshRate() const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
||||||
|
myDisplayFormat == "SECAM60" ? 60 : 50;
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Console::toggleTIABit(TIABit bit, const string& bitname, bool show, bool toggle) const
|
void Console::toggleTIABit(TIABit bit, const string& bitname, bool show, bool toggle) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -185,6 +185,11 @@ class Console : public Serializable, public ConsoleIO
|
||||||
*/
|
*/
|
||||||
EmulationTiming& emulationTiming() { return myEmulationTiming; }
|
EmulationTiming& emulationTiming() { return myEmulationTiming; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieve the current game's refresh rate, or 0 if no game.
|
||||||
|
*/
|
||||||
|
int refreshRate() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Toggle between NTSC/PAL/SECAM (and variants) display format.
|
Toggle between NTSC/PAL/SECAM (and variants) display format.
|
||||||
|
@ -282,9 +287,16 @@ class Console : public Serializable, public ConsoleIO
|
||||||
void toggleCorrectAspectRatio(bool toggle = true);
|
void toggleCorrectAspectRatio(bool toggle = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns the current framerate.
|
Returns the current framerate. Note that this is the actual,
|
||||||
|
dynamic frame rate while a game is running.
|
||||||
*/
|
*/
|
||||||
float getFramerate() const;
|
float currentFrameRate() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieve the current game's refresh rate. Note that this is a
|
||||||
|
static, basic frame rate based on the current TV format.
|
||||||
|
*/
|
||||||
|
int gameRefreshRate() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Toggles the TIA bit specified in the method name.
|
Toggles the TIA bit specified in the method name.
|
||||||
|
|
|
@ -0,0 +1,207 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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 FB_BACKEND_HXX
|
||||||
|
#define FB_BACKEND_HXX
|
||||||
|
|
||||||
|
class FBSurface;
|
||||||
|
|
||||||
|
#include "Rect.hxx"
|
||||||
|
#include "Variant.hxx"
|
||||||
|
#include "FrameBufferConstants.hxx"
|
||||||
|
#include "VideoModeHandler.hxx"
|
||||||
|
#include "bspf.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
This class provides an interface/abstraction for platform-specific,
|
||||||
|
framebuffer-related rendering operations. Different graphical
|
||||||
|
platforms will inherit from this. For most ports that means SDL2,
|
||||||
|
but some (such as libretro) use their own graphical subsystem.
|
||||||
|
|
||||||
|
@author Stephen Anthony
|
||||||
|
*/
|
||||||
|
class FBBackend
|
||||||
|
{
|
||||||
|
friend class FrameBuffer;
|
||||||
|
|
||||||
|
public:
|
||||||
|
FBBackend() = default;
|
||||||
|
virtual ~FBBackend() = default;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
This method is called to query and initialize the video hardware
|
||||||
|
for desktop and fullscreen resolution information. Since several
|
||||||
|
monitors may be attached, we need the resolution for all of them.
|
||||||
|
|
||||||
|
@param fullscreenRes Maximum resolution supported in fullscreen mode
|
||||||
|
@param windowedRes Maximum resolution supported in windowed mode
|
||||||
|
@param renderers List of renderer names (internal name -> end-user name)
|
||||||
|
*/
|
||||||
|
virtual void queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
|
vector<Common::Size>& windowedRes,
|
||||||
|
VariantList& renderers) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to change to the given video mode.
|
||||||
|
|
||||||
|
@param mode The video mode to use
|
||||||
|
@param winIdx The display/monitor that the window last opened on
|
||||||
|
@param winPos The position that the window last opened at
|
||||||
|
|
||||||
|
@return False on any errors, else true
|
||||||
|
*/
|
||||||
|
virtual bool setVideoMode(const VideoModeHandler::Mode& mode,
|
||||||
|
int winIdx, const Common::Point& winPos) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Clear the framebuffer.
|
||||||
|
*/
|
||||||
|
virtual void clear() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Transform from window to renderer coordinates, x direction
|
||||||
|
*/
|
||||||
|
virtual int scaleX(int x) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Transform from window to renderer coordinates, y direction
|
||||||
|
*/
|
||||||
|
virtual int scaleY(int y) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Updates window title.
|
||||||
|
|
||||||
|
@param title The title of the application / window
|
||||||
|
*/
|
||||||
|
virtual void setTitle(const string& title) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Shows or hides the cursor based on the given boolean value.
|
||||||
|
*/
|
||||||
|
virtual void showCursor(bool show) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Grabs or ungrabs the mouse based on the given boolean value.
|
||||||
|
*/
|
||||||
|
virtual void grabMouse(bool grab) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method must be called after all drawing is done, and indicates
|
||||||
|
that the buffers should be pushed to the physical screen.
|
||||||
|
*/
|
||||||
|
virtual void renderToScreen() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Answers if the display is currently in fullscreen mode.
|
||||||
|
|
||||||
|
@return Whether the display is actually in fullscreen mode
|
||||||
|
*/
|
||||||
|
virtual bool fullScreen() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Retrieve the current display's refresh rate.
|
||||||
|
*/
|
||||||
|
virtual int refreshRate() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to retrieve the R/G/B data from the given pixel.
|
||||||
|
|
||||||
|
@param pixel The pixel containing R/G/B data
|
||||||
|
@param r The red component of the color
|
||||||
|
@param g The green component of the color
|
||||||
|
@param b The blue component of the color
|
||||||
|
*/
|
||||||
|
virtual void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to map a given R/G/B triple to the screen palette.
|
||||||
|
|
||||||
|
@param r The red component of the color.
|
||||||
|
@param g The green component of the color.
|
||||||
|
@param b The blue component of the color.
|
||||||
|
*/
|
||||||
|
virtual uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to get the specified ARGB data from the viewable
|
||||||
|
FrameBuffer area. Note that this isn't the same as any internal
|
||||||
|
surfaces that may be in use; it should return the actual data as it
|
||||||
|
is currently seen onscreen.
|
||||||
|
|
||||||
|
@param buffer The actual pixel data in ARGB8888 format
|
||||||
|
@param pitch The pitch (in bytes) for the pixel data
|
||||||
|
@param rect The bounding rectangle for the buffer
|
||||||
|
*/
|
||||||
|
virtual void readPixels(uInt8* buffer, uInt32 pitch,
|
||||||
|
const Common::Rect& rect) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to query if the current window is not
|
||||||
|
centered or fullscreen.
|
||||||
|
|
||||||
|
@return True, if the current window is positioned
|
||||||
|
*/
|
||||||
|
virtual bool isCurrentWindowPositioned() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to query the video hardware for position of
|
||||||
|
the current window.
|
||||||
|
|
||||||
|
@return The position of the currently displayed window
|
||||||
|
*/
|
||||||
|
virtual Common::Point getCurrentWindowPos() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to query the video hardware for the index
|
||||||
|
of the display the current window is displayed on.
|
||||||
|
|
||||||
|
@return The current display index or a negative value if no
|
||||||
|
window is displayed
|
||||||
|
*/
|
||||||
|
virtual Int32 getCurrentDisplayIndex() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to create a surface with the given attributes.
|
||||||
|
|
||||||
|
@param w The requested width of the new surface.
|
||||||
|
@param h The requested height of the new surface.
|
||||||
|
@param inter Interpolation mode
|
||||||
|
@param data If non-null, use the given data values as a static surface
|
||||||
|
*/
|
||||||
|
virtual unique_ptr<FBSurface>
|
||||||
|
createSurface(
|
||||||
|
uInt32 w,
|
||||||
|
uInt32 h,
|
||||||
|
ScalingInterpolation inter = ScalingInterpolation::none,
|
||||||
|
const uInt32* data = nullptr
|
||||||
|
) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to provide information about the backend.
|
||||||
|
*/
|
||||||
|
virtual string about() const = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Following constructors and assignment operators not supported
|
||||||
|
FBBackend(const FBBackend&) = delete;
|
||||||
|
FBBackend(FBBackend&&) = delete;
|
||||||
|
FBBackend& operator=(const FBBackend&) = delete;
|
||||||
|
FBBackend& operator=(FBBackend&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -177,7 +177,8 @@ class FBSurface
|
||||||
@param y The destination y-location to start drawing pixels
|
@param y The destination y-location to start drawing pixels
|
||||||
@param numpixels The number of pixels to draw
|
@param numpixels The number of pixels to draw
|
||||||
*/
|
*/
|
||||||
virtual void drawPixels(const uInt32* data, uInt32 x, uInt32 y, uInt32 numpixels);
|
virtual void drawPixels(const uInt32* data, uInt32 x, uInt32 y,
|
||||||
|
uInt32 numpixels);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method should be called to draw a rectangular box with sides
|
This method should be called to draw a rectangular box with sides
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "Settings.hxx"
|
#include "Settings.hxx"
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "Sound.hxx"
|
#include "Sound.hxx"
|
||||||
|
#include "MediaFactory.hxx"
|
||||||
|
|
||||||
#include "FBSurface.hxx"
|
#include "FBSurface.hxx"
|
||||||
#include "TIASurface.hxx"
|
#include "TIASurface.hxx"
|
||||||
|
@ -63,14 +64,24 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBuffer::~FrameBuffer()
|
FrameBuffer::~FrameBuffer()
|
||||||
{
|
{
|
||||||
|
// Make sure to free surfaces/textures before destroying the backend itself
|
||||||
|
// Most platforms are fine with doing this in either order, but it seems
|
||||||
|
// that OpenBSD in particular crashes when attempting to destroy textures
|
||||||
|
// *after* the renderer is already destroyed
|
||||||
|
freeSurfaces();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBuffer::initialize()
|
void FrameBuffer::initialize()
|
||||||
{
|
{
|
||||||
|
// First create the platform-specific backend; it is needed before anything
|
||||||
|
// else can be used
|
||||||
|
try { myBackend = MediaFactory::createVideoBackend(myOSystem); }
|
||||||
|
catch(const runtime_error& e) { throw e; }
|
||||||
|
|
||||||
// Get desktop resolution and supported renderers
|
// Get desktop resolution and supported renderers
|
||||||
vector<Common::Size> windowedDisplays;
|
vector<Common::Size> windowedDisplays;
|
||||||
queryHardware(myFullscreenDisplays, windowedDisplays, myRenderers);
|
myBackend->queryHardware(myFullscreenDisplays, windowedDisplays, myRenderers);
|
||||||
uInt32 query_w = windowedDisplays[0].w, query_h = windowedDisplays[0].h;
|
uInt32 query_w = windowedDisplays[0].w, query_h = windowedDisplays[0].h;
|
||||||
|
|
||||||
// Check the 'maxres' setting, which is an undocumented developer feature
|
// Check the 'maxres' setting, which is an undocumented developer feature
|
||||||
|
@ -116,8 +127,6 @@ bool FrameBuffer::initialize()
|
||||||
|
|
||||||
// Create a TIA surface; we need it for rendering TIA images
|
// Create a TIA surface; we need it for rendering TIA images
|
||||||
myTIASurface = make_unique<TIASurface>(myOSystem);
|
myTIASurface = make_unique<TIASurface>(myOSystem);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef GUI_SUPPORT
|
#ifdef GUI_SUPPORT
|
||||||
|
@ -210,7 +219,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
||||||
Common::Size size, bool honourHiDPI)
|
Common::Size size, bool honourHiDPI)
|
||||||
{
|
{
|
||||||
++myInitializedCount;
|
++myInitializedCount;
|
||||||
myScreenTitle = title;
|
myBackend->setTitle(title);
|
||||||
|
|
||||||
// In HiDPI mode, all created displays must be scaled appropriately
|
// In HiDPI mode, all created displays must be scaled appropriately
|
||||||
if(honourHiDPI && hidpiEnabled())
|
if(honourHiDPI && hidpiEnabled())
|
||||||
|
@ -254,7 +263,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
||||||
myBufferType = type;
|
myBufferType = type;
|
||||||
|
|
||||||
// Initialize video subsystem
|
// Initialize video subsystem
|
||||||
string pre_about = about();
|
string pre_about = myBackend->about();
|
||||||
FBInitStatus status = applyVideoMode();
|
FBInitStatus status = applyVideoMode();
|
||||||
if(status != FBInitStatus::Success)
|
if(status != FBInitStatus::Success)
|
||||||
return status;
|
return status;
|
||||||
|
@ -289,11 +298,11 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
||||||
// Print initial usage message, but only print it later if the status has changed
|
// Print initial usage message, but only print it later if the status has changed
|
||||||
if(myInitializedCount == 1)
|
if(myInitializedCount == 1)
|
||||||
{
|
{
|
||||||
Logger::info(about());
|
Logger::info(myBackend->about());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
string post_about = about();
|
string post_about = myBackend->about();
|
||||||
if(post_about != pre_about)
|
if(post_about != pre_about)
|
||||||
Logger::info(post_about);
|
Logger::info(post_about);
|
||||||
}
|
}
|
||||||
|
@ -467,7 +476,7 @@ void FrameBuffer::update(bool force)
|
||||||
|
|
||||||
// Push buffers to screen only when necessary
|
// Push buffers to screen only when necessary
|
||||||
if(force)
|
if(force)
|
||||||
renderToScreen();
|
myBackend->renderToScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -493,7 +502,7 @@ void FrameBuffer::updateInEmulationMode(float framesPerSecond)
|
||||||
drawMessage();
|
drawMessage();
|
||||||
|
|
||||||
// Push buffers to screen
|
// Push buffers to screen
|
||||||
renderToScreen();
|
myBackend->renderToScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -600,7 +609,8 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
|
||||||
ss
|
ss
|
||||||
<< myOSystem.console().tia().frameBufferScanlinesLastFrame()
|
<< myOSystem.console().tia().frameBufferScanlinesLastFrame()
|
||||||
<< " / "
|
<< " / "
|
||||||
<< std::fixed << std::setprecision(1) << myOSystem.console().getFramerate()
|
<< std::fixed << std::setprecision(1)
|
||||||
|
<< myOSystem.console().currentFrameRate()
|
||||||
<< "Hz => "
|
<< "Hz => "
|
||||||
<< info.DisplayFormat;
|
<< info.DisplayFormat;
|
||||||
|
|
||||||
|
@ -803,11 +813,11 @@ void FrameBuffer::setPauseDelay()
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
shared_ptr<FBSurface> FrameBuffer::allocateSurface(
|
shared_ptr<FBSurface> FrameBuffer::allocateSurface(
|
||||||
int w, int h, ScalingInterpolation interpolation, const uInt32* data
|
int w, int h, ScalingInterpolation inter, const uInt32* data
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Add new surface to the list
|
// Add new surface to the list
|
||||||
mySurfaceList.push_back(createSurface(w, h, interpolation, data));
|
mySurfaceList.push_back(myBackend->createSurface(w, h, inter, data));
|
||||||
|
|
||||||
// And return a pointer to it (pointer should be treated read-only)
|
// And return a pointer to it (pointer should be treated read-only)
|
||||||
return mySurfaceList.at(mySurfaceList.size() - 1);
|
return mySurfaceList.at(mySurfaceList.size() - 1);
|
||||||
|
@ -945,9 +955,11 @@ string FrameBuffer::getPositionKey()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBuffer::saveCurrentWindowPosition()
|
void FrameBuffer::saveCurrentWindowPosition()
|
||||||
{
|
{
|
||||||
myOSystem.settings().setValue(getDisplayKey(), getCurrentDisplayIndex());
|
myOSystem.settings().setValue(
|
||||||
if(isCurrentWindowPositioned())
|
getDisplayKey(), myBackend->getCurrentDisplayIndex());
|
||||||
myOSystem.settings().setValue(getPositionKey(), getCurrentWindowPos());
|
if(myBackend->isCurrentWindowPositioned())
|
||||||
|
myOSystem.settings().setValue(
|
||||||
|
getPositionKey(), myBackend->getCurrentWindowPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -997,7 +1009,7 @@ void FrameBuffer::toggleFullscreen(bool toggle)
|
||||||
ostringstream msg;
|
ostringstream msg;
|
||||||
msg << "Fullscreen ";
|
msg << "Fullscreen ";
|
||||||
if(isFullscreen)
|
if(isFullscreen)
|
||||||
msg << "enabled (" << refreshRate() << " Hz, ";
|
msg << "enabled (" << myBackend->refreshRate() << " Hz, ";
|
||||||
else
|
else
|
||||||
msg << "disabled (";
|
msg << "disabled (";
|
||||||
msg << "Zoom " << myActiveVidMode.zoom * 100 << "%)";
|
msg << "Zoom " << myActiveVidMode.zoom * 100 << "%)";
|
||||||
|
@ -1033,7 +1045,7 @@ void FrameBuffer::toggleAdaptRefresh(bool toggle)
|
||||||
|
|
||||||
msg << "Adapt refresh rate ";
|
msg << "Adapt refresh rate ";
|
||||||
msg << (isAdaptRefresh ? "enabled" : "disabled");
|
msg << (isAdaptRefresh ? "enabled" : "disabled");
|
||||||
msg << " (" << refreshRate() << " Hz)";
|
msg << " (" << myBackend->refreshRate() << " Hz)";
|
||||||
|
|
||||||
showMessage(msg.str());
|
showMessage(msg.str());
|
||||||
}
|
}
|
||||||
|
@ -1112,7 +1124,7 @@ FBInitStatus FrameBuffer::applyVideoMode()
|
||||||
const Settings& s = myOSystem.settings();
|
const Settings& s = myOSystem.settings();
|
||||||
if(s.getBool("fullscreen"))
|
if(s.getBool("fullscreen"))
|
||||||
{
|
{
|
||||||
Int32 fsIndex = std::max(getCurrentDisplayIndex(), 0);
|
Int32 fsIndex = std::max(myBackend->getCurrentDisplayIndex(), 0);
|
||||||
myVidModeHandler.setDisplaySize(myFullscreenDisplays[fsIndex], fsIndex);
|
myVidModeHandler.setDisplaySize(myFullscreenDisplays[fsIndex], fsIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1130,7 +1142,11 @@ FBInitStatus FrameBuffer::applyVideoMode()
|
||||||
// So we mute the sound until the operation completes
|
// So we mute the sound until the operation completes
|
||||||
bool oldMuteState = myOSystem.sound().mute(true);
|
bool oldMuteState = myOSystem.sound().mute(true);
|
||||||
FBInitStatus status = FBInitStatus::FailNotSupported;
|
FBInitStatus status = FBInitStatus::FailNotSupported;
|
||||||
if(activateVideoMode(myScreenTitle, mode))
|
|
||||||
|
if(myBackend->setVideoMode(mode,
|
||||||
|
myOSystem.settings().getInt(getDisplayKey()),
|
||||||
|
myOSystem.settings().getPoint(getPositionKey()))
|
||||||
|
)
|
||||||
{
|
{
|
||||||
myActiveVidMode = mode;
|
myActiveVidMode = mode;
|
||||||
status = FBInitStatus::Success;
|
status = FBInitStatus::Success;
|
||||||
|
@ -1218,7 +1234,7 @@ void FrameBuffer::setCursorState()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
grabMouse(emulation && (analog || alwaysUseMouse) && myGrabMouse);
|
myBackend->grabMouse(emulation && (analog || alwaysUseMouse) && myGrabMouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -33,6 +33,7 @@ class TIASurface;
|
||||||
#include "Rect.hxx"
|
#include "Rect.hxx"
|
||||||
#include "Variant.hxx"
|
#include "Variant.hxx"
|
||||||
#include "TIAConstants.hxx"
|
#include "TIAConstants.hxx"
|
||||||
|
#include "FBBackend.hxx"
|
||||||
#include "FrameBufferConstants.hxx"
|
#include "FrameBufferConstants.hxx"
|
||||||
#include "EventHandlerConstants.hxx"
|
#include "EventHandlerConstants.hxx"
|
||||||
#include "VideoModeHandler.hxx"
|
#include "VideoModeHandler.hxx"
|
||||||
|
@ -55,16 +56,14 @@ class FrameBuffer
|
||||||
static constexpr float ZOOM_STEPS = 0.25;
|
static constexpr float ZOOM_STEPS = 0.25;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
|
||||||
Creates a new Frame Buffer
|
|
||||||
*/
|
|
||||||
FrameBuffer(OSystem& osystem);
|
FrameBuffer(OSystem& osystem);
|
||||||
virtual ~FrameBuffer();
|
~FrameBuffer();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Initialize the framebuffer object (set up the underlying hardware)
|
Initialize the framebuffer object (set up the underlying hardware).
|
||||||
|
Throws an exception upon encountering any errors.
|
||||||
*/
|
*/
|
||||||
bool initialize();
|
void initialize();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
(Re)creates the framebuffer display. This must be called before any
|
(Re)creates the framebuffer display. This must be called before any
|
||||||
|
@ -141,17 +140,17 @@ class FrameBuffer
|
||||||
Allocate a new surface. The FrameBuffer class takes all responsibility
|
Allocate a new surface. The FrameBuffer class takes all responsibility
|
||||||
for freeing this surface (ie, other classes must not delete it directly).
|
for freeing this surface (ie, other classes must not delete it directly).
|
||||||
|
|
||||||
@param w The requested width of the new surface.
|
@param w The requested width of the new surface
|
||||||
@param h The requested height of the new surface.
|
@param h The requested height of the new surface
|
||||||
@param interpolation Interpolation mode
|
@param inter Interpolation mode
|
||||||
@param data If non-null, use the given data values as a static surface
|
@param data If non-null, use the given data values as a static surface
|
||||||
|
|
||||||
@return A pointer to a valid surface object, or nullptr.
|
@return A pointer to a valid surface object, or nullptr
|
||||||
*/
|
*/
|
||||||
shared_ptr<FBSurface> allocateSurface(
|
shared_ptr<FBSurface> allocateSurface(
|
||||||
int w,
|
int w,
|
||||||
int h,
|
int h,
|
||||||
ScalingInterpolation interpolation = ScalingInterpolation::none,
|
ScalingInterpolation inter = ScalingInterpolation::none,
|
||||||
const uInt32* data = nullptr
|
const uInt32* data = nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -304,27 +303,15 @@ class FrameBuffer
|
||||||
FontDesc getFontDesc(const string& name) const;
|
FontDesc getFontDesc(const string& name) const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// The following methods are system-specific and can/must be
|
|
||||||
// implemented in derived classes.
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Updates window title
|
|
||||||
|
|
||||||
@param title The title of the application / window
|
|
||||||
*/
|
|
||||||
virtual void setTitle(const string& title) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Shows or hides the cursor based on the given boolean value.
|
Shows or hides the cursor based on the given boolean value.
|
||||||
*/
|
*/
|
||||||
virtual void showCursor(bool show) = 0;
|
void showCursor(bool show) { myBackend->showCursor(show); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Answers if the display is currently in fullscreen mode.
|
Answers if the display is currently in fullscreen mode.
|
||||||
*/
|
*/
|
||||||
virtual bool fullScreen() const = 0;
|
bool fullScreen() const { return myBackend->fullScreen(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to retrieve the R/G/B data from the given pixel.
|
This method is called to retrieve the R/G/B data from the given pixel.
|
||||||
|
@ -334,7 +321,9 @@ class FrameBuffer
|
||||||
@param g The green component of the color
|
@param g The green component of the color
|
||||||
@param b The blue component of the color
|
@param b The blue component of the color
|
||||||
*/
|
*/
|
||||||
virtual void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const = 0;
|
void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const {
|
||||||
|
myBackend->getRGB(pixel, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to map a given R/G/B triple to the screen palette.
|
This method is called to map a given R/G/B triple to the screen palette.
|
||||||
|
@ -343,7 +332,9 @@ class FrameBuffer
|
||||||
@param g The green component of the color.
|
@param g The green component of the color.
|
||||||
@param b The blue component of the color.
|
@param b The blue component of the color.
|
||||||
*/
|
*/
|
||||||
virtual uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const = 0;
|
uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const {
|
||||||
|
return myBackend->mapRGB(r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to get the specified ARGB data from the viewable
|
This method is called to get the specified ARGB data from the viewable
|
||||||
|
@ -355,88 +346,22 @@ class FrameBuffer
|
||||||
@param pitch The pitch (in bytes) for the pixel data
|
@param pitch The pitch (in bytes) for the pixel data
|
||||||
@param rect The bounding rectangle for the buffer
|
@param rect The bounding rectangle for the buffer
|
||||||
*/
|
*/
|
||||||
virtual void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const = 0;
|
void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const {
|
||||||
|
myBackend->readPixels(buffer, pitch, rect);
|
||||||
/**
|
}
|
||||||
This method is called to query if the current window is not centered or fullscreen.
|
|
||||||
|
|
||||||
@return True, if the current window is positioned
|
|
||||||
*/
|
|
||||||
virtual bool isCurrentWindowPositioned() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to query the video hardware for position of
|
|
||||||
the current window
|
|
||||||
|
|
||||||
@return The position of the currently displayed window
|
|
||||||
*/
|
|
||||||
virtual Common::Point getCurrentWindowPos() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to query the video hardware for the index
|
|
||||||
of the display the current window is displayed on
|
|
||||||
|
|
||||||
@return the current display index or a negative value if no
|
|
||||||
window is displayed
|
|
||||||
*/
|
|
||||||
virtual Int32 getCurrentDisplayIndex() const = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Clear the framebuffer.
|
Clear the framebuffer.
|
||||||
*/
|
*/
|
||||||
virtual void clear() = 0;
|
void clear() { myBackend->clear(); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Transform from window to renderer coordinates, x direction
|
Transform from window to renderer coordinates, x/y direction
|
||||||
*/
|
*/
|
||||||
virtual int scaleX(int x) const { return x; }
|
int scaleX(int x) const { return myBackend->scaleX(x); }
|
||||||
|
int scaleY(int y) const { return myBackend->scaleY(y); }
|
||||||
/**
|
|
||||||
Transform from window to renderer coordinates, y direction
|
|
||||||
*/
|
|
||||||
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
|
|
||||||
monitors may be attached, we need the resolution for all of them.
|
|
||||||
|
|
||||||
@param fullscreenRes Maximum resolution supported in fullscreen mode
|
|
||||||
@param windowedRes Maximum resolution supported in windowed mode
|
|
||||||
@param renderers List of renderer names (internal name -> end-user name)
|
|
||||||
*/
|
|
||||||
virtual void queryHardware(vector<Common::Size>& fullscreenRes,
|
|
||||||
vector<Common::Size>& windowedRes,
|
|
||||||
VariantList& renderers) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to change to the given video mode.
|
|
||||||
|
|
||||||
@param title The title for the created window
|
|
||||||
@param mode The video mode to use
|
|
||||||
|
|
||||||
@return False on any errors, else true
|
|
||||||
*/
|
|
||||||
virtual bool activateVideoMode(const string& title,
|
|
||||||
const VideoModeHandler::Mode& mode) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to create a surface with the given attributes.
|
|
||||||
|
|
||||||
@param w The requested width of the new surface.
|
|
||||||
@param h The requested height of the new surface.
|
|
||||||
@param interpolation Interpolation mode
|
|
||||||
@param data If non-null, use the given data values as a static surface
|
|
||||||
*/
|
|
||||||
virtual unique_ptr<FBSurface>
|
|
||||||
createSurface(
|
|
||||||
uInt32 w,
|
|
||||||
uInt32 h,
|
|
||||||
ScalingInterpolation interpolation = ScalingInterpolation::none,
|
|
||||||
const uInt32* data = nullptr
|
|
||||||
) const = 0;
|
|
||||||
|
|
||||||
|
private:
|
||||||
/**
|
/**
|
||||||
Calls 'free()' on all surfaces that the framebuffer knows about.
|
Calls 'free()' on all surfaces that the framebuffer knows about.
|
||||||
*/
|
*/
|
||||||
|
@ -447,42 +372,6 @@ class FrameBuffer
|
||||||
*/
|
*/
|
||||||
void reloadSurfaces();
|
void reloadSurfaces();
|
||||||
|
|
||||||
/**
|
|
||||||
Grabs or ungrabs the mouse based on the given boolean value.
|
|
||||||
*/
|
|
||||||
virtual void grabMouse(bool grab) = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set the icon for the main window.
|
|
||||||
*/
|
|
||||||
virtual void setWindowIcon() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method must be called after all drawing is done, and indicates
|
|
||||||
that the buffers should be pushed to the physical screen.
|
|
||||||
*/
|
|
||||||
virtual void renderToScreen() = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to provide information about the FrameBuffer.
|
|
||||||
*/
|
|
||||||
virtual string about() const = 0;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Retrieve the current display's refresh rate
|
|
||||||
*/
|
|
||||||
virtual int refreshRate() const { return 0; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// The parent system for the framebuffer
|
|
||||||
OSystem& myOSystem;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Maximum message width [chars]
|
|
||||||
static constexpr int MESSAGE_WIDTH = 56;
|
|
||||||
// Maximum gauge bar width [chars]
|
|
||||||
static constexpr int GAUGEBAR_WIDTH = 30;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Draw pending messages.
|
Draw pending messages.
|
||||||
|
|
||||||
|
@ -523,22 +412,13 @@ class FrameBuffer
|
||||||
void setupFonts();
|
void setupFonts();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
|
||||||
// Title of the main window/screen
|
|
||||||
string myScreenTitle;
|
|
||||||
|
|
||||||
// Type of the frame buffer
|
|
||||||
BufferType myBufferType{BufferType::None};
|
|
||||||
|
|
||||||
// Number of displays
|
|
||||||
int myNumDisplays{1};
|
|
||||||
|
|
||||||
// The resolution of the attached displays in fullscreen mode
|
|
||||||
// The primary display is typically the first in the array
|
|
||||||
// Windowed modes use myDesktopSize directly
|
|
||||||
vector<Common::Size> myFullscreenDisplays;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// The parent system for the framebuffer
|
||||||
|
OSystem& myOSystem;
|
||||||
|
|
||||||
|
// Backend used for all platform-specific graphics operations
|
||||||
|
unique_ptr<FBBackend> myBackend;
|
||||||
|
|
||||||
// Indicates the number of times the framebuffer was initialized
|
// Indicates the number of times the framebuffer was initialized
|
||||||
uInt32 myInitializedCount{0};
|
uInt32 myInitializedCount{0};
|
||||||
|
|
||||||
|
@ -553,6 +433,11 @@ class FrameBuffer
|
||||||
// Maximum absolute dimensions of the desktop area
|
// Maximum absolute dimensions of the desktop area
|
||||||
Common::Size myAbsDesktopSize;
|
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
|
||||||
|
vector<Common::Size> myFullscreenDisplays;
|
||||||
|
|
||||||
// Supported renderers
|
// Supported renderers
|
||||||
VariantList myRenderers;
|
VariantList myRenderers;
|
||||||
|
|
||||||
|
@ -561,6 +446,9 @@ class FrameBuffer
|
||||||
VideoModeHandler myVidModeHandler;
|
VideoModeHandler myVidModeHandler;
|
||||||
VideoModeHandler::Mode myActiveVidMode;
|
VideoModeHandler::Mode myActiveVidMode;
|
||||||
|
|
||||||
|
// Type of the frame buffer
|
||||||
|
BufferType myBufferType{BufferType::None};
|
||||||
|
|
||||||
#ifdef GUI_SUPPORT
|
#ifdef GUI_SUPPORT
|
||||||
// The font object to use for the normal in-game GUI
|
// The font object to use for the normal in-game GUI
|
||||||
unique_ptr<GUI::Font> myFont;
|
unique_ptr<GUI::Font> myFont;
|
||||||
|
@ -609,6 +497,11 @@ class FrameBuffer
|
||||||
// Holds a reference to all the surfaces that have been created
|
// Holds a reference to all the surfaces that have been created
|
||||||
vector<shared_ptr<FBSurface>> mySurfaceList;
|
vector<shared_ptr<FBSurface>> mySurfaceList;
|
||||||
|
|
||||||
|
// Maximum message width [chars]
|
||||||
|
static constexpr int MESSAGE_WIDTH = 56;
|
||||||
|
// Maximum gauge bar width [chars]
|
||||||
|
static constexpr int GAUGEBAR_WIDTH = 30;
|
||||||
|
|
||||||
FullPaletteArray myFullPalette;
|
FullPaletteArray myFullPalette;
|
||||||
// Holds UI palette data (for each variation)
|
// Holds UI palette data (for each variation)
|
||||||
static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette,
|
static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette,
|
||||||
|
|
|
@ -143,10 +143,15 @@ bool OSystem::create()
|
||||||
// Get relevant information about the video hardware
|
// Get relevant information about the video hardware
|
||||||
// This must be done before any graphics context is created, since
|
// This must be done before any graphics context is created, since
|
||||||
// it may be needed to initialize the size of graphical objects
|
// it may be needed to initialize the size of graphical objects
|
||||||
try { myFrameBuffer = MediaFactory::createVideo(*this); }
|
try
|
||||||
catch(...) { return false; }
|
{
|
||||||
if(!myFrameBuffer->initialize())
|
myFrameBuffer = make_unique<FrameBuffer>(*this);
|
||||||
|
myFrameBuffer->initialize();
|
||||||
|
}
|
||||||
|
catch(...)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the event handler for the system
|
// Create the event handler for the system
|
||||||
myEventHandler = MediaFactory::createEventHandler(*this);
|
myEventHandler = MediaFactory::createEventHandler(*this);
|
||||||
|
@ -722,7 +727,7 @@ string OSystem::getROMInfo(const Console& console)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
float OSystem::frameRate() const
|
float OSystem::frameRate() const
|
||||||
{
|
{
|
||||||
return myConsole ? myConsole->getFramerate() : 0;
|
return myConsole ? myConsole->currentFrameRate() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -167,7 +167,6 @@ uInt32 TIASurface::mapIndexedPixel(uInt8 indexedColor, uInt8 shift) const
|
||||||
return myPalette[indexedColor | shift];
|
return myPalette[indexedColor | shift];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
|
void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
|
||||||
{
|
{
|
||||||
|
@ -512,13 +511,16 @@ void TIASurface::renderForSnapshot()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void TIASurface::updateSurfaceSettings()
|
void TIASurface::updateSurfaceSettings()
|
||||||
{
|
{
|
||||||
myTiaSurface->setScalingInterpolation(interpolationModeFromSettings(myOSystem.settings()));
|
myTiaSurface->setScalingInterpolation(
|
||||||
|
interpolationModeFromSettings(myOSystem.settings())
|
||||||
|
);
|
||||||
mySLineSurface->setScalingInterpolation(
|
mySLineSurface->setScalingInterpolation(
|
||||||
interpolationModeFromSettings(myOSystem.settings())
|
interpolationModeFromSettings(myOSystem.settings())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool TIASurface::correctAspect() const {
|
bool TIASurface::correctAspect() const
|
||||||
|
{
|
||||||
return myOSystem.settings().getBool("tia.correct_aspect");
|
return myOSystem.settings().getBool("tia.correct_aspect");
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,8 @@ class TIASurface
|
||||||
@param rgb_palette The RGB components of the palette, needed for
|
@param rgb_palette The RGB components of the palette, needed for
|
||||||
calculating a phosphor palette
|
calculating a phosphor palette
|
||||||
*/
|
*/
|
||||||
void setPalette(const PaletteArray& tia_palette, const PaletteArray& rgb_palette);
|
void setPalette(const PaletteArray& tia_palette,
|
||||||
|
const PaletteArray& rgb_palette);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get a TIA surface that has no post-processing whatsoever. This is
|
Get a TIA surface that has no post-processing whatsoever. This is
|
||||||
|
@ -77,6 +78,11 @@ class TIASurface
|
||||||
*/
|
*/
|
||||||
const FBSurface& baseSurface(Common::Rect& rect) const;
|
const FBSurface& baseSurface(Common::Rect& rect) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a underlying FBSurface that the TIA is being rendered into.
|
||||||
|
*/
|
||||||
|
const FBSurface& tiaSurface() const { return *myTiaSurface; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Use the palette to map a single indexed pixel color. This is used by the
|
Use the palette to map a single indexed pixel color. This is used by the
|
||||||
TIA output widget.
|
TIA output widget.
|
||||||
|
|
|
@ -16,25 +16,13 @@
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
|
||||||
#include "OSystem.hxx"
|
|
||||||
#include "AtariNTSC.hxx"
|
|
||||||
#include "TIAConstants.hxx"
|
|
||||||
|
|
||||||
#include "FBSurfaceLIBRETRO.hxx"
|
#include "FBSurfaceLIBRETRO.hxx"
|
||||||
#include "FrameBufferLIBRETRO.hxx"
|
#include "FBBackendLIBRETRO.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBufferLIBRETRO::FrameBufferLIBRETRO(OSystem& osystem)
|
void FBBackendLIBRETRO::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
: FrameBuffer(osystem),
|
vector<Common::Size>& windowedRes,
|
||||||
myRenderSurface(nullptr)
|
VariantList& renderers)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameBufferLIBRETRO::queryHardware(vector<Common::Size>& fullscreenRes,
|
|
||||||
vector<Common::Size>& windowedRes,
|
|
||||||
VariantList& renderers)
|
|
||||||
{
|
{
|
||||||
fullscreenRes.emplace_back(1920, 1080);
|
fullscreenRes.emplace_back(1920, 1080);
|
||||||
windowedRes.emplace_back(1920, 1080);
|
windowedRes.emplace_back(1920, 1080);
|
||||||
|
@ -43,18 +31,8 @@ void FrameBufferLIBRETRO::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
unique_ptr<FBSurface>
|
unique_ptr<FBSurface> FBBackendLIBRETRO::createSurface(
|
||||||
FrameBufferLIBRETRO::createSurface(uInt32 w, uInt32 h, ScalingInterpolation, const uInt32* data) const
|
uInt32 w, uInt32 h, ScalingInterpolation, const uInt32*) const
|
||||||
{
|
{
|
||||||
unique_ptr<FBSurface> ptr = make_unique<FBSurfaceLIBRETRO>
|
return make_unique<FBSurfaceLIBRETRO>(w, h);
|
||||||
(const_cast<FrameBufferLIBRETRO&>(*this), w, h, data);
|
|
||||||
|
|
||||||
if(w == AtariNTSC::outWidth(TIAConstants::frameBufferWidth) &&
|
|
||||||
h == TIAConstants::frameBufferHeight)
|
|
||||||
{
|
|
||||||
uInt32 pitch;
|
|
||||||
ptr.get()->basePtr(myRenderSurface, pitch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// 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 FB_BACKEND_LIBRETRO_HXX
|
||||||
|
#define FB_BACKEND_LIBRETRO_HXX
|
||||||
|
|
||||||
|
class OSystem;
|
||||||
|
|
||||||
|
#include "bspf.hxx"
|
||||||
|
#include "FBBackend.hxx"
|
||||||
|
|
||||||
|
/**
|
||||||
|
This class implements a standard LIBRETRO backend. Most of the
|
||||||
|
functionality is not used, since libretro has its own rendering system.
|
||||||
|
|
||||||
|
@author Stephen Anthony
|
||||||
|
*/
|
||||||
|
class FBBackendLIBRETRO : public FBBackend
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Creates a new LIBRETRO framebuffer.
|
||||||
|
*/
|
||||||
|
explicit FBBackendLIBRETRO(OSystem&) { }
|
||||||
|
~FBBackendLIBRETRO() override { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
This method is called to map a given R/G/B triple to the screen palette.
|
||||||
|
|
||||||
|
@param r The red component of the color.
|
||||||
|
@param g The green component of the color.
|
||||||
|
@param b The blue component of the color.
|
||||||
|
*/
|
||||||
|
uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const override {
|
||||||
|
return (r << 16) | (g << 8) | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to query and initialize the video hardware
|
||||||
|
for desktop and fullscreen resolution information. Since several
|
||||||
|
monitors may be attached, we need the resolution for all of them.
|
||||||
|
|
||||||
|
@param fullscreenRes Maximum resolution supported in fullscreen mode
|
||||||
|
@param windowedRes Maximum resolution supported in windowed mode
|
||||||
|
@param renderers List of renderer names (internal name -> end-user name)
|
||||||
|
*/
|
||||||
|
void queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
|
vector<Common::Size>& windowedRes,
|
||||||
|
VariantList& renderers) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to create a surface with the given attributes.
|
||||||
|
|
||||||
|
@param w The requested width of the new surface.
|
||||||
|
@param h The requested height of the new surface.
|
||||||
|
*/
|
||||||
|
unique_ptr<FBSurface>
|
||||||
|
createSurface(uInt32 w, uInt32 h, ScalingInterpolation,
|
||||||
|
const uInt32*) const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
This method is called to provide information about the backend.
|
||||||
|
*/
|
||||||
|
string about() const override { return "Video system: libretro"; }
|
||||||
|
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
// Most methods here aren't used at all. See FBBacked class for
|
||||||
|
// description, if needed.
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
int scaleX(int x) const override { return x; }
|
||||||
|
int scaleY(int y) const override { return y; }
|
||||||
|
void setTitle(const string&) override { }
|
||||||
|
void showCursor(bool) override { }
|
||||||
|
bool fullScreen() const override { return true; }
|
||||||
|
void getRGB(uInt32, uInt8*, uInt8*, uInt8*) const override { }
|
||||||
|
void readPixels(uInt8*, uInt32, const Common::Rect&) const override { }
|
||||||
|
bool isCurrentWindowPositioned() const override { return true; }
|
||||||
|
Common::Point getCurrentWindowPos() const override { return Common::Point{}; }
|
||||||
|
Int32 getCurrentDisplayIndex() const override { return 0; }
|
||||||
|
void clear() override { }
|
||||||
|
bool setVideoMode(const VideoModeHandler::Mode&,
|
||||||
|
int, const Common::Point&) override { return true; }
|
||||||
|
void grabMouse(bool) override { }
|
||||||
|
void renderToScreen() override { }
|
||||||
|
int refreshRate() const override { return 0; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Following constructors and assignment operators not supported
|
||||||
|
FBBackendLIBRETRO() = delete;
|
||||||
|
FBBackendLIBRETRO(const FBBackendLIBRETRO&) = delete;
|
||||||
|
FBBackendLIBRETRO(FBBackendLIBRETRO&&) = delete;
|
||||||
|
FBBackendLIBRETRO& operator=(const FBBackendLIBRETRO&) = delete;
|
||||||
|
FBBackendLIBRETRO& operator=(FBBackendLIBRETRO&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -18,15 +18,7 @@
|
||||||
#include "FBSurfaceLIBRETRO.hxx"
|
#include "FBSurfaceLIBRETRO.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceLIBRETRO::FBSurfaceLIBRETRO(FrameBufferLIBRETRO&,
|
FBSurfaceLIBRETRO::FBSurfaceLIBRETRO(uInt32 width, uInt32 height)
|
||||||
uInt32 width, uInt32 height, const uInt32* data)
|
|
||||||
{
|
|
||||||
createSurface(width, height, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FBSurfaceLIBRETRO::createSurface(uInt32 width, uInt32 height,
|
|
||||||
const uInt32* data)
|
|
||||||
{
|
{
|
||||||
myWidth = width;
|
myWidth = width;
|
||||||
myHeight = height;
|
myHeight = height;
|
||||||
|
@ -39,9 +31,3 @@ void FBSurfaceLIBRETRO::createSurface(uInt32 width, uInt32 height,
|
||||||
myPitch = width;
|
myPitch = width;
|
||||||
////////////////////////////////////////////////////
|
////////////////////////////////////////////////////
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FBSurfaceLIBRETRO::render()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
|
@ -20,23 +20,22 @@
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FBSurface.hxx"
|
#include "FBSurface.hxx"
|
||||||
#include "FrameBufferLIBRETRO.hxx"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
An FBSurface suitable for the LIBRETRO Render2D API, making use of hardware
|
An FBSurface suitable for the LIBRETRO Render2D API. As with FBBackend,
|
||||||
acceleration behind the scenes.
|
most of the functionality here is handled by libretro directly.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
*/
|
*/
|
||||||
class FBSurfaceLIBRETRO : public FBSurface
|
class FBSurfaceLIBRETRO : public FBSurface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FBSurfaceLIBRETRO(FrameBufferLIBRETRO& buffer, uInt32 width, uInt32 height,
|
FBSurfaceLIBRETRO(uInt32 width, uInt32 height);
|
||||||
const uInt32* data);
|
|
||||||
~FBSurfaceLIBRETRO() override { }
|
~FBSurfaceLIBRETRO() override { }
|
||||||
|
|
||||||
// Most of the surface drawing primitives are implemented in FBSurface;
|
// Most of the surface drawing primitives are implemented in FBSurface;
|
||||||
void fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId color) override { }
|
void fillRect(uInt32 x, uInt32 y, uInt32 w,
|
||||||
|
uInt32 h, ColorId color) override { }
|
||||||
|
|
||||||
uInt32 width() const override { return myWidth; }
|
uInt32 width() const override { return myWidth; }
|
||||||
uInt32 height() const override { return myHeight; }
|
uInt32 height() const override { return myHeight; }
|
||||||
|
@ -50,7 +49,7 @@ class FBSurfaceLIBRETRO : public FBSurface
|
||||||
void setVisible(bool visible) override { }
|
void setVisible(bool visible) override { }
|
||||||
|
|
||||||
void translateCoords(Int32& x, Int32& y) const override { }
|
void translateCoords(Int32& x, Int32& y) const override { }
|
||||||
bool render() override;
|
bool render() override { return true; }
|
||||||
void invalidate() override { }
|
void invalidate() override { }
|
||||||
void free() override { }
|
void free() override { }
|
||||||
void reload() override { }
|
void reload() override { }
|
||||||
|
@ -61,22 +60,17 @@ class FBSurfaceLIBRETRO : public FBSurface
|
||||||
void applyAttributes() override { }
|
void applyAttributes() override { }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createSurface(uInt32 width, uInt32 height, const uInt32* data);
|
unique_ptr<uInt32[]> myPixelData;
|
||||||
|
uInt32 myWidth, myHeight;
|
||||||
|
Common::Rect mySrcGUIR, myDstGUIR;
|
||||||
|
|
||||||
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
FBSurfaceLIBRETRO() = delete;
|
FBSurfaceLIBRETRO() = delete;
|
||||||
FBSurfaceLIBRETRO(const FBSurfaceLIBRETRO&) = delete;
|
FBSurfaceLIBRETRO(const FBSurfaceLIBRETRO&) = delete;
|
||||||
FBSurfaceLIBRETRO(FBSurfaceLIBRETRO&&) = delete;
|
FBSurfaceLIBRETRO(FBSurfaceLIBRETRO&&) = delete;
|
||||||
FBSurfaceLIBRETRO& operator=(const FBSurfaceLIBRETRO&) = delete;
|
FBSurfaceLIBRETRO& operator=(const FBSurfaceLIBRETRO&) = delete;
|
||||||
FBSurfaceLIBRETRO& operator=(FBSurfaceLIBRETRO&&) = delete;
|
FBSurfaceLIBRETRO& operator=(FBSurfaceLIBRETRO&&) = delete;
|
||||||
|
|
||||||
private:
|
|
||||||
Common::Rect mySrcGUIR, myDstGUIR;
|
|
||||||
|
|
||||||
private:
|
|
||||||
unique_ptr<uInt32[]> myPixelData;
|
|
||||||
|
|
||||||
uInt32 myWidth, myHeight;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// 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 FRAMEBUFFER_LIBRETRO_HXX
|
|
||||||
#define FRAMEBUFFER_LIBRETRO_HXX
|
|
||||||
|
|
||||||
class OSystem;
|
|
||||||
class FBSurfaceLIBRETRO;
|
|
||||||
|
|
||||||
#include "bspf.hxx"
|
|
||||||
#include "FrameBuffer.hxx"
|
|
||||||
|
|
||||||
/**
|
|
||||||
This class implements a standard LIBRETRO 2D, hardware accelerated framebuffer.
|
|
||||||
Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
|
||||||
|
|
||||||
@author Stephen Anthony
|
|
||||||
*/
|
|
||||||
class FrameBufferLIBRETRO : public FrameBuffer
|
|
||||||
{
|
|
||||||
friend class FBSurfaceLIBRETRO;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Creates a new LIBRETRO framebuffer
|
|
||||||
*/
|
|
||||||
explicit FrameBufferLIBRETRO(OSystem& osystem);
|
|
||||||
~FrameBufferLIBRETRO() override { }
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// The following are derived from public methods in FrameBuffer.hxx
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/**
|
|
||||||
Updates window title.
|
|
||||||
|
|
||||||
@param title The title of the application / window
|
|
||||||
*/
|
|
||||||
void setTitle(const string& title) override { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Shows or hides the cursor based on the given boolean value.
|
|
||||||
*/
|
|
||||||
void showCursor(bool show) override { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Answers if the display is currently in fullscreen mode.
|
|
||||||
*/
|
|
||||||
bool fullScreen() const override { return true; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to retrieve the R/G/B data from the given pixel.
|
|
||||||
|
|
||||||
@param pixel The pixel containing R/G/B data
|
|
||||||
@param r The red component of the color
|
|
||||||
@param g The green component of the color
|
|
||||||
@param b The blue component of the color
|
|
||||||
*/
|
|
||||||
inline void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const override { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to map a given R/G/B triple to the screen palette.
|
|
||||||
|
|
||||||
@param r The red component of the color.
|
|
||||||
@param g The green component of the color.
|
|
||||||
@param b The blue component of the color.
|
|
||||||
*/
|
|
||||||
inline uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const override { return (r << 16) | (g << 8) | b; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to get a copy of the specified ARGB data from the
|
|
||||||
viewable FrameBuffer area. Note that this isn't the same as any
|
|
||||||
internal surfaces that may be in use; it should return the actual data
|
|
||||||
as it is currently seen onscreen.
|
|
||||||
|
|
||||||
@param buffer A copy of the pixel data in ARGB8888 format
|
|
||||||
@param pitch The pitch (in bytes) for the pixel data
|
|
||||||
@param rect The bounding rectangle for the buffer
|
|
||||||
*/
|
|
||||||
void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const override { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Clear the frame buffer
|
|
||||||
*/
|
|
||||||
void clear() override { }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// The following are derived from protected methods in FrameBuffer.hxx
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
/**
|
|
||||||
This method is called to query and initialize the video hardware
|
|
||||||
for desktop and fullscreen resolution information. Since several
|
|
||||||
monitors may be attached, we need the resolution for all of them.
|
|
||||||
|
|
||||||
@param fullscreenRes Maximum resolution supported in fullscreen mode
|
|
||||||
@param windowedRes Maximum resolution supported in windowed mode
|
|
||||||
@param renderers List of renderer names (internal name -> end-user name)
|
|
||||||
*/
|
|
||||||
void queryHardware(vector<Common::Size>& fullscreenRes,
|
|
||||||
vector<Common::Size>& windowedRes,
|
|
||||||
VariantList& renderers) override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to query if the current window is not centered or fullscreen.
|
|
||||||
|
|
||||||
@return True, if the current window is positioned
|
|
||||||
*/
|
|
||||||
bool isCurrentWindowPositioned() const override { return true; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to query the video hardware for position of
|
|
||||||
the current window
|
|
||||||
|
|
||||||
@return The position of the currently displayed window
|
|
||||||
*/
|
|
||||||
Common::Point getCurrentWindowPos() const override { return Common::Point{}; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to query the video hardware for the index
|
|
||||||
of the display the current window is displayed on
|
|
||||||
|
|
||||||
@return the current display index or a negative value if no
|
|
||||||
window is displayed
|
|
||||||
*/
|
|
||||||
Int32 getCurrentDisplayIndex() const override { return 0; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to change to the given video mode.
|
|
||||||
|
|
||||||
@param title The title for the created window
|
|
||||||
@param mode The video mode to use
|
|
||||||
|
|
||||||
@return False on any errors, else 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.
|
|
||||||
|
|
||||||
@param w The requested width of the new surface.
|
|
||||||
@param h The requested height of the new surface.
|
|
||||||
@param data If non-null, use the given data values as a static surface
|
|
||||||
*/
|
|
||||||
unique_ptr<FBSurface>
|
|
||||||
createSurface(uInt32 w, uInt32 h, ScalingInterpolation, const uInt32* data) const override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Grabs or ungrabs the mouse based on the given boolean value.
|
|
||||||
*/
|
|
||||||
void grabMouse(bool grab) override { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Set the icon for the main SDL window.
|
|
||||||
*/
|
|
||||||
void setWindowIcon() override { }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to provide information about the FrameBuffer.
|
|
||||||
*/
|
|
||||||
string about() const override { return "Video system: libretro"; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method must be called after all drawing is done, and indicates
|
|
||||||
that the buffers should be pushed to the physical screen.
|
|
||||||
*/
|
|
||||||
void renderToScreen() override { }
|
|
||||||
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
Returns a pointer to the output rendering buffer
|
|
||||||
*/
|
|
||||||
uInt32* getRenderSurface() const { return myRenderSurface; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
mutable uInt32* myRenderSurface;
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Following constructors and assignment operators not supported
|
|
||||||
FrameBufferLIBRETRO() = delete;
|
|
||||||
FrameBufferLIBRETRO(const FrameBufferLIBRETRO&) = delete;
|
|
||||||
FrameBufferLIBRETRO(FrameBufferLIBRETRO&&) = delete;
|
|
||||||
FrameBufferLIBRETRO& operator=(const FrameBufferLIBRETRO&) = delete;
|
|
||||||
FrameBufferLIBRETRO& operator=(FrameBufferLIBRETRO&&) = delete;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -9,8 +9,8 @@ SOURCES_CXX := \
|
||||||
$(CORE_DIR)/libretro/libretro.cxx \
|
$(CORE_DIR)/libretro/libretro.cxx \
|
||||||
$(CORE_DIR)/libretro/EventHandlerLIBRETRO.cxx \
|
$(CORE_DIR)/libretro/EventHandlerLIBRETRO.cxx \
|
||||||
$(CORE_DIR)/libretro/FSNodeLIBRETRO.cxx \
|
$(CORE_DIR)/libretro/FSNodeLIBRETRO.cxx \
|
||||||
|
$(CORE_DIR)/libretro/FBBackendLIBRETRO.cxx \
|
||||||
$(CORE_DIR)/libretro/FBSurfaceLIBRETRO.cxx \
|
$(CORE_DIR)/libretro/FBSurfaceLIBRETRO.cxx \
|
||||||
$(CORE_DIR)/libretro/FrameBufferLIBRETRO.cxx \
|
|
||||||
$(CORE_DIR)/libretro/OSystemLIBRETRO.cxx \
|
$(CORE_DIR)/libretro/OSystemLIBRETRO.cxx \
|
||||||
$(CORE_DIR)/libretro/SoundLIBRETRO.cxx \
|
$(CORE_DIR)/libretro/SoundLIBRETRO.cxx \
|
||||||
$(CORE_DIR)/libretro/StellaLIBRETRO.cxx \
|
$(CORE_DIR)/libretro/StellaLIBRETRO.cxx \
|
||||||
|
|
|
@ -18,10 +18,10 @@
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "StellaLIBRETRO.hxx"
|
#include "StellaLIBRETRO.hxx"
|
||||||
#include "SoundLIBRETRO.hxx"
|
#include "SoundLIBRETRO.hxx"
|
||||||
#include "FrameBufferLIBRETRO.hxx"
|
#include "FBBackendLIBRETRO.hxx"
|
||||||
|
#include "FBSurfaceLIBRETRO.hxx"
|
||||||
|
|
||||||
#include "AtariNTSC.hxx"
|
#include "AtariNTSC.hxx"
|
||||||
#include "PaletteHandler.hxx"
|
|
||||||
#include "AudioSettings.hxx"
|
#include "AudioSettings.hxx"
|
||||||
#include "Serializer.hxx"
|
#include "Serializer.hxx"
|
||||||
#include "StateManager.hxx"
|
#include "StateManager.hxx"
|
||||||
|
@ -33,27 +33,7 @@
|
||||||
StellaLIBRETRO::StellaLIBRETRO()
|
StellaLIBRETRO::StellaLIBRETRO()
|
||||||
{
|
{
|
||||||
audio_buffer = make_unique<Int16[]>(audio_buffer_max);
|
audio_buffer = make_unique<Int16[]>(audio_buffer_max);
|
||||||
|
|
||||||
console_timing = ConsoleTiming::ntsc;
|
|
||||||
console_format = "AUTO";
|
|
||||||
|
|
||||||
video_aspect_ntsc = 0;
|
|
||||||
video_aspect_pal = 0;
|
|
||||||
|
|
||||||
video_palette = PaletteHandler::SETTING_STANDARD;
|
|
||||||
video_filter = NTSCFilter::Preset::OFF;
|
|
||||||
video_ready = false;
|
|
||||||
|
|
||||||
audio_samples = 0;
|
|
||||||
audio_mode = "byrom";
|
|
||||||
|
|
||||||
video_phosphor = "byrom";
|
|
||||||
video_phosphor_blend = 60;
|
|
||||||
phosphor_default = false;
|
|
||||||
|
|
||||||
rom_image = make_unique<uInt8[]>(getROMMax());
|
rom_image = make_unique<uInt8[]>(getROMMax());
|
||||||
|
|
||||||
system_ready = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -302,9 +282,16 @@ float StellaLIBRETRO::getVideoAspect() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void* StellaLIBRETRO::getVideoBuffer() const
|
void* StellaLIBRETRO::getVideoBuffer() const
|
||||||
{
|
{
|
||||||
FrameBufferLIBRETRO& frame = static_cast<FrameBufferLIBRETRO&>(myOSystem->frameBuffer());
|
if (!render_surface)
|
||||||
|
{
|
||||||
|
const FBSurface& surface =
|
||||||
|
myOSystem->frameBuffer().tiaSurface().tiaSurface();
|
||||||
|
|
||||||
return static_cast<void*>(frame.getRenderSurface());
|
uInt32 pitch = 0;
|
||||||
|
surface.basePtr(render_surface, pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return render_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "EventHandler.hxx"
|
#include "EventHandler.hxx"
|
||||||
#include "M6532.hxx"
|
#include "M6532.hxx"
|
||||||
#include "Paddles.hxx"
|
#include "Paddles.hxx"
|
||||||
|
#include "PaletteHandler.hxx"
|
||||||
#include "System.hxx"
|
#include "System.hxx"
|
||||||
#include "TIA.hxx"
|
#include "TIA.hxx"
|
||||||
#include "TIASurface.hxx"
|
#include "TIASurface.hxx"
|
||||||
|
@ -122,7 +123,7 @@ class StellaLIBRETRO
|
||||||
void setAudioStereo(int mode);
|
void setAudioStereo(int mode);
|
||||||
|
|
||||||
void setInputEvent(Event::Type type, Int32 state) {
|
void setInputEvent(Event::Type type, Int32 state) {
|
||||||
myOSystem->eventHandler().handleEvent(type, state);
|
myOSystem->eventHandler().handleEvent(type, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller::Type getLeftControllerType() const {
|
Controller::Type getLeftControllerType() const {
|
||||||
|
@ -153,39 +154,40 @@ class StellaLIBRETRO
|
||||||
StellaLIBRETRO& operator=(StellaLIBRETRO&&) = delete;
|
StellaLIBRETRO& operator=(StellaLIBRETRO&&) = delete;
|
||||||
|
|
||||||
unique_ptr<OSystemLIBRETRO> myOSystem;
|
unique_ptr<OSystemLIBRETRO> myOSystem;
|
||||||
uInt32 system_ready;
|
uInt32 system_ready{false};
|
||||||
|
|
||||||
ByteBuffer rom_image;
|
ByteBuffer rom_image;
|
||||||
uInt32 rom_size;
|
uInt32 rom_size{0};
|
||||||
string rom_path;
|
string rom_path;
|
||||||
|
|
||||||
ConsoleTiming console_timing;
|
ConsoleTiming console_timing{ConsoleTiming::ntsc};
|
||||||
string console_format;
|
string console_format{"AUTO"};
|
||||||
|
|
||||||
uInt32 render_width, render_height;
|
mutable uInt32* render_surface{nullptr};
|
||||||
|
uInt32 render_width{0}, render_height{0};
|
||||||
|
|
||||||
bool video_ready;
|
bool video_ready{false};
|
||||||
|
|
||||||
unique_ptr<Int16[]> audio_buffer;
|
unique_ptr<Int16[]> audio_buffer;
|
||||||
uInt32 audio_samples;
|
uInt32 audio_samples{0};
|
||||||
|
|
||||||
// (31440 rate / 50 Hz) * 16-bit stereo * 1.25x padding
|
|
||||||
const uInt32 audio_buffer_max = (31440 / 50 * 4 * 5) / 4;
|
|
||||||
|
|
||||||
uInt8 system_ram[128];
|
uInt8 system_ram[128];
|
||||||
|
|
||||||
|
// (31440 rate / 50 Hz) * 16-bit stereo * 1.25x padding
|
||||||
|
static constexpr uInt32 audio_buffer_max = (31440 / 50 * 4 * 5) / 4;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string video_palette;
|
string video_palette{PaletteHandler::SETTING_STANDARD};
|
||||||
string video_phosphor;
|
string video_phosphor{"byrom"};
|
||||||
uInt32 video_phosphor_blend;
|
uInt32 video_phosphor_blend{60};
|
||||||
|
|
||||||
uInt32 video_aspect_ntsc;
|
uInt32 video_aspect_ntsc{0};
|
||||||
uInt32 video_aspect_pal;
|
uInt32 video_aspect_pal{0};
|
||||||
NTSCFilter::Preset video_filter;
|
NTSCFilter::Preset video_filter{NTSCFilter::Preset::OFF};
|
||||||
|
|
||||||
string audio_mode;
|
string audio_mode{"byrom"};
|
||||||
|
|
||||||
bool phosphor_default;
|
bool phosphor_default{false};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -495,9 +495,9 @@
|
||||||
<ClCompile Include="..\common\audio\SimpleResampler.cxx" />
|
<ClCompile Include="..\common\audio\SimpleResampler.cxx" />
|
||||||
<ClCompile Include="..\common\Base.cxx" />
|
<ClCompile Include="..\common\Base.cxx" />
|
||||||
<ClCompile Include="..\common\EventHandlerSDL2.cxx" />
|
<ClCompile Include="..\common\EventHandlerSDL2.cxx" />
|
||||||
|
<ClCompile Include="..\common\FBBackendSDL2.cxx" />
|
||||||
<ClCompile Include="..\common\FBSurfaceSDL2.cxx" />
|
<ClCompile Include="..\common\FBSurfaceSDL2.cxx" />
|
||||||
<ClCompile Include="..\common\FpsMeter.cxx" />
|
<ClCompile Include="..\common\FpsMeter.cxx" />
|
||||||
<ClCompile Include="..\common\FrameBufferSDL2.cxx" />
|
|
||||||
<ClCompile Include="..\common\FSNodeZIP.cxx" />
|
<ClCompile Include="..\common\FSNodeZIP.cxx" />
|
||||||
<ClCompile Include="..\common\JoyMap.cxx" />
|
<ClCompile Include="..\common\JoyMap.cxx" />
|
||||||
<ClCompile Include="..\common\KeyMap.cxx" />
|
<ClCompile Include="..\common\KeyMap.cxx" />
|
||||||
|
@ -1508,9 +1508,9 @@
|
||||||
<ClInclude Include="..\common\Base.hxx" />
|
<ClInclude Include="..\common\Base.hxx" />
|
||||||
<ClInclude Include="..\common\bspf.hxx" />
|
<ClInclude Include="..\common\bspf.hxx" />
|
||||||
<ClInclude Include="..\common\EventHandlerSDL2.hxx" />
|
<ClInclude Include="..\common\EventHandlerSDL2.hxx" />
|
||||||
|
<ClInclude Include="..\common\FBBackendSDL2.hxx" />
|
||||||
<ClInclude Include="..\common\FBSurfaceSDL2.hxx" />
|
<ClInclude Include="..\common\FBSurfaceSDL2.hxx" />
|
||||||
<ClInclude Include="..\common\FpsMeter.hxx" />
|
<ClInclude Include="..\common\FpsMeter.hxx" />
|
||||||
<ClInclude Include="..\common\FrameBufferSDL2.hxx" />
|
|
||||||
<ClInclude Include="..\common\FSNodeFactory.hxx" />
|
<ClInclude Include="..\common\FSNodeFactory.hxx" />
|
||||||
<ClInclude Include="..\common\FSNodeZIP.hxx" />
|
<ClInclude Include="..\common\FSNodeZIP.hxx" />
|
||||||
<ClInclude Include="..\common\JoyMap.hxx" />
|
<ClInclude Include="..\common\JoyMap.hxx" />
|
||||||
|
@ -2060,4 +2060,4 @@
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
</Filter>
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\common\FrameBufferSDL2.cxx">
|
<ClCompile Include="..\common\FBBackendSDL2.cxx">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="FSNodeWINDOWS.cxx">
|
<ClCompile Include="FSNodeWINDOWS.cxx">
|
||||||
|
@ -1034,7 +1034,7 @@
|
||||||
<ClInclude Include="..\common\bspf.hxx">
|
<ClInclude Include="..\common\bspf.hxx">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\common\FrameBufferSDL2.hxx">
|
<ClInclude Include="..\common\FBBackendSDL2.hxx">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="HomeFinder.hxx">
|
<ClInclude Include="HomeFinder.hxx">
|
||||||
|
@ -2126,4 +2126,4 @@
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Reference in New Issue