diff --git a/src/common/FBSurfaceTIA.cxx b/src/common/FBSurfaceTIA.cxx index 204e46509..134d38c87 100644 --- a/src/common/FBSurfaceTIA.cxx +++ b/src/common/FBSurfaceTIA.cxx @@ -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) diff --git a/src/common/FBSurfaceTIA.hxx b/src/common/FBSurfaceTIA.hxx index 9a7337405..95c3ba1e6 100644 --- a/src/common/FBSurfaceTIA.hxx +++ b/src/common/FBSurfaceTIA.hxx @@ -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; diff --git a/src/common/FrameBufferGL.cxx b/src/common/FrameBufferGL.cxx index ed624b4fc..71bb46623 100644 --- a/src/common/FrameBufferGL.cxx +++ b/src/common/FrameBufferGL.cxx @@ -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) { diff --git a/src/common/FrameBufferGL.hxx b/src/common/FrameBufferGL.hxx index 0818e6c59..0bf639cf2 100644 --- a/src/common/FrameBufferGL.hxx +++ b/src/common/FrameBufferGL.hxx @@ -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. diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index ec4122f38..b0262fdbd 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -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")); diff --git a/src/emucore/Console.hxx b/src/emucore/Console.hxx index aad04929f..d611e31f8 100644 --- a/src/emucore/Console.hxx +++ b/src/emucore/Console.hxx @@ -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. */ diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index c622fcb8c..85f9e4288 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -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(); diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index c503b5df1..af670930b 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -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 diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 1c7ca0f80..7d847e90f 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -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 Specify the OpenGL library\n" - << " -gl_filter 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 Scale the TIA width by the given percentage in NTSC mode\n" << " -gl_aspectp 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 Use the specified filter in emulation mode\n" diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 9d4994cd9..8903e379c 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -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);