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 "FBSurfaceSDL2.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||
: FrameBuffer(osystem)
|
||||
FBBackendSDL2::FBBackendSDL2(OSystem& osystem)
|
||||
: myOSystem(osystem)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -43,7 +43,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
|||
Logger::error(buf.str());
|
||||
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
|
||||
// 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;
|
||||
|
||||
|
@ -61,12 +61,6 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
|||
|
||||
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);
|
||||
myRenderer = nullptr;
|
||||
}
|
||||
|
@ -81,9 +75,9 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
void FBBackendSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -105,7 +99,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
|
||||
string lastRes = "";
|
||||
|
||||
for (int m = 0; m < numModes; m++)
|
||||
for(int m = 0; m < numModes; ++m)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
ostringstream res;
|
||||
|
@ -196,7 +190,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
||||
bool FBBackendSDL2::isCurrentWindowPositioned() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -205,7 +199,7 @@ bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
||||
Common::Point FBBackendSDL2::getCurrentWindowPos() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -217,7 +211,7 @@ Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
||||
Int32 FBBackendSDL2::getCurrentDisplayIndex() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -225,8 +219,8 @@ Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::activateVideoMode(const string& title,
|
||||
const VideoModeHandler::Mode& mode)
|
||||
bool FBBackendSDL2::setVideoMode(const VideoModeHandler::Mode& mode,
|
||||
int winIdx, const Common::Point& winPos)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -236,26 +230,22 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
|||
|
||||
const bool fullScreen = mode.fsIndex != -1;
|
||||
bool forceCreateRenderer = false;
|
||||
|
||||
// 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());
|
||||
Int32 displayIndex = std::min(myNumDisplays, winIdx);
|
||||
|
||||
int posX, posY;
|
||||
|
||||
myCenter = myOSystem.settings().getBool("center");
|
||||
if (myCenter)
|
||||
if(myCenter)
|
||||
posX = posY = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
||||
else
|
||||
{
|
||||
posX = myWindowedPos.x;
|
||||
posY = myWindowedPos.y;
|
||||
posX = winPos.x;
|
||||
posY = winPos.y;
|
||||
|
||||
// Make sure the window is at least partially visibile
|
||||
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;
|
||||
|
||||
|
@ -273,16 +263,22 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
|||
|
||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||
SDL_DisplayMode adaptedSdlMode;
|
||||
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
|
||||
&& gameRefreshRate()
|
||||
const int gameRefreshRate =
|
||||
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||
const bool shouldAdapt = fullScreen
|
||||
&& myOSystem.settings().getBool("tia.fs_refresh")
|
||||
&& gameRefreshRate
|
||||
// take care of 59.94 Hz
|
||||
&& refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0;
|
||||
const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||
&& refreshRate() % gameRefreshRate != 0
|
||||
&& refreshRate() % (gameRefreshRate - 1) != 0;
|
||||
const bool adaptRefresh = shouldAdapt &&
|
||||
adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||
#else
|
||||
const bool adaptRefresh = false;
|
||||
#endif
|
||||
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,
|
||||
// as it's not necessary, and causes flashing in fullscreen mode
|
||||
|
@ -303,13 +299,13 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
|||
if(myWindow)
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
if(myWindow == nullptr)
|
||||
{
|
||||
|
@ -333,7 +329,8 @@ bool FrameBufferSDL2::activateVideoMode(const string& title,
|
|||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
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 wantedRefreshRate = gameRefreshRate();
|
||||
const int wantedRefreshRate =
|
||||
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||
// Take care of rounded refresh rates (e.g. 59.94 Hz)
|
||||
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
|
||||
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:
|
||||
// - new myWindow (force = true)
|
||||
// - 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;
|
||||
|
||||
|
@ -462,7 +465,7 @@ void FrameBufferSDL2::setTitle(const string& title)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string FrameBufferSDL2::about() const
|
||||
string FBBackendSDL2::about() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -484,7 +487,7 @@ string FrameBufferSDL2::about() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::showCursor(bool show)
|
||||
void FBBackendSDL2::showCursor(bool show)
|
||||
{
|
||||
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;
|
||||
|
||||
|
@ -500,7 +503,7 @@ void FrameBufferSDL2::grabMouse(bool grab)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::fullScreen() const
|
||||
bool FBBackendSDL2::fullScreen() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -512,7 +515,7 @@ bool FrameBufferSDL2::fullScreen() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int FrameBufferSDL2::refreshRate() const
|
||||
int FBBackendSDL2::refreshRate() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -529,20 +532,7 @@ int FrameBufferSDL2::refreshRate() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int FrameBufferSDL2::gameRefreshRate() const
|
||||
{
|
||||
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()
|
||||
void FBBackendSDL2::renderToScreen()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -551,7 +541,7 @@ void FrameBufferSDL2::renderToScreen()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::setWindowIcon()
|
||||
void FBBackendSDL2::setWindowIcon()
|
||||
{
|
||||
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
||||
#include "stella_icon.hxx"
|
||||
|
@ -565,19 +555,20 @@ void FrameBufferSDL2::setWindowIcon()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
unique_ptr<FBSurface> FrameBufferSDL2::createSurface(
|
||||
unique_ptr<FBSurface> FBBackendSDL2::createSurface(
|
||||
uInt32 w,
|
||||
uInt32 h,
|
||||
ScalingInterpolation interpolation,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* data
|
||||
) 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,
|
||||
const Common::Rect& rect) const
|
||||
void FBBackendSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||
const Common::Rect& rect) const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -589,7 +580,7 @@ void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::clear()
|
||||
void FBBackendSDL2::clear()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -597,49 +588,34 @@ void FrameBufferSDL2::clear()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SDL_Renderer* FrameBufferSDL2::renderer()
|
||||
{
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::isInitialized() const
|
||||
{
|
||||
return myRenderer != nullptr;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const SDL_PixelFormat& FrameBufferSDL2::pixelFormat() const
|
||||
{
|
||||
return *myPixelFormat;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::detectFeatures()
|
||||
void FBBackendSDL2::detectFeatures()
|
||||
{
|
||||
myRenderTargetSupport = detectRenderTargetSupport();
|
||||
|
||||
if (myRenderer) {
|
||||
if (!myRenderTargetSupport) {
|
||||
Logger::info("Render targets are not supported --- QIS not available");
|
||||
}
|
||||
}
|
||||
if(myRenderer && !myRenderTargetSupport)
|
||||
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_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);
|
||||
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);
|
||||
|
||||
if (myRenderer == nullptr) {
|
||||
if(myRenderer == nullptr)
|
||||
{
|
||||
myRenderW = myWindowW;
|
||||
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.
|
||||
//============================================================================
|
||||
|
||||
#ifndef FRAMEBUFFER_SDL2_HXX
|
||||
#define FRAMEBUFFER_SDL2_HXX
|
||||
#ifndef FB_BACKEND_SDL2_HXX
|
||||
#define FB_BACKEND_SDL2_HXX
|
||||
|
||||
#include "SDL_lib.hxx"
|
||||
|
||||
|
@ -24,27 +24,55 @@ class OSystem;
|
|||
class FBSurfaceSDL2;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "FBBackend.hxx"
|
||||
|
||||
/**
|
||||
This class implements a standard SDL2 2D, hardware accelerated framebuffer.
|
||||
Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
||||
This class implements a standard SDL2 2D, hardware accelerated framebuffer
|
||||
backend. Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class FrameBufferSDL2 : public FrameBuffer
|
||||
class FBBackendSDL2 : public FBBackend
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Creates a new SDL2 framebuffer
|
||||
*/
|
||||
explicit FrameBufferSDL2(OSystem& osystem);
|
||||
~FrameBufferSDL2() override;
|
||||
explicit FBBackendSDL2(OSystem& osystem);
|
||||
~FBBackendSDL2() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// The following are derived from public methods in FrameBuffer.hxx
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
/**
|
||||
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.
|
||||
|
||||
|
@ -93,7 +121,8 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
@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;
|
||||
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
|
||||
|
@ -110,6 +139,7 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
@return The position of the currently displayed window
|
||||
*/
|
||||
Common::Point getCurrentWindowPos() const override;
|
||||
|
||||
/**
|
||||
This method is called to query the video hardware for the index
|
||||
of the display the current window is displayed on
|
||||
|
@ -124,40 +154,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
*/
|
||||
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
|
||||
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.
|
||||
|
||||
@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
|
||||
*/
|
||||
bool activateVideoMode(const string& title,
|
||||
const VideoModeHandler::Mode& mode) override;
|
||||
|
||||
/**
|
||||
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
|
||||
|
||||
@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);
|
||||
bool setVideoMode(const VideoModeHandler::Mode& mode,
|
||||
int winIdx, const Common::Point& winPos) 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.
|
||||
@param interpolation Interpolation mode
|
||||
@param data If non-null, use the given data values as a static surface
|
||||
@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
|
||||
*/
|
||||
unique_ptr<FBSurface>
|
||||
createSurface(
|
||||
uInt32 w,
|
||||
uInt32 h,
|
||||
ScalingInterpolation interpolation,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* data
|
||||
) const override;
|
||||
|
||||
|
@ -223,28 +201,49 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
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.
|
||||
This method is called to provide information about the backend.
|
||||
*/
|
||||
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
|
||||
that the buffers should be pushed to the physical screen.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void detectFeatures();
|
||||
|
||||
/**
|
||||
Detect render target support;
|
||||
Detect render target support.
|
||||
*/
|
||||
bool detectRenderTargetSupport();
|
||||
|
||||
|
@ -254,16 +253,13 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
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;
|
||||
|
||||
/**
|
||||
Retrieve the current game's refresh rate, or 60 if no game
|
||||
*/
|
||||
int gameRefreshRate() const;
|
||||
void setWindowIcon();
|
||||
|
||||
private:
|
||||
OSystem& myOSystem;
|
||||
|
||||
// The SDL video buffer
|
||||
SDL_Window* myWindow{nullptr};
|
||||
SDL_Renderer* myRenderer{nullptr};
|
||||
|
@ -274,22 +270,25 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
// Center setting of current window
|
||||
bool myCenter{false};
|
||||
|
||||
// last position of windowed window
|
||||
Common::Point myWindowedPos;
|
||||
|
||||
// Does the renderer support render targets?
|
||||
bool myRenderTargetSupport{false};
|
||||
|
||||
// Title of the main window/screen
|
||||
string myScreenTitle;
|
||||
|
||||
// Number of displays
|
||||
int myNumDisplays{1};
|
||||
|
||||
// Window and renderer dimensions
|
||||
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
FrameBufferSDL2() = delete;
|
||||
FrameBufferSDL2(const FrameBufferSDL2&) = delete;
|
||||
FrameBufferSDL2(FrameBufferSDL2&&) = delete;
|
||||
FrameBufferSDL2& operator=(const FrameBufferSDL2&) = delete;
|
||||
FrameBufferSDL2& operator=(FrameBufferSDL2&&) = delete;
|
||||
FBBackendSDL2() = delete;
|
||||
FBBackendSDL2(const FBBackendSDL2&) = delete;
|
||||
FBBackendSDL2(FBBackendSDL2&&) = delete;
|
||||
FBBackendSDL2& operator=(const FBBackendSDL2&) = delete;
|
||||
FBBackendSDL2& operator=(FBBackendSDL2&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,9 +22,9 @@
|
|||
#include "sdl_blitter/BlitterFactory.hxx"
|
||||
|
||||
namespace {
|
||||
BlitterFactory::ScalingAlgorithm scalingAlgorithm(ScalingInterpolation interpolation)
|
||||
BlitterFactory::ScalingAlgorithm scalingAlgorithm(ScalingInterpolation inter)
|
||||
{
|
||||
switch (interpolation) {
|
||||
switch (inter) {
|
||||
case ScalingInterpolation::none:
|
||||
return BlitterFactory::ScalingAlgorithm::nearestNeighbour;
|
||||
|
||||
|
@ -41,12 +41,12 @@ namespace {
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
||||
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||
uInt32 width, uInt32 height,
|
||||
ScalingInterpolation interpolation,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* staticData)
|
||||
: myFB(buffer),
|
||||
myInterpolationMode(interpolation)
|
||||
: myBackend(backend),
|
||||
myInterpolationMode(inter)
|
||||
{
|
||||
createSurface(width, height, staticData);
|
||||
}
|
||||
|
@ -214,7 +214,7 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
|||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// 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,
|
||||
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
||||
|
@ -242,11 +242,13 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::reinitializeBlitter()
|
||||
{
|
||||
if (!myBlitter && myFB.isInitialized())
|
||||
myBlitter = BlitterFactory::createBlitter(myFB, scalingAlgorithm(myInterpolationMode));
|
||||
if (!myBlitter && myBackend.isInitialized())
|
||||
myBlitter = BlitterFactory::createBlitter(
|
||||
myBackend, scalingAlgorithm(myInterpolationMode));
|
||||
|
||||
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 "FBSurface.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "sdl_blitter/Blitter.hxx"
|
||||
|
||||
/**
|
||||
|
@ -32,9 +32,8 @@
|
|||
class FBSurfaceSDL2 : public FBSurface
|
||||
{
|
||||
public:
|
||||
FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height,
|
||||
ScalingInterpolation interpolation,
|
||||
const uInt32* staticData);
|
||||
FBSurfaceSDL2(FBBackendSDL2& backend, uInt32 width, uInt32 height,
|
||||
ScalingInterpolation inter, const uInt32* staticData);
|
||||
~FBSurfaceSDL2() override;
|
||||
|
||||
// Most of the surface drawing primitives are implemented in FBSurface;
|
||||
|
@ -95,7 +94,7 @@ class FBSurfaceSDL2 : public FBSurface
|
|||
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
||||
|
||||
private:
|
||||
FrameBufferSDL2& myFB;
|
||||
FBBackendSDL2& myBackend;
|
||||
|
||||
unique_ptr<Blitter> myBlitter;
|
||||
ScalingInterpolation myInterpolationMode
|
||||
|
|
|
@ -51,10 +51,10 @@
|
|||
|
||||
#if defined(__LIB_RETRO__)
|
||||
#include "EventHandlerLIBRETRO.hxx"
|
||||
#include "FrameBufferLIBRETRO.hxx"
|
||||
#include "FBBackendLIBRETRO.hxx"
|
||||
#elif defined(SDL_SUPPORT)
|
||||
#include "EventHandlerSDL2.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#else
|
||||
#error Unsupported backend!
|
||||
#endif
|
||||
|
@ -128,12 +128,12 @@ class MediaFactory
|
|||
#endif
|
||||
}
|
||||
|
||||
static unique_ptr<FrameBuffer> createVideo(OSystem& osystem)
|
||||
static unique_ptr<FBBackend> createVideoBackend(OSystem& osystem)
|
||||
{
|
||||
#if defined(__LIB_RETRO__)
|
||||
return make_unique<FrameBufferLIBRETRO>(osystem);
|
||||
return make_unique<FBBackendLIBRETRO>(osystem);
|
||||
#elif defined(SDL_SUPPORT)
|
||||
return make_unique<FrameBufferSDL2>(osystem);
|
||||
return make_unique<FBBackendSDL2>(osystem);
|
||||
#else
|
||||
#error Unsupported platform for FrameBuffer!
|
||||
#endif
|
||||
|
|
|
@ -5,9 +5,9 @@ MODULE_OBJS := \
|
|||
src/common/AudioSettings.o \
|
||||
src/common/Base.o \
|
||||
src/common/EventHandlerSDL2.o \
|
||||
src/common/FBBackendSDL2.o \
|
||||
src/common/FBSurfaceSDL2.o \
|
||||
src/common/FpsMeter.o \
|
||||
src/common/FrameBufferSDL2.o \
|
||||
src/common/FSNodeZIP.o \
|
||||
src/common/JoyMap.o \
|
||||
src/common/KeyMap.o \
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "ThreadDebugging.hxx"
|
||||
#include "BilinearBlitter.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate)
|
||||
BilinearBlitter::BilinearBlitter(FBBackendSDL2& fb, bool interpolate)
|
||||
: myFB(fb),
|
||||
myInterpolate(interpolate)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef BILINEAR_BLITTER_HXX
|
||||
#define BILINEAR_BLITTER_HXX
|
||||
|
||||
class FrameBufferSDL2;
|
||||
class FBBackendSDL2;
|
||||
|
||||
#include "Blitter.hxx"
|
||||
#include "SDL_lib.hxx"
|
||||
|
@ -27,7 +27,7 @@ class BilinearBlitter : public Blitter {
|
|||
|
||||
public:
|
||||
|
||||
BilinearBlitter(FrameBufferSDL2& fb, bool interpolate);
|
||||
BilinearBlitter(FBBackendSDL2& fb, bool interpolate);
|
||||
|
||||
~BilinearBlitter() override;
|
||||
|
||||
|
@ -41,7 +41,7 @@ class BilinearBlitter : public Blitter {
|
|||
virtual void blit(SDL_Surface& surface) override;
|
||||
|
||||
private:
|
||||
FrameBufferSDL2& myFB;
|
||||
FBBackendSDL2& myFB;
|
||||
|
||||
SDL_Texture* myTexture{nullptr};
|
||||
SDL_Texture* mySecondaryTexture{nullptr};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "BilinearBlitter.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()) {
|
||||
throw runtime_error("BlitterFactory requires an initialized framebuffer!");
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include <string>
|
||||
|
||||
#include "Blitter.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "bspf.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
|
||||
class BlitterFactory {
|
||||
public:
|
||||
|
@ -35,7 +35,7 @@ class BlitterFactory {
|
|||
|
||||
public:
|
||||
|
||||
static unique_ptr<Blitter> createBlitter(FrameBufferSDL2& fb, ScalingAlgorithm scaling);
|
||||
static unique_ptr<Blitter> createBlitter(FBBackendSDL2& fb, ScalingAlgorithm scaling);
|
||||
};
|
||||
|
||||
#endif // BLITTER_FACTORY_HXX
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "ThreadDebugging.hxx"
|
||||
#include "QisBlitter.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
QisBlitter::QisBlitter(FrameBufferSDL2& fb)
|
||||
QisBlitter::QisBlitter(FBBackendSDL2& 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");
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef QIS_BLITTER_HXX
|
||||
#define QIS_BLITTER_HXX
|
||||
|
||||
class FrameBufferSDL2;
|
||||
class FBBackendSDL2;
|
||||
|
||||
#include "Blitter.hxx"
|
||||
#include "SDL_lib.hxx"
|
||||
|
@ -27,9 +27,9 @@ class QisBlitter : public Blitter {
|
|||
|
||||
public:
|
||||
|
||||
explicit QisBlitter(FrameBufferSDL2& fb);
|
||||
explicit QisBlitter(FBBackendSDL2& fb);
|
||||
|
||||
static bool isSupported(FrameBufferSDL2 &fb);
|
||||
static bool isSupported(FBBackendSDL2& fb);
|
||||
|
||||
~QisBlitter() override;
|
||||
|
||||
|
@ -44,7 +44,7 @@ class QisBlitter : public Blitter {
|
|||
|
||||
private:
|
||||
|
||||
FrameBufferSDL2& myFB;
|
||||
FBBackendSDL2& myFB;
|
||||
|
||||
SDL_Texture* mySrcTexture{nullptr};
|
||||
SDL_Texture* mySecondarySrcTexture{nullptr};
|
||||
|
|
|
@ -250,7 +250,6 @@ Console::~Console()
|
|||
myOSystem.sound().close();
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Console::setConsoleTiming()
|
||||
{
|
||||
|
@ -728,7 +727,8 @@ void Console::changeVSizeAdjust(int direction)
|
|||
|
||||
ostringstream val;
|
||||
|
||||
val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ") << newAdjustVSize << "%";
|
||||
val << (newAdjustVSize ? newAdjustVSize > 0 ? "+" : "" : " ")
|
||||
<< newAdjustVSize << "%";
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
@ -755,8 +756,7 @@ void Console::setTIAProperties()
|
|||
static_cast<Int32>(BSPF::stringToInt(myProperties.get(PropType::Display_VCenter))), TIAConstants::minVcenter, TIAConstants::maxVcenter
|
||||
);
|
||||
|
||||
if(myDisplayFormat == "NTSC" || myDisplayFormat == "PAL60" ||
|
||||
myDisplayFormat == "SECAM60")
|
||||
if(gameRefreshRate() == 60)
|
||||
{
|
||||
// Assume we've got ~262 scanlines (NTSC-like format)
|
||||
myTIA->setLayout(FrameLayout::ntsc);
|
||||
|
@ -805,17 +805,22 @@ void Console::setControllers(const string& romMd5)
|
|||
|
||||
myLeftControl = std::move(myCMHandler->leftController());
|
||||
myRightControl = std::move(myCMHandler->rightController());
|
||||
myOSystem.eventHandler().defineKeyControllerMappings(Controller::Type::CompuMate, Controller::Jack::Left);
|
||||
myOSystem.eventHandler().defineJoyControllerMappings(Controller::Type::CompuMate, Controller::Jack::Left);
|
||||
myOSystem.eventHandler().defineKeyControllerMappings(
|
||||
Controller::Type::CompuMate, Controller::Jack::Left);
|
||||
myOSystem.eventHandler().defineJoyControllerMappings(
|
||||
Controller::Type::CompuMate, Controller::Jack::Left);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Setup the controllers based on properties
|
||||
Controller::Type leftType = Controller::getType(myProperties.get(PropType::Controller_Left));
|
||||
Controller::Type rightType = Controller::getType(myProperties.get(PropType::Controller_Right));
|
||||
Controller::Type leftType =
|
||||
Controller::getType(myProperties.get(PropType::Controller_Left));
|
||||
Controller::Type rightType =
|
||||
Controller::getType(myProperties.get(PropType::Controller_Right));
|
||||
size_t size = 0;
|
||||
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
|
||||
if(image != nullptr && size != 0)
|
||||
|
@ -827,7 +832,8 @@ void Console::setControllers(const string& romMd5)
|
|||
!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);
|
||||
|
||||
// Swap the ports if necessary
|
||||
|
@ -985,13 +991,21 @@ void Console::changeAutoFireRate(int direction)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float Console::getFramerate() const
|
||||
float Console::currentFrameRate() const
|
||||
{
|
||||
return
|
||||
(myConsoleTiming == ConsoleTiming::ntsc ? 262.F * 60.F : 312.F * 50.F) /
|
||||
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
|
||||
{
|
||||
|
|
|
@ -185,6 +185,11 @@ class Console : public Serializable, public ConsoleIO
|
|||
*/
|
||||
EmulationTiming& emulationTiming() { return myEmulationTiming; }
|
||||
|
||||
/**
|
||||
Retrieve the current game's refresh rate, or 0 if no game.
|
||||
*/
|
||||
int refreshRate() const;
|
||||
|
||||
public:
|
||||
/**
|
||||
Toggle between NTSC/PAL/SECAM (and variants) display format.
|
||||
|
@ -282,9 +287,16 @@ class Console : public Serializable, public ConsoleIO
|
|||
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.
|
||||
|
|
|
@ -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 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
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "Settings.hxx"
|
||||
#include "TIA.hxx"
|
||||
#include "Sound.hxx"
|
||||
#include "MediaFactory.hxx"
|
||||
|
||||
#include "FBSurface.hxx"
|
||||
#include "TIASurface.hxx"
|
||||
|
@ -63,14 +64,24 @@ FrameBuffer::FrameBuffer(OSystem& osystem)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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
|
||||
vector<Common::Size> windowedDisplays;
|
||||
queryHardware(myFullscreenDisplays, windowedDisplays, myRenderers);
|
||||
myBackend->queryHardware(myFullscreenDisplays, windowedDisplays, myRenderers);
|
||||
uInt32 query_w = windowedDisplays[0].w, query_h = windowedDisplays[0].h;
|
||||
|
||||
// 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
|
||||
myTIASurface = make_unique<TIASurface>(myOSystem);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
|
@ -210,7 +219,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
|||
Common::Size size, bool honourHiDPI)
|
||||
{
|
||||
++myInitializedCount;
|
||||
myScreenTitle = title;
|
||||
myBackend->setTitle(title);
|
||||
|
||||
// In HiDPI mode, all created displays must be scaled appropriately
|
||||
if(honourHiDPI && hidpiEnabled())
|
||||
|
@ -254,7 +263,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title, BufferType type,
|
|||
myBufferType = type;
|
||||
|
||||
// Initialize video subsystem
|
||||
string pre_about = about();
|
||||
string pre_about = myBackend->about();
|
||||
FBInitStatus status = applyVideoMode();
|
||||
if(status != FBInitStatus::Success)
|
||||
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
|
||||
if(myInitializedCount == 1)
|
||||
{
|
||||
Logger::info(about());
|
||||
Logger::info(myBackend->about());
|
||||
}
|
||||
else
|
||||
{
|
||||
string post_about = about();
|
||||
string post_about = myBackend->about();
|
||||
if(post_about != pre_about)
|
||||
Logger::info(post_about);
|
||||
}
|
||||
|
@ -467,7 +476,7 @@ void FrameBuffer::update(bool force)
|
|||
|
||||
// Push buffers to screen only when necessary
|
||||
if(force)
|
||||
renderToScreen();
|
||||
myBackend->renderToScreen();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -493,7 +502,7 @@ void FrameBuffer::updateInEmulationMode(float framesPerSecond)
|
|||
drawMessage();
|
||||
|
||||
// Push buffers to screen
|
||||
renderToScreen();
|
||||
myBackend->renderToScreen();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -600,7 +609,8 @@ void FrameBuffer::drawFrameStats(float framesPerSecond)
|
|||
ss
|
||||
<< myOSystem.console().tia().frameBufferScanlinesLastFrame()
|
||||
<< " / "
|
||||
<< std::fixed << std::setprecision(1) << myOSystem.console().getFramerate()
|
||||
<< std::fixed << std::setprecision(1)
|
||||
<< myOSystem.console().currentFrameRate()
|
||||
<< "Hz => "
|
||||
<< info.DisplayFormat;
|
||||
|
||||
|
@ -803,11 +813,11 @@ void FrameBuffer::setPauseDelay()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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
|
||||
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)
|
||||
return mySurfaceList.at(mySurfaceList.size() - 1);
|
||||
|
@ -945,9 +955,11 @@ string FrameBuffer::getPositionKey()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBuffer::saveCurrentWindowPosition()
|
||||
{
|
||||
myOSystem.settings().setValue(getDisplayKey(), getCurrentDisplayIndex());
|
||||
if(isCurrentWindowPositioned())
|
||||
myOSystem.settings().setValue(getPositionKey(), getCurrentWindowPos());
|
||||
myOSystem.settings().setValue(
|
||||
getDisplayKey(), myBackend->getCurrentDisplayIndex());
|
||||
if(myBackend->isCurrentWindowPositioned())
|
||||
myOSystem.settings().setValue(
|
||||
getPositionKey(), myBackend->getCurrentWindowPos());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -997,7 +1009,7 @@ void FrameBuffer::toggleFullscreen(bool toggle)
|
|||
ostringstream msg;
|
||||
msg << "Fullscreen ";
|
||||
if(isFullscreen)
|
||||
msg << "enabled (" << refreshRate() << " Hz, ";
|
||||
msg << "enabled (" << myBackend->refreshRate() << " Hz, ";
|
||||
else
|
||||
msg << "disabled (";
|
||||
msg << "Zoom " << myActiveVidMode.zoom * 100 << "%)";
|
||||
|
@ -1033,7 +1045,7 @@ void FrameBuffer::toggleAdaptRefresh(bool toggle)
|
|||
|
||||
msg << "Adapt refresh rate ";
|
||||
msg << (isAdaptRefresh ? "enabled" : "disabled");
|
||||
msg << " (" << refreshRate() << " Hz)";
|
||||
msg << " (" << myBackend->refreshRate() << " Hz)";
|
||||
|
||||
showMessage(msg.str());
|
||||
}
|
||||
|
@ -1112,7 +1124,7 @@ FBInitStatus FrameBuffer::applyVideoMode()
|
|||
const Settings& s = myOSystem.settings();
|
||||
if(s.getBool("fullscreen"))
|
||||
{
|
||||
Int32 fsIndex = std::max(getCurrentDisplayIndex(), 0);
|
||||
Int32 fsIndex = std::max(myBackend->getCurrentDisplayIndex(), 0);
|
||||
myVidModeHandler.setDisplaySize(myFullscreenDisplays[fsIndex], fsIndex);
|
||||
}
|
||||
else
|
||||
|
@ -1130,7 +1142,11 @@ FBInitStatus FrameBuffer::applyVideoMode()
|
|||
// So we mute the sound until the operation completes
|
||||
bool oldMuteState = myOSystem.sound().mute(true);
|
||||
FBInitStatus status = FBInitStatus::FailNotSupported;
|
||||
if(activateVideoMode(myScreenTitle, mode))
|
||||
|
||||
if(myBackend->setVideoMode(mode,
|
||||
myOSystem.settings().getInt(getDisplayKey()),
|
||||
myOSystem.settings().getPoint(getPositionKey()))
|
||||
)
|
||||
{
|
||||
myActiveVidMode = mode;
|
||||
status = FBInitStatus::Success;
|
||||
|
@ -1218,7 +1234,7 @@ void FrameBuffer::setCursorState()
|
|||
break;
|
||||
}
|
||||
|
||||
grabMouse(emulation && (analog || alwaysUseMouse) && myGrabMouse);
|
||||
myBackend->grabMouse(emulation && (analog || alwaysUseMouse) && myGrabMouse);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -33,6 +33,7 @@ class TIASurface;
|
|||
#include "Rect.hxx"
|
||||
#include "Variant.hxx"
|
||||
#include "TIAConstants.hxx"
|
||||
#include "FBBackend.hxx"
|
||||
#include "FrameBufferConstants.hxx"
|
||||
#include "EventHandlerConstants.hxx"
|
||||
#include "VideoModeHandler.hxx"
|
||||
|
@ -55,16 +56,14 @@ class FrameBuffer
|
|||
static constexpr float ZOOM_STEPS = 0.25;
|
||||
|
||||
public:
|
||||
/**
|
||||
Creates a new Frame Buffer
|
||||
*/
|
||||
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
|
||||
|
@ -141,17 +140,17 @@ class FrameBuffer
|
|||
Allocate a new surface. The FrameBuffer class takes all responsibility
|
||||
for freeing this surface (ie, other classes must not delete it directly).
|
||||
|
||||
@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
|
||||
@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
|
||||
|
||||
@return A pointer to a valid surface object, or nullptr.
|
||||
@return A pointer to a valid surface object, or nullptr
|
||||
*/
|
||||
shared_ptr<FBSurface> allocateSurface(
|
||||
int w,
|
||||
int h,
|
||||
ScalingInterpolation interpolation = ScalingInterpolation::none,
|
||||
ScalingInterpolation inter = ScalingInterpolation::none,
|
||||
const uInt32* data = nullptr
|
||||
);
|
||||
|
||||
|
@ -304,27 +303,15 @@ class FrameBuffer
|
|||
FontDesc getFontDesc(const string& name) const;
|
||||
#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.
|
||||
*/
|
||||
virtual void showCursor(bool show) = 0;
|
||||
void showCursor(bool show) { myBackend->showCursor(show); }
|
||||
|
||||
/**
|
||||
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.
|
||||
|
@ -334,7 +321,9 @@ class FrameBuffer
|
|||
@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;
|
||||
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.
|
||||
|
@ -343,7 +332,9 @@ class FrameBuffer
|
|||
@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;
|
||||
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
|
||||
|
@ -355,88 +346,22 @@ class FrameBuffer
|
|||
@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;
|
||||
void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const {
|
||||
myBackend->readPixels(buffer, pitch, rect);
|
||||
}
|
||||
|
||||
/**
|
||||
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; }
|
||||
|
||||
/**
|
||||
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;
|
||||
int scaleX(int x) const { return myBackend->scaleX(x); }
|
||||
int scaleY(int y) const { return myBackend->scaleY(y); }
|
||||
|
||||
private:
|
||||
/**
|
||||
Calls 'free()' on all surfaces that the framebuffer knows about.
|
||||
*/
|
||||
|
@ -447,42 +372,6 @@ class FrameBuffer
|
|||
*/
|
||||
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.
|
||||
|
||||
|
@ -523,22 +412,13 @@ class FrameBuffer
|
|||
void setupFonts();
|
||||
#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:
|
||||
// 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
|
||||
uInt32 myInitializedCount{0};
|
||||
|
||||
|
@ -553,6 +433,11 @@ class FrameBuffer
|
|||
// Maximum absolute dimensions of the desktop area
|
||||
Common::Size myAbsDesktopSize;
|
||||
|
||||
// The resolution of the attached displays in fullscreen mode
|
||||
// The primary display is typically the first in the array
|
||||
// Windowed modes use myDesktopSize directly
|
||||
vector<Common::Size> myFullscreenDisplays;
|
||||
|
||||
// Supported renderers
|
||||
VariantList myRenderers;
|
||||
|
||||
|
@ -561,6 +446,9 @@ class FrameBuffer
|
|||
VideoModeHandler myVidModeHandler;
|
||||
VideoModeHandler::Mode myActiveVidMode;
|
||||
|
||||
// Type of the frame buffer
|
||||
BufferType myBufferType{BufferType::None};
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
// The font object to use for the normal in-game GUI
|
||||
unique_ptr<GUI::Font> myFont;
|
||||
|
@ -609,6 +497,11 @@ class FrameBuffer
|
|||
// Holds a reference to all the surfaces that have been created
|
||||
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;
|
||||
// Holds UI palette data (for each variation)
|
||||
static UIPaletteArray ourStandardUIPalette, ourClassicUIPalette,
|
||||
|
|
|
@ -143,10 +143,15 @@ bool OSystem::create()
|
|||
// Get relevant information about the video hardware
|
||||
// This must be done before any graphics context is created, since
|
||||
// it may be needed to initialize the size of graphical objects
|
||||
try { myFrameBuffer = MediaFactory::createVideo(*this); }
|
||||
catch(...) { return false; }
|
||||
if(!myFrameBuffer->initialize())
|
||||
try
|
||||
{
|
||||
myFrameBuffer = make_unique<FrameBuffer>(*this);
|
||||
myFrameBuffer->initialize();
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the event handler for the system
|
||||
myEventHandler = MediaFactory::createEventHandler(*this);
|
||||
|
@ -722,7 +727,7 @@ string OSystem::getROMInfo(const Console& console)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIASurface::setNTSC(NTSCFilter::Preset preset, bool show)
|
||||
{
|
||||
|
@ -512,13 +511,16 @@ void TIASurface::renderForSnapshot()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void TIASurface::updateSurfaceSettings()
|
||||
{
|
||||
myTiaSurface->setScalingInterpolation(interpolationModeFromSettings(myOSystem.settings()));
|
||||
myTiaSurface->setScalingInterpolation(
|
||||
interpolationModeFromSettings(myOSystem.settings())
|
||||
);
|
||||
mySLineSurface->setScalingInterpolation(
|
||||
interpolationModeFromSettings(myOSystem.settings())
|
||||
);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool TIASurface::correctAspect() const {
|
||||
bool TIASurface::correctAspect() const
|
||||
{
|
||||
return myOSystem.settings().getBool("tia.correct_aspect");
|
||||
}
|
||||
|
|
|
@ -67,7 +67,8 @@ class TIASurface
|
|||
@param rgb_palette The RGB components of the palette, needed for
|
||||
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
|
||||
|
@ -77,6 +78,11 @@ class TIASurface
|
|||
*/
|
||||
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
|
||||
TIA output widget.
|
||||
|
|
|
@ -16,25 +16,13 @@
|
|||
//============================================================================
|
||||
|
||||
#include "bspf.hxx"
|
||||
|
||||
#include "OSystem.hxx"
|
||||
#include "AtariNTSC.hxx"
|
||||
#include "TIAConstants.hxx"
|
||||
|
||||
#include "FBSurfaceLIBRETRO.hxx"
|
||||
#include "FrameBufferLIBRETRO.hxx"
|
||||
#include "FBBackendLIBRETRO.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBufferLIBRETRO::FrameBufferLIBRETRO(OSystem& osystem)
|
||||
: FrameBuffer(osystem),
|
||||
myRenderSurface(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferLIBRETRO::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
void FBBackendLIBRETRO::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
{
|
||||
fullscreenRes.emplace_back(1920, 1080);
|
||||
windowedRes.emplace_back(1920, 1080);
|
||||
|
@ -43,18 +31,8 @@ void FrameBufferLIBRETRO::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
unique_ptr<FBSurface>
|
||||
FrameBufferLIBRETRO::createSurface(uInt32 w, uInt32 h, ScalingInterpolation, const uInt32* data) const
|
||||
unique_ptr<FBSurface> FBBackendLIBRETRO::createSurface(
|
||||
uInt32 w, uInt32 h, ScalingInterpolation, const uInt32*) const
|
||||
{
|
||||
unique_ptr<FBSurface> ptr = make_unique<FBSurfaceLIBRETRO>
|
||||
(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;
|
||||
return make_unique<FBSurfaceLIBRETRO>(w, h);
|
||||
}
|
|
@ -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"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBSurfaceLIBRETRO::FBSurfaceLIBRETRO(FrameBufferLIBRETRO&,
|
||||
uInt32 width, uInt32 height, const uInt32* data)
|
||||
{
|
||||
createSurface(width, height, data);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceLIBRETRO::createSurface(uInt32 width, uInt32 height,
|
||||
const uInt32* data)
|
||||
FBSurfaceLIBRETRO::FBSurfaceLIBRETRO(uInt32 width, uInt32 height)
|
||||
{
|
||||
myWidth = width;
|
||||
myHeight = height;
|
||||
|
@ -39,9 +31,3 @@ void FBSurfaceLIBRETRO::createSurface(uInt32 width, uInt32 height,
|
|||
myPitch = width;
|
||||
////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBSurfaceLIBRETRO::render()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -20,23 +20,22 @@
|
|||
|
||||
#include "bspf.hxx"
|
||||
#include "FBSurface.hxx"
|
||||
#include "FrameBufferLIBRETRO.hxx"
|
||||
|
||||
/**
|
||||
An FBSurface suitable for the LIBRETRO Render2D API, making use of hardware
|
||||
acceleration behind the scenes.
|
||||
An FBSurface suitable for the LIBRETRO Render2D API. As with FBBackend,
|
||||
most of the functionality here is handled by libretro directly.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class FBSurfaceLIBRETRO : public FBSurface
|
||||
{
|
||||
public:
|
||||
FBSurfaceLIBRETRO(FrameBufferLIBRETRO& buffer, uInt32 width, uInt32 height,
|
||||
const uInt32* data);
|
||||
FBSurfaceLIBRETRO(uInt32 width, uInt32 height);
|
||||
~FBSurfaceLIBRETRO() override { }
|
||||
|
||||
// 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 height() const override { return myHeight; }
|
||||
|
@ -50,7 +49,7 @@ class FBSurfaceLIBRETRO : public FBSurface
|
|||
void setVisible(bool visible) override { }
|
||||
|
||||
void translateCoords(Int32& x, Int32& y) const override { }
|
||||
bool render() override;
|
||||
bool render() override { return true; }
|
||||
void invalidate() override { }
|
||||
void free() override { }
|
||||
void reload() override { }
|
||||
|
@ -61,22 +60,17 @@ class FBSurfaceLIBRETRO : public FBSurface
|
|||
void applyAttributes() override { }
|
||||
|
||||
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
|
||||
FBSurfaceLIBRETRO() = delete;
|
||||
FBSurfaceLIBRETRO(const FBSurfaceLIBRETRO&) = delete;
|
||||
FBSurfaceLIBRETRO(FBSurfaceLIBRETRO&&) = delete;
|
||||
FBSurfaceLIBRETRO& operator=(const FBSurfaceLIBRETRO&) = delete;
|
||||
FBSurfaceLIBRETRO& operator=(FBSurfaceLIBRETRO&&) = delete;
|
||||
|
||||
private:
|
||||
Common::Rect mySrcGUIR, myDstGUIR;
|
||||
|
||||
private:
|
||||
unique_ptr<uInt32[]> myPixelData;
|
||||
|
||||
uInt32 myWidth, myHeight;
|
||||
};
|
||||
|
||||
#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/EventHandlerLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/FSNodeLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/FBBackendLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/FBSurfaceLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/FrameBufferLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/OSystemLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/SoundLIBRETRO.cxx \
|
||||
$(CORE_DIR)/libretro/StellaLIBRETRO.cxx \
|
||||
|
|
|
@ -18,10 +18,10 @@
|
|||
#include "bspf.hxx"
|
||||
#include "StellaLIBRETRO.hxx"
|
||||
#include "SoundLIBRETRO.hxx"
|
||||
#include "FrameBufferLIBRETRO.hxx"
|
||||
#include "FBBackendLIBRETRO.hxx"
|
||||
#include "FBSurfaceLIBRETRO.hxx"
|
||||
|
||||
#include "AtariNTSC.hxx"
|
||||
#include "PaletteHandler.hxx"
|
||||
#include "AudioSettings.hxx"
|
||||
#include "Serializer.hxx"
|
||||
#include "StateManager.hxx"
|
||||
|
@ -33,27 +33,7 @@
|
|||
StellaLIBRETRO::StellaLIBRETRO()
|
||||
{
|
||||
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());
|
||||
|
||||
system_ready = false;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -302,9 +282,16 @@ float StellaLIBRETRO::getVideoAspect() 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 "M6532.hxx"
|
||||
#include "Paddles.hxx"
|
||||
#include "PaletteHandler.hxx"
|
||||
#include "System.hxx"
|
||||
#include "TIA.hxx"
|
||||
#include "TIASurface.hxx"
|
||||
|
@ -122,7 +123,7 @@ class StellaLIBRETRO
|
|||
void setAudioStereo(int mode);
|
||||
|
||||
void setInputEvent(Event::Type type, Int32 state) {
|
||||
myOSystem->eventHandler().handleEvent(type, state);
|
||||
myOSystem->eventHandler().handleEvent(type, state);
|
||||
}
|
||||
|
||||
Controller::Type getLeftControllerType() const {
|
||||
|
@ -153,39 +154,40 @@ class StellaLIBRETRO
|
|||
StellaLIBRETRO& operator=(StellaLIBRETRO&&) = delete;
|
||||
|
||||
unique_ptr<OSystemLIBRETRO> myOSystem;
|
||||
uInt32 system_ready;
|
||||
uInt32 system_ready{false};
|
||||
|
||||
ByteBuffer rom_image;
|
||||
uInt32 rom_size;
|
||||
uInt32 rom_size{0};
|
||||
string rom_path;
|
||||
|
||||
ConsoleTiming console_timing;
|
||||
string console_format;
|
||||
ConsoleTiming console_timing{ConsoleTiming::ntsc};
|
||||
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;
|
||||
uInt32 audio_samples;
|
||||
|
||||
// (31440 rate / 50 Hz) * 16-bit stereo * 1.25x padding
|
||||
const uInt32 audio_buffer_max = (31440 / 50 * 4 * 5) / 4;
|
||||
uInt32 audio_samples{0};
|
||||
|
||||
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:
|
||||
string video_palette;
|
||||
string video_phosphor;
|
||||
uInt32 video_phosphor_blend;
|
||||
string video_palette{PaletteHandler::SETTING_STANDARD};
|
||||
string video_phosphor{"byrom"};
|
||||
uInt32 video_phosphor_blend{60};
|
||||
|
||||
uInt32 video_aspect_ntsc;
|
||||
uInt32 video_aspect_pal;
|
||||
NTSCFilter::Preset video_filter;
|
||||
uInt32 video_aspect_ntsc{0};
|
||||
uInt32 video_aspect_pal{0};
|
||||
NTSCFilter::Preset video_filter{NTSCFilter::Preset::OFF};
|
||||
|
||||
string audio_mode;
|
||||
string audio_mode{"byrom"};
|
||||
|
||||
bool phosphor_default;
|
||||
bool phosphor_default{false};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -495,9 +495,9 @@
|
|||
<ClCompile Include="..\common\audio\SimpleResampler.cxx" />
|
||||
<ClCompile Include="..\common\Base.cxx" />
|
||||
<ClCompile Include="..\common\EventHandlerSDL2.cxx" />
|
||||
<ClCompile Include="..\common\FBBackendSDL2.cxx" />
|
||||
<ClCompile Include="..\common\FBSurfaceSDL2.cxx" />
|
||||
<ClCompile Include="..\common\FpsMeter.cxx" />
|
||||
<ClCompile Include="..\common\FrameBufferSDL2.cxx" />
|
||||
<ClCompile Include="..\common\FSNodeZIP.cxx" />
|
||||
<ClCompile Include="..\common\JoyMap.cxx" />
|
||||
<ClCompile Include="..\common\KeyMap.cxx" />
|
||||
|
@ -1508,9 +1508,9 @@
|
|||
<ClInclude Include="..\common\Base.hxx" />
|
||||
<ClInclude Include="..\common\bspf.hxx" />
|
||||
<ClInclude Include="..\common\EventHandlerSDL2.hxx" />
|
||||
<ClInclude Include="..\common\FBBackendSDL2.hxx" />
|
||||
<ClInclude Include="..\common\FBSurfaceSDL2.hxx" />
|
||||
<ClInclude Include="..\common\FpsMeter.hxx" />
|
||||
<ClInclude Include="..\common\FrameBufferSDL2.hxx" />
|
||||
<ClInclude Include="..\common\FSNodeFactory.hxx" />
|
||||
<ClInclude Include="..\common\FSNodeZIP.hxx" />
|
||||
<ClInclude Include="..\common\JoyMap.hxx" />
|
||||
|
@ -2060,4 +2060,4 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\common\FrameBufferSDL2.cxx">
|
||||
<ClCompile Include="..\common\FBBackendSDL2.cxx">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FSNodeWINDOWS.cxx">
|
||||
|
@ -1034,7 +1034,7 @@
|
|||
<ClInclude Include="..\common\bspf.hxx">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\common\FrameBufferSDL2.hxx">
|
||||
<ClInclude Include="..\common\FBBackendSDL2.hxx">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="HomeFinder.hxx">
|
||||
|
@ -2126,4 +2126,4 @@
|
|||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
Loading…
Reference in New Issue