Added scanline interpolation option (blended scanlines) with the

'tv_scaninter' option.  Added Alt-8 keypress to toggle this; still
TODO is add a UI item for it.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2462 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2012-05-08 19:37:04 +00:00
parent 7d3ea13a01
commit f59f5ab5e8
10 changed files with 90 additions and 28 deletions

View File

@ -230,8 +230,8 @@ void FBSurfaceTIA::reload()
// Base texture (@ index 0)
myGL.BindTexture(GL_TEXTURE_2D, myTexID[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@ -247,10 +247,11 @@ void FBSurfaceTIA::reload()
// Scanline texture (@ index 1)
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
#ifdef HAVE_GL_BGRA
static uInt16 const scanline[4] = { 0x0000, 0x0000, 0x8000, 0x0000 };
myGL.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0,
@ -273,18 +274,34 @@ void FBSurfaceTIA::reload()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setFilter(const string& name)
void FBSurfaceTIA::setScanIntensity(uInt32 intensity)
{
// We only do GL_NEAREST or GL_LINEAR for now
GLint filter = name == "linear" ? GL_LINEAR : GL_NEAREST;
myScanlineIntensityI = (GLuint)intensity;
myScanlineIntensityF = (GLfloat)intensity / 100;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setTexInterpolation(bool enable)
{
myTexFilter[0] = enable ? GL_LINEAR : GL_NEAREST;
myGL.BindTexture(GL_TEXTURE_2D, myTexID[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[0]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::setScanInterpolation(bool enable)
{
myTexFilter[1] = enable ? GL_LINEAR : GL_NEAREST;
myGL.BindTexture(GL_TEXTURE_2D, myTexID[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, myTexFilter[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, myTexFilter[1]);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
myGL.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceTIA::updateCoords(uInt32 baseH,
uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH)

View File

@ -56,8 +56,10 @@ class FBSurfaceTIA : public FBSurface
private:
void setTIA(const TIA& tia) { myTIA = &tia; }
void setTIAPalette(const uInt32* palette);
void setFilter(const string& name);
void enableScanlines(bool enable) { myScanlinesEnabled = enable; }
void setScanIntensity(uInt32 intensity);
void setTexInterpolation(bool enable);
void setScanInterpolation(bool enable);
void updateCoords(uInt32 baseH, uInt32 imgX, uInt32 imgY, uInt32 imgW, uInt32 imgH);
void updateCoords();
@ -75,6 +77,7 @@ class FBSurfaceTIA : public FBSurface
GLuint myImageX, myImageY, myImageW, myImageH;
GLfloat myTexCoordW, myTexCoordH;
GLfloat myCoord[32];
GLint myTexFilter[2];
bool myScanlinesEnabled;
GLuint myScanlineIntensityI;

View File

@ -311,10 +311,7 @@ bool FrameBufferGL::setVidMode(VideoMode& mode)
p_gl.MatrixMode(GL_MODELVIEW);
p_gl.LoadIdentity();
#if 0
cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl
<< mode << endl;
#endif
//cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl << mode << endl;
// The framebuffer only takes responsibility for TIA surfaces
// Other surfaces (such as the ones used for dialogs) are allocated
@ -330,8 +327,10 @@ cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl
myTiaSurface->updateCoords(baseHeight, mode.image_x, mode.image_y,
mode.image_w, mode.image_h);
myTiaSurface->setFilter(myOSystem->settings().getString("gl_filter"));
myTiaSurface->enableScanlines(myFilterType == kBlarggNTSC);
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("gl_inter"));
myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv_scaninter"));
myTiaSurface->setTIA(myOSystem->console().tia());
}
@ -385,7 +384,12 @@ void FrameBufferGL::enableNTSC(bool enable)
{
myFilterType = enable ? kBlarggNTSC : myUsePhosphor ? kPhosphor : kNone;
myTiaSurface->updateCoords();
myTiaSurface->enableScanlines(myFilterType == kBlarggNTSC);
myTiaSurface->setScanIntensity(myOSystem->settings().getInt("tv_scanlines"));
myTiaSurface->setTexInterpolation(myOSystem->settings().getBool("gl_inter"));
myTiaSurface->setScanInterpolation(myOSystem->settings().getBool("tv_scaninter"));
myRedrawEntireFrame = true;
}
}
@ -401,14 +405,22 @@ uInt32 FrameBufferGL::changeScanlines(int relative, int absolute)
intensity = BSPF_max(0, intensity);
intensity = BSPF_min(100, intensity);
myTiaSurface->myScanlineIntensityI = (GLuint)intensity;
myTiaSurface->myScanlineIntensityF = (GLfloat)intensity / 100;
myTiaSurface->setScanIntensity(intensity);
myRedrawEntireFrame = true;
}
return intensity;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::enableScanlineInterpolation(bool enable)
{
if(myTiaSurface)
{
myTiaSurface->setScanInterpolation(enable);
myRedrawEntireFrame = true;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::setTIAPalette(const uInt32* palette)
{

View File

@ -94,7 +94,7 @@ class FrameBufferGL : public FrameBuffer
bool ntscEnabled() const { return myFilterType == kBlarggNTSC; }
/**
Change scanline intensity.
Change scanline intensity and interpolation.
relative = -1 means decrease current intensity by 'directin
direction = 0 means to reload the current video mode
direction = +1 means go to the next higher video mode
@ -105,6 +105,7 @@ class FrameBufferGL : public FrameBuffer
@return New current intensity
*/
uInt32 changeScanlines(int relative, int absolute = 50);
void enableScanlineInterpolation(bool enable);
/**
Set up the TIA/emulation palette for a screen of any depth > 8.

View File

@ -490,6 +490,28 @@ void Console::changeScanlines(int amount, bool show)
if(show) myOSystem->frameBuffer().showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::toggleScanlineInterpolation()
{
ostringstream buf;
if(myOSystem->frameBuffer().type() == kDoubleBuffer)
{
if(myOSystem->frameBuffer().ntscEnabled())
{
bool enable = !myOSystem->settings().getBool("tv_scaninter");
myOSystem->frameBuffer().enableScanlineInterpolation(enable);
buf << "Scanline interpolation " << (enable ? "enabled" : "disabled");
myOSystem->settings().setBool("tv_scaninter", enable);
}
else
buf << "Scanlines only available in TV filtering mode";
}
else
buf << "Scanlines not available in software mode";
myOSystem->frameBuffer().showMessage(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Console::setProperties(const Properties& props)
{
@ -517,7 +539,6 @@ FBInitStatus Console::initializeVideo(bool full)
bool enable = myProperties.get(Display_Phosphor) == "YES";
int blend = atoi(myProperties.get(Display_PPBlend).c_str());
myOSystem->frameBuffer().enablePhosphor(enable, blend);
myOSystem->frameBuffer().changeScanlines(0, myOSystem->settings().getInt("tv_scanlines"));
toggleNTSC((NTSCFilter::Preset)myOSystem->settings().getInt("tv_filter"));
setPalette(myOSystem->settings().getString("palette"));

View File

@ -212,6 +212,11 @@ class Console : public Serializable
*/
void changeScanlines(int amount, bool show = false);
/**
Toggles interpolation/smoothing of scanlines in TV modes.
*/
void toggleScanlineInterpolation();
/**
Toggles the PAL color-loss effect.
*/

View File

@ -409,6 +409,10 @@ void EventHandler::poll(uInt64 time)
myOSystem->console().changeScanlines(+5, true);
break;
case KBDK_8: // Alt-8 turns toggles scanline interpolation
myOSystem->console().toggleScanlineInterpolation();
break;
case KBDK_z:
if(mod & KMOD_SHIFT)
myOSystem->console().toggleP0Collision();

View File

@ -303,7 +303,7 @@ class FrameBuffer
virtual bool ntscEnabled() const { return false; }
/**
Change scanline intensity.
Change scanline intensity and interpolation.
relative = -1 means decrease current intensity by 'directin
direction = 0 means to reload the current video mode
direction = +1 means go to the next higher video mode
@ -314,6 +314,7 @@ class FrameBuffer
@return New current intensity
*/
virtual uInt32 changeScanlines(int relative, int absolute = 50) { return absolute; }
virtual void enableScanlineInterpolation(bool enable) { }
//////////////////////////////////////////////////////////////////////
// The following methods are system-specific and *must* be implemented

View File

@ -40,7 +40,7 @@ Settings::Settings(OSystem* osystem)
setInternal("video", "soft");
// OpenGL specific options
setInternal("gl_filter", "nearest");
setInternal("gl_inter", "false");
setInternal("gl_aspectn", "90");
setInternal("gl_aspectp", "100");
setInternal("gl_fsscale", "false");
@ -62,6 +62,7 @@ Settings::Settings(OSystem* osystem)
// TV filtering options
setInternal("tv_filter", "0");
setInternal("tv_scanlines", "50");
setInternal("tv_scaninter", "true");
// Sound options
setInternal("sound", "true");
@ -259,9 +260,6 @@ void Settings::validate()
if(s != "sleep" && s != "busy") setInternal("timing", "sleep");
#ifdef DISPLAY_OPENGL
s = getString("gl_filter");
if(s != "linear" && s != "nearest") setInternal("gl_filter", "nearest");
i = getInt("gl_aspectn");
if(i < 80 || i > 120) setInternal("gl_aspectn", "100");
i = getInt("gl_aspectp");
@ -335,9 +333,7 @@ void Settings::usage()
<< " gl SDL OpenGL mode\n"
<< endl
<< " -gl_lib <name> Specify the OpenGL library\n"
<< " -gl_filter <type> Type is one of the following:\n"
<< " nearest Normal scaling (GL_NEAREST)\n"
<< " linear Blurred scaling (GL_LINEAR)\n"
<< " -gl_inter <1|0> Enable interpolated (smooth) scaling\n"
<< " -gl_aspectn <number> Scale the TIA width by the given percentage in NTSC mode\n"
<< " -gl_aspectp <number> Scale the TIA width by the given percentage in PAL mode\n"
<< " -gl_fsscale <1|0> Stretch GL image in fullscreen emulation mode to max/integer scale\n"
@ -346,6 +342,7 @@ void Settings::usage()
<< endl
<< " -tv_filter <0-5> Set TV effects off (0) or to specified mode (1-5)\n"
<< " -tv_scanlines <0-100> Set scanline intensity to percentage (0 disables completely)\n"
<< " -tv_scaninter <1|0> Enable interpolated (smooth) scanlines\n"
<< endl
#endif
<< " -tia_filter <filter> Use the specified filter in emulation mode\n"

View File

@ -317,6 +317,7 @@ void VideoDialog::loadConfig()
instance().settings().getString("timing"), "sleep");
// GL Filter setting
// FIXME
myGLFilterPopup->setSelected(
instance().settings().getString("gl_filter"), "nearest");
myGLFilterPopup->setEnabled(gl);