diff options
author | Eugene Sandulenko | 2016-12-26 16:14:27 +0100 |
---|---|---|
committer | GitHub | 2016-12-26 16:14:27 +0100 |
commit | bdb3808d11ed6658999e383f23007305580b814c (patch) | |
tree | 4a9771249084ff0e53da367ce70d1333d712a8d3 | |
parent | f3e0c4d093f52d1728b65c078df88c2f482ec956 (diff) | |
parent | b7bd1991933526a6637e4ea0fd3f1305d0f6627a (diff) | |
download | scummvm-rg350-bdb3808d11ed6658999e383f23007305580b814c.tar.gz scummvm-rg350-bdb3808d11ed6658999e383f23007305580b814c.tar.bz2 scummvm-rg350-bdb3808d11ed6658999e383f23007305580b814c.zip |
Merge pull request #734 from tobiatesan/enable_bilinear
WINTERMUTE: Enable bilinear filtering in Wintermute
-rw-r--r-- | engines/wintermute/base/base_game.cpp | 6 | ||||
-rw-r--r-- | engines/wintermute/base/base_game.h | 3 | ||||
-rw-r--r-- | engines/wintermute/base/gfx/osystem/render_ticket.cpp | 15 | ||||
-rw-r--r-- | engines/wintermute/detection.cpp | 13 | ||||
-rw-r--r-- | engines/wintermute/detection_tables.h | 1 | ||||
-rw-r--r-- | graphics/transparent_surface.cpp | 382 | ||||
-rw-r--r-- | graphics/transparent_surface.h | 10 |
7 files changed, 242 insertions, 188 deletions
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp index ef3cc2d84f..24779b9793 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -361,6 +361,12 @@ bool BaseGame::initConfManSettings() { _debugShowFPS = false; } + if (ConfMan.hasKey("bilinear_filtering")) { + _bilinearFiltering = ConfMan.getBool("bilinear_filtering"); + } else { + _bilinearFiltering = false; + } + if (ConfMan.hasKey("disable_smartcache")) { _smartCache = ConfMan.getBool("disable_smartcache"); } else { diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h index 6aacc1feab..46484cc5ca 100644 --- a/engines/wintermute/base/base_game.h +++ b/engines/wintermute/base/base_game.h @@ -101,7 +101,7 @@ public: virtual bool displayDebugInfo(); void setShowFPS(bool enabled) { _debugShowFPS = enabled; } - + bool getBilinearFiltering() { return _bilinearFiltering; } bool getSuspendedRendering() const { return _suspendedRendering; } TTextEncoding _textEncoding; @@ -279,6 +279,7 @@ protected: VideoTheoraPlayer *_theoraPlayer; private: bool _debugShowFPS; + bool _bilinearFiltering; void *_debugLogFile; void DEBUG_DebugDisable(); void DEBUG_DebugEnable(const char *filename = nullptr); diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index afe884300a..78d445ac8c 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -27,6 +27,7 @@ */ +#include "engines/wintermute/base/base_game.h" #include "engines/wintermute/base/gfx/osystem/render_ticket.h" #include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" #include "graphics/transform_tools.h" @@ -59,7 +60,12 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s // TransformTools.) if (_transform._angle != Graphics::kDefaultAngle) { Graphics::TransparentSurface src(*_surface, false); - Graphics::Surface *temp = src.rotoscale(transform); + Graphics::Surface *temp; + if (owner->_gameRef->getBilinearFiltering()) { + temp = src.rotoscale<Graphics::FILTER_BILINEAR>(transform); + } else { + temp = src.rotoscale<Graphics::FILTER_NEAREST>(transform); + } _surface->free(); delete _surface; _surface = temp; @@ -67,7 +73,12 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s dstRect->height() != srcRect->height()) && _transform._numTimesX * _transform._numTimesY == 1) { Graphics::TransparentSurface src(*_surface, false); - Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); + Graphics::Surface *temp; + if (owner->_gameRef->getBilinearFiltering()) { + temp = src.scale<Graphics::FILTER_BILINEAR>(dstRect->width(), dstRect->height()); + } else { + temp = src.scale<Graphics::FILTER_NEAREST>(dstRect->width(), dstRect->height()); + } _surface->free(); delete _surface; _surface = temp; diff --git a/engines/wintermute/detection.cpp b/engines/wintermute/detection.cpp index 4e8eab505f..9ccb75d62f 100644 --- a/engines/wintermute/detection.cpp +++ b/engines/wintermute/detection.cpp @@ -59,8 +59,19 @@ static const ADExtraGuiOptionsMap gameGuiOptions[] = { _s("Show the current number of frames per second in the upper left corner"), "show_fps", false + }, + }, + + { + GAMEOPTION_BILINEAR, + { + _s("Sprite bilinear filtering (SLOW)"), + _s("Apply bilinear filtering to individual sprites"), + "bilinear_filtering", + false } }, + AD_EXTRA_GUI_OPTIONS_TERMINATOR }; @@ -76,7 +87,7 @@ class WintermuteMetaEngine : public AdvancedMetaEngine { public: WintermuteMetaEngine() : AdvancedMetaEngine(Wintermute::gameDescriptions, sizeof(WMEGameDescription), Wintermute::wintermuteGames, gameGuiOptions) { _singleId = "wintermute"; - _guiOptions = GUIO2(GUIO_NOMIDI, GAMEOPTION_SHOW_FPS); + _guiOptions = GUIO3(GUIO_NOMIDI, GAMEOPTION_SHOW_FPS, GAMEOPTION_BILINEAR); _maxScanDepth = 2; _directoryGlobs = directoryGlobs; } diff --git a/engines/wintermute/detection_tables.h b/engines/wintermute/detection_tables.h index 68985d8d0c..681d4dec42 100644 --- a/engines/wintermute/detection_tables.h +++ b/engines/wintermute/detection_tables.h @@ -23,6 +23,7 @@ namespace Wintermute { #define GAMEOPTION_SHOW_FPS GUIO_GAMEOPTIONS1 +#define GAMEOPTION_BILINEAR GUIO_GAMEOPTIONS2 static const PlainGameDescriptor wintermuteGames[] = { {"5ld", "Five Lethal Demons"}, diff --git a/graphics/transparent_surface.cpp b/graphics/transparent_surface.cpp index 7ef7d00286..2a5decf4e2 100644 --- a/graphics/transparent_surface.cpp +++ b/graphics/transparent_surface.cpp @@ -37,8 +37,6 @@ #include "graphics/transparent_surface.h" #include "graphics/transform_tools.h" -//#define ENABLE_BILINEAR - namespace Graphics { static const int kBModShift = 0;//img->format.bShift; @@ -677,6 +675,7 @@ systems. +template <TFilteringMode filteringMode> TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { assert(transform._angle != 0); // This would not be ideal; rotoscale() should never be called in conditional branches where angle = 0 anyway. @@ -739,50 +738,50 @@ TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transfo dy = sh - dy; } -#ifdef ENABLE_BILINEAR - if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) { - const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); - tColorRGBA c00, c01, c10, c11, cswap; - c00 = *sp; - sp += 1; - c01 = *sp; - sp += (this->pitch / 4); - c11 = *sp; - sp -= 1; - c10 = *sp; - if (flipx) { - cswap = c00; c00=c01; c01=cswap; - cswap = c10; c10=c11; c11=cswap; + if (filteringMode == FILTER_BILINEAR) { + if ((dx > -1) && (dy > -1) && (dx < sw) && (dy < sh)) { + const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); + tColorRGBA c00, c01, c10, c11, cswap; + c00 = *sp; + sp += 1; + c01 = *sp; + sp += (this->pitch / 4); + c11 = *sp; + sp -= 1; + c10 = *sp; + if (flipx) { + cswap = c00; c00=c01; c01=cswap; + cswap = c10; c10=c11; c11=cswap; + } + if (flipy) { + cswap = c00; c00=c10; c10=cswap; + cswap = c01; c01=c11; c11=cswap; + } + /* + * Interpolate colors + */ + int ex = (sdx & 0xffff); + int ey = (sdy & 0xffff); + int t1, t2; + t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; + t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; + pc->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; + t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; + pc->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; + t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; + pc->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; + t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; + pc->a = (((t2 - t1) * ey) >> 16) + t1; } - if (flipy) { - cswap = c00; c00=c10; c10=cswap; - cswap = c01; c01=c11; c11=cswap; + } else { + if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) { + const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); + *pc = *sp; } - /* - * Interpolate colors - */ - int ex = (sdx & 0xffff); - int ey = (sdy & 0xffff); - int t1, t2; - t1 = ((((c01.r - c00.r) * ex) >> 16) + c00.r) & 0xff; - t2 = ((((c11.r - c10.r) * ex) >> 16) + c10.r) & 0xff; - pc->r = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.g - c00.g) * ex) >> 16) + c00.g) & 0xff; - t2 = ((((c11.g - c10.g) * ex) >> 16) + c10.g) & 0xff; - pc->g = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.b - c00.b) * ex) >> 16) + c00.b) & 0xff; - t2 = ((((c11.b - c10.b) * ex) >> 16) + c10.b) & 0xff; - pc->b = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01.a - c00.a) * ex) >> 16) + c00.a) & 0xff; - t2 = ((((c11.a - c10.a) * ex) >> 16) + c10.a) & 0xff; - pc->a = (((t2 - t1) * ey) >> 16) + t1; - } -#else - if ((dx >= 0) && (dy >= 0) && (dx < srcW) && (dy < srcH)) { - const tColorRGBA *sp = (const tColorRGBA *)getBasePtr(dx, dy); - *pc = *sp; } -#endif sdx += icosx; sdy += isiny; pc++; @@ -791,6 +790,7 @@ TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transfo return target; } +template <TFilteringMode filteringMode> TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { Common::Rect srcRect(0, 0, (int16)w, (int16)h); @@ -807,173 +807,173 @@ TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) target->create((uint16)dstW, (uint16)dstH, this->format); -#ifdef ENABLE_BILINEAR + if (filteringMode == FILTER_BILINEAR) { - // NB: The actual order of these bytes may not be correct, but - // since all values are treated equal, that does not matter. - struct tColorRGBA { byte r; byte g; byte b; byte a; }; + // NB: The actual order of these bytes may not be correct, but + // since all values are treated equal, that does not matter. + struct tColorRGBA { byte r; byte g; byte b; byte a; }; - bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor + bool flipx = false, flipy = false; // TODO: See mirroring comment in RenderTicket ctor + + + int *sax = new int[dstW + 1]; + int *say = new int[dstH + 1]; + assert(sax && say); + /* + * Precalculate row increments + */ + int spixelw = (srcW - 1); + int spixelh = (srcH - 1); + int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1)); + int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1)); + + /* Maximum scaled source size */ + int ssx = (srcW << 16) - 1; + int ssy = (srcH << 16) - 1; + + /* Precalculate horizontal row increments */ + int csx = 0; + int *csax = sax; + for (int x = 0; x <= dstW; x++) { + *csax = csx; + csax++; + csx += sx; - int *sax = new int[dstW + 1]; - int *say = new int[dstH + 1]; - assert(sax && say); - - /* - * Precalculate row increments - */ - int spixelw = (srcW - 1); - int spixelh = (srcH - 1); - int sx = (int) (65536.0f * (float) spixelw / (float) (dstW - 1)); - int sy = (int) (65536.0f * (float) spixelh / (float) (dstH - 1)); - - /* Maximum scaled source size */ - int ssx = (srcW << 16) - 1; - int ssy = (srcH << 16) - 1; - - /* Precalculate horizontal row increments */ - int csx = 0; - int *csax = sax; - for (int x = 0; x <= dstW; x++) { - *csax = csx; - csax++; - csx += sx; - - /* Guard from overflows */ - if (csx > ssx) { - csx = ssx; + /* Guard from overflows */ + if (csx > ssx) { + csx = ssx; + } } - } - /* Precalculate vertical row increments */ - int csy = 0; - int *csay = say; - for (int y = 0; y <= dstH; y++) { - *csay = csy; - csay++; - csy += sy; - - /* Guard from overflows */ - if (csy > ssy) { - csy = ssy; + /* Precalculate vertical row increments */ + int csy = 0; + int *csay = say; + for (int y = 0; y <= dstH; y++) { + *csay = csy; + csay++; + csy += sy; + + /* Guard from overflows */ + if (csy > ssy) { + csy = ssy; + } } - } - const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0); - tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0); - int spixelgap = srcW; + const tColorRGBA *sp = (const tColorRGBA *) getBasePtr(0, 0); + tColorRGBA *dp = (tColorRGBA *) target->getBasePtr(0, 0); + int spixelgap = srcW; - if (flipx) { - sp += spixelw; - } - if (flipy) { - sp += spixelgap * spixelh; - } + if (flipx) { + sp += spixelw; + } + if (flipy) { + sp += spixelgap * spixelh; + } - csay = say; - for (int y = 0; y < dstH; y++) { - const tColorRGBA *csp = sp; - csax = sax; - for (int x = 0; x < dstW; x++) { - /* - * Setup color source pointers - */ - int ex = (*csax & 0xffff); - int ey = (*csay & 0xffff); - int cx = (*csax >> 16); - int cy = (*csay >> 16); - - const tColorRGBA *c00, *c01, *c10, *c11; - c00 = sp; - c01 = sp; - c10 = sp; - if (cy < spixelh) { - if (flipy) { - c10 -= spixelgap; - } else { - c10 += spixelgap; + csay = say; + for (int y = 0; y < dstH; y++) { + const tColorRGBA *csp = sp; + csax = sax; + for (int x = 0; x < dstW; x++) { + /* + * Setup color source pointers + */ + int ex = (*csax & 0xffff); + int ey = (*csay & 0xffff); + int cx = (*csax >> 16); + int cy = (*csay >> 16); + + const tColorRGBA *c00, *c01, *c10, *c11; + c00 = sp; + c01 = sp; + c10 = sp; + if (cy < spixelh) { + if (flipy) { + c10 -= spixelgap; + } else { + c10 += spixelgap; + } } - } - c11 = c10; - if (cx < spixelw) { + c11 = c10; + if (cx < spixelw) { + if (flipx) { + c01--; + c11--; + } else { + c01++; + c11++; + } + } + + /* + * Draw and interpolate colors + */ + int t1, t2; + t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; + t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; + dp->r = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; + t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; + dp->g = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; + t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; + dp->b = (((t2 - t1) * ey) >> 16) + t1; + t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; + t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; + dp->a = (((t2 - t1) * ey) >> 16) + t1; + + /* + * Advance source pointer x + */ + int *salastx = csax; + csax++; + int sstepx = (*csax >> 16) - (*salastx >> 16); if (flipx) { - c01--; - c11--; + sp -= sstepx; } else { - c01++; - c11++; + sp += sstepx; } - } - - /* - * Draw and interpolate colors - */ - int t1, t2; - t1 = ((((c01->r - c00->r) * ex) >> 16) + c00->r) & 0xff; - t2 = ((((c11->r - c10->r) * ex) >> 16) + c10->r) & 0xff; - dp->r = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->g - c00->g) * ex) >> 16) + c00->g) & 0xff; - t2 = ((((c11->g - c10->g) * ex) >> 16) + c10->g) & 0xff; - dp->g = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->b - c00->b) * ex) >> 16) + c00->b) & 0xff; - t2 = ((((c11->b - c10->b) * ex) >> 16) + c10->b) & 0xff; - dp->b = (((t2 - t1) * ey) >> 16) + t1; - t1 = ((((c01->a - c00->a) * ex) >> 16) + c00->a) & 0xff; - t2 = ((((c11->a - c10->a) * ex) >> 16) + c10->a) & 0xff; - dp->a = (((t2 - t1) * ey) >> 16) + t1; + /* + * Advance destination pointer x + */ + dp++; + } /* - * Advance source pointer x + * Advance source pointer y */ - int *salastx = csax; - csax++; - int sstepx = (*csax >> 16) - (*salastx >> 16); - if (flipx) { - sp -= sstepx; + int *salasty = csay; + csay++; + int sstepy = (*csay >> 16) - (*salasty >> 16); + sstepy *= spixelgap; + if (flipy) { + sp = csp - sstepy; } else { - sp += sstepx; + sp = csp + sstepy; } - - /* - * Advance destination pointer x - */ - dp++; - } - /* - * Advance source pointer y - */ - int *salasty = csay; - csay++; - int sstepy = (*csay >> 16) - (*salasty >> 16); - sstepy *= spixelgap; - if (flipy) { - sp = csp - sstepy; - } else { - sp = csp + sstepy; } - } - delete[] sax; - delete[] say; + delete[] sax; + delete[] say; -#else - - int *scaleCacheX = new int[dstW]; - for (int x = 0; x < dstW; x++) { - scaleCacheX[x] = (x * srcW) / dstW; - } + } else { - for (int y = 0; y < dstH; y++) { - uint32 *destP = (uint32 *)target->getBasePtr(0, y); - const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH); + int *scaleCacheX = new int[dstW]; for (int x = 0; x < dstW; x++) { - *destP++ = srcP[scaleCacheX[x]]; + scaleCacheX[x] = (x * srcW) / dstW; } - } - delete[] scaleCacheX; -#endif + for (int y = 0; y < dstH; y++) { + uint32 *destP = (uint32 *)target->getBasePtr(0, y); + const uint32 *srcP = (const uint32 *)getBasePtr(0, (y * srcH) / dstH); + for (int x = 0; x < dstW; x++) { + *destP++ = srcP[scaleCacheX[x]]; + } + } + delete[] scaleCacheX; + + } return target; @@ -1057,4 +1057,18 @@ TransparentSurface *TransparentSurface::convertTo(const PixelFormat &dstFormat, return surface; } + +template TransparentSurface *TransparentSurface::rotoscale<FILTER_NEAREST>(const TransformStruct &transform) const; +template TransparentSurface *TransparentSurface::rotoscale<FILTER_BILINEAR>(const TransformStruct &transform) const; +template TransparentSurface *TransparentSurface::scale<FILTER_NEAREST>(uint16 newWidth, uint16 newHeight) const; +template TransparentSurface *TransparentSurface::scale<FILTER_BILINEAR>(uint16 newWidth, uint16 newHeight) const; + +TransparentSurface *TransparentSurface::rotoscale(const TransformStruct &transform) const { + return rotoscale<FILTER_BILINEAR>(transform); +} + +TransparentSurface *TransparentSurface::scale(uint16 newWidth, uint16 newHeight) const { + return scale<FILTER_NEAREST>(newWidth, newHeight); +} + } // End of namespace Graphics diff --git a/graphics/transparent_surface.h b/graphics/transparent_surface.h index 8654183548..83c65766fb 100644 --- a/graphics/transparent_surface.h +++ b/graphics/transparent_surface.h @@ -68,6 +68,11 @@ enum AlphaType { ALPHA_FULL = 2 }; +enum TFilteringMode { + FILTER_NEAREST = 0, + FILTER_BILINEAR = 1 +}; + /** * A transparent graphics surface, which implements alpha blitting. */ @@ -141,8 +146,10 @@ struct TransparentSurface : public Graphics::Surface { * @param newHeight the resulting height. * @see TransformStruct */ + template <TFilteringMode filteringMode> TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; + TransparentSurface *scale(uint16 newWidth, uint16 newHeight) const; /** * @brief Rotoscale function; this returns a transformed version of this surface after rotation and * scaling. Please do not use this if angle == 0, use plain old scaling function. @@ -150,6 +157,9 @@ struct TransparentSurface : public Graphics::Surface { * @param transform a TransformStruct wrapping the required info. @see TransformStruct * */ + template <TFilteringMode filteringMode> + TransparentSurface *rotoscale(const TransformStruct &transform) const; + TransparentSurface *rotoscale(const TransformStruct &transform) const; TransparentSurface *convertTo(const PixelFormat &dstFormat, const byte *palette = 0) const; |