diff options
Diffstat (limited to 'engines/titanic/support/video_surface.cpp')
-rw-r--r-- | engines/titanic/support/video_surface.cpp | 240 |
1 files changed, 162 insertions, 78 deletions
diff --git a/engines/titanic/support/video_surface.cpp b/engines/titanic/support/video_surface.cpp index 63ad782722..45813bb740 100644 --- a/engines/titanic/support/video_surface.cpp +++ b/engines/titanic/support/video_surface.cpp @@ -23,16 +23,19 @@ #include "titanic/support/video_surface.h" #include "titanic/support/image_decoders.h" #include "titanic/support/screen_manager.h" +#include "titanic/support/transparency_surface.h" #include "titanic/titanic.h" namespace Titanic { int CVideoSurface::_videoSurfaceCounter = 0; +byte CVideoSurface::_palette1[32][32]; +byte CVideoSurface::_palette2[32][32]; CVideoSurface::CVideoSurface(CScreenManager *screenManager) : _screenManager(screenManager), _rawSurface(nullptr), _movie(nullptr), - _pendingLoad(false), _transBlitFlag(false), _fastBlitFlag(false), - _transparencySurface(nullptr), _transparencyMode(TRANS_DEFAULT), + _pendingLoad(false), _flipVertically(false), _fastBlitFlag(false), + _transparencySurface(nullptr), _transparencyMode(TRANS_DEFAULT), _freeTransparencySurface(DisposeAfterUse::NO), _hasFrame(true), _lockCount(0) { _videoSurfaceNum = _videoSurfaceCounter++; } @@ -46,6 +49,19 @@ CVideoSurface::~CVideoSurface() { delete _transparencySurface; } +void CVideoSurface::setupPalette(byte palette[32][32], byte val) { + for (uint idx1 = 0; idx1 < 32; ++idx1) { + for (uint idx2 = 0, base = 0; idx2 < 32; ++idx2, base += idx1) { + uint v = base / 31; + palette[idx1][idx2] = (byte)v; + + if (val != 0xff && v != idx2) { + assert(0); + } + } + } +} + void CVideoSurface::setSurface(CScreenManager *screenManager, DirectDrawSurface *surface) { _screenManager = screenManager; _ddSurface = surface; @@ -56,10 +72,10 @@ void CVideoSurface::blitFrom(const Point &destPos, CVideoSurface *src, const Rec Rect srcBounds, destBounds; clipBounds(srcBounds, destBounds, src, srcRect, &destPos); - if (src->_transBlitFlag) - blitRect2(srcBounds, destBounds, src); + if (src->_flipVertically) + flippedBlitRect(srcBounds, destBounds, src); else - blitRect1(srcBounds, destBounds, src); + blitRect(srcBounds, destBounds, src); } } @@ -132,44 +148,118 @@ void CVideoSurface::clipBounds(Rect &srcRect, Rect &destRect, error("Invalid rect"); } -void CVideoSurface::blitRect1(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { +void CVideoSurface::blitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { src->lock(); lock(); if (src->_fastBlitFlag) { _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top)); - } else if (getTransparencySurface()) { - transBlitRect(srcRect, destRect, src); - } else { - _rawSurface->transBlitFrom(*src->_rawSurface, srcRect, destRect, src->getTransparencyColor()); - } + } else if (src->getTransparencySurface()) { + transBlitRect(srcRect, destRect, src, false); + } else if (lock()) { + if (src->lock()) { + const Graphics::ManagedSurface *srcSurface = src->_rawSurface; + Graphics::ManagedSurface *destSurface = _rawSurface; + Graphics::Surface destArea = destSurface->getSubArea(destRect); + const uint transColor = src->getTransparencyColor(); + + const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr( + srcRect.left, srcRect.top); + uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, 0); + + for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr, + srcPtr += src->getPitch() / 2, + destPtr += destArea.pitch / 2) { + // Prepare for copying the line + const uint16 *lineSrcP = srcPtr; + uint16 *lineDestP = destPtr; + + for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX, ++lineSrcP, ++lineDestP) { + if (*lineSrcP != transColor) + *lineDestP = *lineSrcP; + } + } - src->unlock(); - unlock(); + src->unlock(); + } + + unlock(); + } } -void CVideoSurface::blitRect2(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { - if (getTransparencySurface()) { - transBlitRect(srcRect, destRect, src); - } else { - src->lock(); - lock(); +void CVideoSurface::flippedBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { + if (src->getTransparencySurface()) { + transBlitRect(srcRect, destRect, src, true); + } else if (lock()) { + if (src->lock()) { + const Graphics::ManagedSurface *srcSurface = src->_rawSurface; + Graphics::ManagedSurface *destSurface = _rawSurface; + Graphics::Surface destArea = destSurface->getSubArea(destRect); + const uint transColor = src->getTransparencyColor(); + + const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr( + srcRect.left, srcRect.top); + uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, destArea.h - 1); + + for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr, + srcPtr += src->getPitch() / 2, + destPtr -= destArea.pitch / 2) { + // Prepare for copying the line + const uint16 *lineSrcP = srcPtr; + uint16 *lineDestP = destPtr; + + for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX, ++lineSrcP, ++lineDestP) { + if (*lineSrcP != transColor) + *lineDestP = *lineSrcP; + } + } - _rawSurface->blitFrom(*src->_rawSurface, srcRect, Point(destRect.left, destRect.top)); + src->unlock(); + } - src->unlock(); unlock(); } } -void CVideoSurface::transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src) { +void CVideoSurface::transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src, bool flipFlag) { + assert(srcRect.width() == destRect.width() && srcRect.height() == destRect.height()); + if (lock()) { if (src->lock()) { Graphics::ManagedSurface *srcSurface = src->_rawSurface; Graphics::ManagedSurface *destSurface = _rawSurface; - - // TODO: Handle the transparency mode correctly - destSurface->blitFrom(*srcSurface, srcRect, Point(srcRect.left, srcRect.top)); + Graphics::Surface destArea = destSurface->getSubArea(destRect); + + const uint16 *srcPtr = (const uint16 *)srcSurface->getBasePtr( + srcRect.left, flipFlag ? srcRect.top : srcRect.bottom - 1); + uint16 *destPtr = (uint16 *)destArea.getBasePtr(0, destArea.h - 1); + bool isAlpha = src->_transparencyMode == TRANS_ALPHA0 || + src->_transparencyMode == TRANS_ALPHA255; + + CTransparencySurface transSurface(src->getTransparencySurface(), src->_transparencyMode); + + for (int yCtr = 0; yCtr < srcRect.height(); ++yCtr) { + // Prepare for copying the line + const uint16 *lineSrcP = srcPtr; + uint16 *lineDestP = destPtr; + transSurface.setRow(flipFlag ? srcRect.top + yCtr : srcRect.bottom - yCtr - 1); + transSurface.setCol(srcRect.left); + + for (int srcX = srcRect.left; srcX < srcRect.right; ++srcX) { + if (!transSurface.isPixelTransparent()) { + copyPixel(lineDestP, lineSrcP, transSurface.getAlpha(), srcSurface->format, isAlpha); + } + + ++lineSrcP; + ++lineDestP; + transSurface.moveX(); + } + + // Move to next line + srcPtr = flipFlag ? srcPtr + (src->getPitch() / 2) : + srcPtr - (src->getPitch() / 2); + destPtr -= destArea.pitch / 2; + } src->unlock(); } @@ -196,10 +286,40 @@ bool CVideoSurface::hasFrame() { } } -/*------------------------------------------------------------------------*/ +#define RGB_SHIFT 3 +void CVideoSurface::copyPixel(uint16 *destP, const uint16 *srcP, byte alpha, + const Graphics::PixelFormat &srcFormat, bool isAlpha) { + const Graphics::PixelFormat destFormat = _ddSurface->getFormat(); + alpha &= 0xff; + assert(alpha < 32); + + // Get the source color + byte r, g, b; + srcFormat.colorToRGB(*srcP, r, g, b); + r >>= RGB_SHIFT; + g >>= RGB_SHIFT; + b >>= RGB_SHIFT; + + if (isAlpha) { + r = _palette1[31 - alpha][r]; + g = _palette1[31 - alpha][g]; + b = _palette1[31 - alpha][b]; + } -byte OSVideoSurface::_palette1[32][32]; -byte OSVideoSurface::_palette2[32][32]; + byte r2, g2, b2; + destFormat.colorToRGB(*destP, r2, g2, b2); + r2 >>= RGB_SHIFT; + g2 >>= RGB_SHIFT; + b2 >>= RGB_SHIFT; + r2 = _palette1[alpha][r2]; + g2 = _palette1[alpha][g2]; + b2 = _palette1[alpha][b2]; + + *destP = destFormat.RGBToColor((r + r2) << RGB_SHIFT, + (g + g2) << RGB_SHIFT, (b + b2) << RGB_SHIFT); +} + +/*------------------------------------------------------------------------*/ OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, DirectDrawSurface *surface) : CVideoSurface(screenManager) { @@ -210,7 +330,7 @@ OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey CVideoSurface(screenManager) { _ddSurface = nullptr; _pendingLoad = pendingLoad; - + if (_pendingLoad) { loadResource(key); } else { @@ -219,24 +339,6 @@ OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey } } -void OSVideoSurface::setupPalette(byte palette[32][32], byte val) { - for (uint idx1 = 0; idx1 < 32; ++idx1) { - for (uint idx2 = 0, base = 0; idx2 < 32; ++idx2, base += idx1) { - int64 v = 0x84210843; - v *= base; - uint v2 = (v >> 36); - v = ((v2 >> 31) + v2) & 0xff; - palette[idx1][idx2] = v << 3; - - if (val != 0xff && v != idx2) { - v = 0x80808081 * v * val; - v2 = v >> 39; - palette[idx1][idx2] = ((v2 >> 31) + v2) << 3; - } - } - } -} - void OSVideoSurface::loadResource(const CResourceKey &key) { _resourceKey = key; _pendingLoad = true; @@ -351,7 +453,7 @@ void OSVideoSurface::recreate(int width, int height) { } void OSVideoSurface::resize(int width, int height) { - if (!_ddSurface || _ddSurface->getWidth() != width || + if (!_ddSurface || _ddSurface->getWidth() != width || _ddSurface->getHeight() != height) recreate(width, height); } @@ -365,7 +467,7 @@ int OSVideoSurface::getPixelDepth() { error("Could not load resource"); lock(); - + int result = _rawSurface->format.bytesPerPixel; if (result == 1) // Paletted 8-bit images don't store the color directly in the pixels @@ -408,8 +510,13 @@ uint16 OSVideoSurface::getPixel(const Common::Point &pt) { if (pt.x >= 0 && pt.y >= 0 && pt.x < getWidth() && pt.y < getHeight()) { if (_transparencySurface) { - const byte *pixelP = (const byte *)_transparencySurface->getBasePtr(pt.x, pt.y); - if (*pixelP != 0xF0) + // WORKAROUND: Original had the setRow _flipVertically check in reverse. + // Pretty sure putting it the way is below is the correct way + CTransparencySurface transSurface(&_transparencySurface->rawSurface(), _transparencyMode); + transSurface.setRow(_flipVertically ? getHeight() - pt.y - 1 : pt.y); + transSurface.setCol(pt.x); + + if (transSurface.isPixelTransparent()) return getTransparencyColor(); } @@ -429,29 +536,6 @@ void OSVideoSurface::setPixel(const Point &pt, uint pixel) { *pixelP = pixel; } -void OSVideoSurface::changePixel(uint16 *pixelP, uint16 *color, byte srcVal, bool remapFlag) { - assert(getPixelDepth() == 2); - const Graphics::PixelFormat &destFormat = _ddSurface->getFormat(); - const Graphics::PixelFormat srcFormat(2, 5, 5, 5, 0, 10, 5, 0, 0); - - // Get the color - byte r, g, b; - srcFormat.colorToRGB(*color, r, g, b); - if (remapFlag) { - r = _palette1[31 - srcVal][r >> 3]; - g = _palette1[31 - srcVal][g >> 3]; - b = _palette1[31 - srcVal][b >> 3]; - } - - byte r2, g2, b2; - destFormat.colorToRGB(*pixelP, r2, g2, b2); - r2 = _palette1[srcVal][r2 >> 3]; - g2 = _palette1[srcVal][g2 >> 3]; - b2 = _palette1[srcVal][b2 >> 3]; - - *pixelP = destFormat.RGBToColor(r + r2, g + g2, b + b2); -} - void OSVideoSurface::shiftColors() { if (!loadIfReady()) return; @@ -510,7 +594,7 @@ const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const { } void OSVideoSurface::flipVertically(bool needsLock) { - if (!loadIfReady() || !_transBlitFlag) + if (!loadIfReady() || !_flipVertically) return; if (needsLock) @@ -529,7 +613,7 @@ void OSVideoSurface::flipVertically(bool needsLock) { Common::copy(lineBuffer, lineBuffer + pitch, line1P); } - _transBlitFlag = false; + _flipVertically = false; if (needsLock) unlock(); } @@ -576,8 +660,8 @@ void OSVideoSurface::transPixelate() { unlock(); } -Graphics::ManagedSurface *OSVideoSurface::dupMovieFrame() const { - return _movie ? _movie->duplicateFrame() : nullptr; +Graphics::ManagedSurface *OSVideoSurface::dupMovieTransparency() const { + return _movie ? _movie->duplicateTransparency() : nullptr; } int OSVideoSurface::freeSurface() { |