The framebuffer now recognizes double-buffering based on whether the render backend is accelerated, and the refresh method uses this to refresh buffers. This fixes the flashing that appears in OpenGL in Windows and OSX. Interestingly, Direct3D in Windows and OpenGL in Linux didn't exhibit this issue.

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2871 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-03-08 22:57:16 +00:00
parent c878fd926d
commit 0b3bf4b659
5 changed files with 25 additions and 30 deletions

View File

@ -42,7 +42,8 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem)
myRenderer(NULL), myRenderer(NULL),
myWindowFlags(0), myWindowFlags(0),
myTiaSurface(NULL), myTiaSurface(NULL),
myDirtyFlag(true) myDirtyFlag(true),
myDblBufferedFlag(true)
{ {
// Initialize SDL2 context // Initialize SDL2 context
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
@ -211,7 +212,12 @@ bool FrameBufferSDL2::setVideoMode(const string& title, VideoMode& mode, bool fu
} }
SDL_RendererInfo renderinfo; SDL_RendererInfo renderinfo;
if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0) if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0)
{
myOSystem->settings().setValue("video", renderinfo.name); myOSystem->settings().setValue("video", renderinfo.name);
// For now, accelerated renderers imply double buffering
// Eventually, SDL may be updated to query this from the render backend
myDblBufferedFlag = renderinfo.flags & SDL_RENDERER_ACCELERATED;
}
// The framebuffer only takes responsibility for TIA surfaces // The framebuffer only takes responsibility for TIA surfaces
// Other surfaces (such as the ones used for dialogs) are allocated // Other surfaces (such as the ones used for dialogs) are allocated

View File

@ -113,9 +113,9 @@ class FrameBufferSDL2 : public FrameBuffer
{ return SDL_MapRGB(myPixelFormat, r, g, b); } { return SDL_MapRGB(myPixelFormat, r, g, b); }
/** /**
This method is called to query the type of the FrameBuffer. This method is called to query the buffering type of the FrameBuffer.
*/ */
BufferType type() const { return kDoubleBuffer; } bool isDoubleBuffered() const { return myDblBufferedFlag; }
/** /**
This method is called to query the TV effects in use by the FrameBuffer. This method is called to query the TV effects in use by the FrameBuffer.
@ -238,6 +238,9 @@ class FrameBufferSDL2 : public FrameBuffer
// Indicates that the texture has been modified, and should be redrawn // Indicates that the texture has been modified, and should be redrawn
bool myDirtyFlag; bool myDirtyFlag;
// Indicates whether the backend is using double buffering
bool myDblBufferedFlag;
}; };
#endif #endif

View File

@ -317,7 +317,7 @@ void FrameBuffer::update()
{ {
// When onscreen messages are enabled in double-buffer mode, // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required // a full redraw is required
myOSystem->menu().draw(myMsg.enabled && type() == kDoubleBuffer); myOSystem->menu().draw(myMsg.enabled && isDoubleBuffered());
break; // S_MENU break; // S_MENU
} }
@ -325,7 +325,7 @@ void FrameBuffer::update()
{ {
// When onscreen messages are enabled in double-buffer mode, // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required // a full redraw is required
myOSystem->commandMenu().draw(myMsg.enabled && type() == kDoubleBuffer); myOSystem->commandMenu().draw(myMsg.enabled && isDoubleBuffered());
break; // S_CMDMENU break; // S_CMDMENU
} }
@ -333,7 +333,7 @@ void FrameBuffer::update()
{ {
// When onscreen messages are enabled in double-buffer mode, // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required // a full redraw is required
myOSystem->launcher().draw(myMsg.enabled && type() == kDoubleBuffer); myOSystem->launcher().draw(myMsg.enabled && isDoubleBuffered());
break; // S_LAUNCHER break; // S_LAUNCHER
} }
@ -342,7 +342,7 @@ void FrameBuffer::update()
{ {
// When onscreen messages are enabled in double-buffer mode, // When onscreen messages are enabled in double-buffer mode,
// a full redraw is required // a full redraw is required
myOSystem->debugger().draw(myMsg.enabled && type() == kDoubleBuffer); myOSystem->debugger().draw(myMsg.enabled && isDoubleBuffered());
break; // S_DEBUGGER break; // S_DEBUGGER
} }
#endif #endif
@ -510,14 +510,13 @@ void FrameBuffer::refresh()
// This method is in essence a FULL refresh, putting all rendering // This method is in essence a FULL refresh, putting all rendering
// buffers in a known, fully redrawn state // buffers in a known, fully redrawn state
bool doubleBuffered = (type() == kDoubleBuffer);
switch(myOSystem->eventHandler().state()) switch(myOSystem->eventHandler().state())
{ {
case EventHandler::S_EMULATE: case EventHandler::S_EMULATE:
case EventHandler::S_PAUSE: case EventHandler::S_PAUSE:
invalidate(); invalidate();
drawTIA(true); drawTIA(true);
if(doubleBuffered) if(isDoubleBuffered())
{ {
postFrameUpdate(); postFrameUpdate();
invalidate(); invalidate();
@ -529,7 +528,7 @@ void FrameBuffer::refresh()
invalidate(); invalidate();
drawTIA(true); drawTIA(true);
myOSystem->menu().draw(true); myOSystem->menu().draw(true);
if(doubleBuffered) if(isDoubleBuffered())
{ {
postFrameUpdate(); postFrameUpdate();
invalidate(); invalidate();
@ -542,7 +541,7 @@ void FrameBuffer::refresh()
invalidate(); invalidate();
drawTIA(true); drawTIA(true);
myOSystem->commandMenu().draw(true); myOSystem->commandMenu().draw(true);
if(doubleBuffered) if(isDoubleBuffered())
{ {
postFrameUpdate(); postFrameUpdate();
invalidate(); invalidate();
@ -554,7 +553,7 @@ void FrameBuffer::refresh()
case EventHandler::S_LAUNCHER: case EventHandler::S_LAUNCHER:
invalidate(); invalidate();
myOSystem->launcher().draw(true); myOSystem->launcher().draw(true);
if(doubleBuffered) if(isDoubleBuffered())
{ {
postFrameUpdate(); postFrameUpdate();
invalidate(); invalidate();
@ -566,7 +565,7 @@ void FrameBuffer::refresh()
case EventHandler::S_DEBUGGER: case EventHandler::S_DEBUGGER:
invalidate(); invalidate();
myOSystem->debugger().draw(true); myOSystem->debugger().draw(true);
if(doubleBuffered) if(isDoubleBuffered())
{ {
postFrameUpdate(); postFrameUpdate();
invalidate(); invalidate();

View File

@ -39,12 +39,6 @@ namespace GUI {
#include "Variant.hxx" #include "Variant.hxx"
#include "bspf.hxx" #include "bspf.hxx"
// Different types of framebuffer derived objects
enum BufferType {
kSingleBuffer,
kDoubleBuffer
};
// Return values for initialization of framebuffer window // Return values for initialization of framebuffer window
enum FBInitStatus { enum FBInitStatus {
kSuccess, kSuccess,
@ -365,9 +359,9 @@ class FrameBuffer
virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b) const = 0; virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b) const = 0;
/** /**
This method is called to query the type of the FrameBuffer. This method is called to query the buffering type of the FrameBuffer.
*/ */
virtual BufferType type() const = 0; virtual bool isDoubleBuffered() const = 0;
/** /**
This method is called to get the specified scanline data from the This method is called to get the specified scanline data from the

View File

@ -37,10 +37,8 @@
Settings::Settings(OSystem* osystem) Settings::Settings(OSystem* osystem)
: myOSystem(osystem) : myOSystem(osystem)
{ {
// Add options that are common to all versions of Stella
setInternal("video", "soft");
// Video-related options // Video-related options
setInternal("video", "");
setInternal("vsync", "true"); setInternal("vsync", "true");
setInternal("fullscreen", "0"); setInternal("fullscreen", "0");
setInternal("fullres", "auto"); setInternal("fullres", "auto");
@ -275,21 +273,16 @@ void Settings::validate()
string s; string s;
int i; int i;
s = getString("video");
if(s != "soft" && s != "gl") setInternal("video", "soft");
s = getString("timing"); s = getString("timing");
if(s != "sleep" && s != "busy") setInternal("timing", "sleep"); if(s != "sleep" && s != "busy") setInternal("timing", "sleep");
//FIXSDL
i = getInt("tia.aspectn"); i = getInt("tia.aspectn");
if(i < 80 || i > 120) setInternal("tia.aspectn", "100"); if(i < 80 || i > 120) setInternal("tia.aspectn", "90");
i = getInt("tia.aspectp"); i = getInt("tia.aspectp");
if(i < 80 || i > 120) setInternal("tia.aspectp", "100"); if(i < 80 || i > 120) setInternal("tia.aspectp", "100");
i = getInt("tv.filter"); i = getInt("tv.filter");
if(i < 0 || i > 5) setInternal("tv.filter", "0"); if(i < 0 || i > 5) setInternal("tv.filter", "0");
//////////////////
#ifdef SOUND_SUPPORT #ifdef SOUND_SUPPORT
i = getInt("volume"); i = getInt("volume");