Commit facc0966 authored by Gerhard Stein's avatar Gerhard Stein

NY00123 integration of the Video Scalers

parent d4ef5612
......@@ -56,6 +56,7 @@ bool CSettings::saveDrvCfg()
Configuration.WriteString("Video", "OGLfilter", VidConf.m_opengl_filter == GL_NEAREST ? "nearest" : "linear" );
#endif
Configuration.WriteInt("Video", "filter", VidConf.m_ScaleXFilter);
Configuration.WriteString("Video", "scaletype", VidConf.m_normal_scale ? "normal" : "scale2x" );
Configuration.SetKeyword("Video", "specialfx", VidConf.m_special_fx);
Configuration.WriteInt("Video", "autoframeskip", g_pTimer->getFrameRate());
Configuration.SetKeyword("Video", "showfps", VidConf.showfps);
......@@ -115,6 +116,11 @@ bool CSettings::loadDrvCfg()
Configuration.ReadKeyword("Video", "vsync", &VidConf.vsync, true);
Configuration.ReadInteger("Video", "filter", &value, 1);
VidConf.m_ScaleXFilter = value;
std::string scaleType;
Configuration.ReadString("Video", "scaletype", scaleType, "normal");
VidConf.m_normal_scale = (scaleType == "normal");
Configuration.ReadKeyword("Video", "OpenGL", &VidConf.m_opengl, false);
#if defined(USE_OPENGL)
......@@ -173,6 +179,7 @@ void CSettings::loadDefaultGraphicsCfg() //Loads default graphics
g_pVideoDriver->setZoom(1);
g_pTimer->setFPS(60);
g_pVideoDriver->setFilter(1);
g_pVideoDriver->setScaleType(true);
}
......
......@@ -75,10 +75,11 @@ CBaseMenu(CRect<float>(0.15f, 0.24f, 0.65f, 0.55f) )
mpMenuDialog->addControl( mpCameraButton );
mpScalerSelection = new CGUIComboSelection( "Scaler",
filledStrList( 4, "none", "2x", "3x", "4x" ) );
filledStrList( 7, "none", "normal2x", "normal3x", "normal4x", "scale2x", "scale3x", "scale4x" ) );
mpMenuDialog->addControl( mpScalerSelection );
mpVSyncSwitch = new CGUISwitch( "VSync" );
mpMenuDialog->addControl( mpVSyncSwitch );
......@@ -115,7 +116,7 @@ void CVideoSettings::init()
#if !defined(EMBEDDED)
mpScalerSelection->setSelection( mUserVidConf.m_ScaleXFilter==1 ? "none" : itoa(mUserVidConf.m_ScaleXFilter) + "x" );
mpScalerSelection->setSelection( mUserVidConf.m_ScaleXFilter==1 ? "none" : (mUserVidConf.m_normal_scale ? "normal" : "scale") + itoa(mUserVidConf.m_ScaleXFilter) + "x" );
mpVSyncSwitch->enable( mUserVidConf.vsync );
mpFullScreenSwitch->setText( mUserVidConf.Fullscreen ? "Go Windowed" : "Go Fullscreen" );
......@@ -149,7 +150,13 @@ void CVideoSettings::release()
sscanf( res.c_str(), "%hux%hux", &mUserVidConf.m_DisplayRect.w, &mUserVidConf.m_DisplayRect.h );
if( scalerStr != "none" )
mUserVidConf.m_ScaleXFilter = scalerStr.at(0)-'0';
{
mUserVidConf.m_normal_scale = (scalerStr.at(0) == 'n');
if (mUserVidConf.m_normal_scale)
mUserVidConf.m_ScaleXFilter = scalerStr.at(6)-'0';
else
mUserVidConf.m_ScaleXFilter = scalerStr.at(5)-'0';
}
else
mUserVidConf.m_ScaleXFilter = 1;
#endif
......
......@@ -43,6 +43,7 @@ void CVidConfig::reset()
Fullscreen=false;
#endif
m_ScaleXFilter=1;
m_normal_scale=true;
Zoom=1;
#ifdef USE_OPENGL
......@@ -61,8 +62,6 @@ void CVidConfig::reset()
#if defined(TARGET_OS_IPHONE) || defined(TARGET_IPHONE_SIMULATOR)
m_opengl = true;
Zoom = 1;
m_ScaleXFilter = 1;
m_aspect_correction = false;
#endif
}
......
......@@ -52,6 +52,7 @@ public:
bool Fullscreen;
short m_ScaleXFilter;
bool m_normal_scale;
unsigned short Zoom;
bool m_opengl;
bool m_aspect_correction;
......
......@@ -247,6 +247,9 @@ void CVideoDriver::setZoom(short value) {
m_VidConfig.Zoom = value;
}
void CVideoDriver::setScaleType(bool IsNormal)
{ m_VidConfig.m_normal_scale = IsNormal; }
// defines the scroll-buffer that is used for blitScrollSurface(). It's normally passed by a CMap Object
// it might have when a level-map is loaded.
void CVideoDriver::updateScrollBuffer(SmartPointer<CMap> &map) {
......
......@@ -95,6 +95,7 @@ public:
void setMode(const CRect<Uint16>& res);
void setSpecialFXMode(bool SpecialFX);
void setFilter(short value);
void setScaleType(bool IsNormal);
void setZoom(short vale);
#ifdef USE_OPENGL
void enableOpenGL(bool value) { m_VidConfig.m_opengl = value; }
......
......@@ -130,6 +130,7 @@ bool COpenGL::createSurfaces()
g_pGfxEngine->Palette.setFXSurface( FXSurface );
Scaler.setFilterFactor(m_VidConfig.m_ScaleXFilter);
Scaler.setFilterType(m_VidConfig.m_normal_scale);
Scaler.setDynamicFactor( float(FilteredSurface->w)/float(screen->w),
float(FilteredSurface->h)/float(screen->h));
......
......@@ -40,6 +40,7 @@ bool CSDLVideo::createSurfaces()
{
// Configure the Scaler
Scaler.setFilterFactor(m_VidConfig.m_ScaleXFilter);
Scaler.setFilterType(m_VidConfig.m_normal_scale);
// This function creates the surfaces which are needed for the game.
const CRect<Uint16> &gamerect = m_VidConfig.m_GameRect;
......@@ -78,6 +79,7 @@ bool CSDLVideo::createSurfaces()
g_pGfxEngine->Palette.setFXSurface( FXSurface );
Scaler.setFilterFactor(m_VidConfig.m_ScaleXFilter);
Scaler.setFilterType(m_VidConfig.m_normal_scale);
Scaler.setDynamicFactor( float(FilteredSurface->w)/float(screen->w),
float(FilteredSurface->h)/float(screen->h));
......
......@@ -23,6 +23,11 @@ void CScaler::setFilterFactor( const Uint32 FilterFactor )
this->FilterFactor = FilterFactor;
}
void CScaler::setFilterType( bool IsNormal )
{
this->IsFilterNormal = IsNormal;
}
/**
* Scale functions
......@@ -79,6 +84,167 @@ void CScaler::scaleDynamic( SDL_Surface *srcSfc,
}
// Software implementation of linear interpolation - too slow for us.
/*
void CScaler::scaleDynamicLinear( SDL_Surface *srcSfc,
SDL_Surface *dstSfc )
{
const bool equalWidth = (dstSfc->w == srcSfc->w);
const bool equalHeight = (dstSfc->h == srcSfc->h);
if(equalWidth && equalHeight)
{
SDL_BlitSurface(srcSfc, NULL, dstSfc, NULL);
return;
}
const float dstWidth = float(dstSfc->w);
const float dstHeight = float(dstSfc->h);
Uint32 *dstPixel = static_cast<Uint32*>(dstSfc->pixels);
Uint32 *srcPixel = static_cast<Uint32*>(srcSfc->pixels);
Uint32 pitch;
Uint32 *topLeftPixel, *topRightPixel, *bottomLeftPixel, *bottomRightPixel;
// Pass those numbers to the stack
const float l_wFac = wFac;
const float l_hFac = hFac;
float xSrc, ySrc;
int channel;
ySrc = 0.0f;
for( Uint32 yDst = 0, xDst ; yDst<dstHeight ; yDst++ )
{
xSrc = 0.0f;
pitch = Uint32(ySrc)*srcSfc->w;
if(equalWidth)
{
memcpy(dstPixel, srcPixel+pitch, srcSfc->pitch);
}
else
{
for( xDst = 0; xDst<dstWidth ; xDst++ )
{
topLeftPixel = srcPixel+pitch+Uint32(xSrc);
if (xSrc >= 1.0f)
topLeftPixel -= 1;
if (pitch >= srcSfc->w)
topLeftPixel -= srcSfc->w;
topRightPixel = topLeftPixel+1;
bottomLeftPixel = topLeftPixel+srcSfc->w;
bottomRightPixel = bottomLeftPixel+1;
for (channel = 0; channel < 4; channel++)
((Uint8 *)(dstPixel))[channel] =
Uint8(
((Uint8 *)topLeftPixel)[channel]*(1-xSrc+Uint32(xSrc))*(1-ySrc+Uint32(ySrc))+
((Uint8 *)topRightPixel)[channel]*(xSrc-Uint32(xSrc))*(1-ySrc+Uint32(ySrc))+
((Uint8 *)bottomLeftPixel)[channel]*(1-xSrc+Uint32(xSrc))*(ySrc-Uint32(ySrc))+
((Uint8 *)bottomRightPixel)[channel]*(xSrc-Uint32(xSrc))*(ySrc-Uint32(ySrc))
);
xSrc += l_wFac;
dstPixel++;
}
}
ySrc += l_hFac;
}
}
*/
// Another implementation of linear interpolation - slow again.
/*
void CScaler::scaleDynamicLinear( SDL_Surface *srcSfc,
SDL_Surface *dstSfc )
{
if((dstSfc->w == srcSfc->w) && (dstSfc->h == srcSfc->h))
{
SDL_BlitSurface(srcSfc, NULL, dstSfc, NULL);
return;
}
const Uint32 srcWidth = Uint32(srcSfc->w);
const Uint32 srcHeight = Uint32(srcSfc->h);
const Uint32 dstWidth = Uint32(dstSfc->w);
const Uint32 dstHeight = Uint32(dstSfc->h);
const Uint32 dstArea = dstWidth*dstHeight;
Uint32 *dstPixel = static_cast<Uint32*>(dstSfc->pixels);
Uint32 *srcPixel = static_cast<Uint32*>(srcSfc->pixels);
int channel;
Uint32 leftEdge, topEdge;
for( Uint32 yDst = 0, xDst ; yDst<dstHeight ; yDst++ )
for( xDst = 0 ; xDst<dstWidth ; xDst++ )
{
leftEdge = xDst*srcWidth/dstWidth;
if (leftEdge > 0)
leftEdge--;
topEdge = yDst*srcHeight/dstHeight;
if (topEdge > 0)
topEdge--;
for( channel = 0 ; channel < 4 ; channel++ )
{
((Uint8 *)(dstPixel))[channel] =
(
((Uint8 *)(srcPixel + (topEdge+1)*srcWidth+leftEdge+1))[channel]
* (yDst*srcHeight%dstHeight) * (xDst*srcWidth%dstWidth) +
((Uint8 *)(srcPixel + topEdge*srcWidth+leftEdge+1))[channel]
* (dstHeight - yDst*srcHeight%dstHeight) * (xDst*srcWidth%dstWidth) +
((Uint8 *)(srcPixel + (topEdge+1)*srcWidth+leftEdge))[channel]
* (yDst*srcHeight%dstHeight) * (dstWidth - xDst*srcWidth%dstWidth) +
((Uint8 *)(srcPixel + topEdge*srcWidth+leftEdge))[channel]
* (dstHeight - yDst*srcHeight%dstHeight) * (dstWidth - xDst*srcWidth%dstWidth)
) / dstArea;
}
dstPixel++;
}
}
*/
void CScaler::scaleNormal( SDL_Surface *srcSfc,
SDL_Surface *dstSfc )
{
if((dstSfc->w == srcSfc->w) && (dstSfc->h == srcSfc->h))
{
SDL_BlitSurface(srcSfc, NULL, dstSfc, NULL);
return;
}
const Uint32 srcWidth = Uint32(srcSfc->w);
const Uint32 srcHeight = Uint32(srcSfc->h);
const Uint32 dstWidth = Uint32(dstSfc->w);
const Uint16 dstPitch = dstSfc->pitch;
Uint32 *dstPixel = static_cast<Uint32*>(dstSfc->pixels), *origDstPixel = dstPixel;
Uint32 *srcPixel = static_cast<Uint32*>(srcSfc->pixels);
Uint32 zoomIndex;
for( Uint32 ySrc = 0, xSrc ; ySrc<srcHeight ; ySrc++ )
{
// First we just stretch a row horizontally
for( xSrc = 0 ; xSrc<srcWidth ; xSrc++, srcPixel++ )
for( zoomIndex = 0; zoomIndex < FilterFactor; zoomIndex++, dstPixel++ )
*dstPixel = *srcPixel;
// Now we make copies of the stretched row
for( zoomIndex = 1; zoomIndex < FilterFactor; zoomIndex++, dstPixel+=dstWidth )
memcpy(dstPixel, origDstPixel, dstPitch);
origDstPixel += zoomIndex*dstWidth;
}
}
void CScaler::scaleUp( SDL_Surface *dstSfc,
......@@ -91,14 +257,17 @@ void CScaler::scaleUp( SDL_Surface *dstSfc,
SDL_LockSurface( srcSfc );
SDL_LockSurface( dstSfc );
scale( FilterFactor,
dstSfc->pixels,
dstSfc->pitch,
srcSfc->pixels,
srcSfc->pitch,
dstSfc->format->BytesPerPixel,
srcSfc->w,
srcSfc->h );
if (IsFilterNormal)
scaleNormal( srcSfc, dstSfc );
else
scale( FilterFactor,
dstSfc->pixels,
dstSfc->pitch,
srcSfc->pixels,
srcSfc->pitch,
dstSfc->format->BytesPerPixel,
srcSfc->w,
srcSfc->h );
SDL_UnlockSurface( dstSfc );
SDL_UnlockSurface( srcSfc );
......
......@@ -44,14 +44,21 @@ public:
Uint32 filterFactor() { return FilterFactor; }
void setFilterType( bool IsNormal );
//bool filterType() { return IsFilterNormal; }
private:
void scaleDynamic( SDL_Surface *srcSfc,
SDL_Surface *dstSfc );
void scaleNormal( SDL_Surface *srcSfc,
SDL_Surface *dstSfc );
float wFac;
float hFac;
Uint32 FilterFactor;
bool IsFilterNormal;
};
#endif /* CSCALER_H_ */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment