Skip to content

Commit

Permalink
TITANIC: Transparency in movie frames now working
Browse files Browse the repository at this point in the history
Turns out the movie frames didn't need to be 32-bit, it just needed
custom copying code to replace transparent pixels with the transparency
color, so when blitted to the screen, the pixels aren't drawn.
  • Loading branch information
dreammaster committed Nov 29, 2016
1 parent 8c45369 commit 8b4a1a7
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 26 deletions.
4 changes: 2 additions & 2 deletions engines/titanic/game_manager.cpp
Expand Up @@ -39,7 +39,7 @@ CGameManager::CGameManager(CProjectItem *project, CGameView *gameView, Audio::Mi

CTimeEventInfo::_nextId = 0;
_movie = nullptr;
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16);
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340);
_project->setGameManager(this);
g_vm->_filesManager->setGameManager(this);
}
Expand Down Expand Up @@ -264,7 +264,7 @@ void CGameManager::viewChange() {
delete _movieSurface;

_movie = nullptr;
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16);
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340);
_trueTalkManager.clear();

for (CTreeItem *treeItem = _project; treeItem; treeItem = treeItem->scan(_project))
Expand Down
2 changes: 1 addition & 1 deletion engines/titanic/star_control/surface_fader_base.cpp
Expand Up @@ -49,7 +49,7 @@ bool CSurfaceFaderBase::setupSurface(CScreenManager *screenManager, CVideoSurfac
delete _videoSurface;
}

_videoSurface = screenManager->createSurface(width, height, 16);
_videoSurface = screenManager->createSurface(width, height);
return true;
}

Expand Down
56 changes: 41 additions & 15 deletions engines/titanic/support/avi_surface.cpp
Expand Up @@ -265,6 +265,33 @@ void AVISurface::setupDecompressor() {
}
}

void AVISurface::copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedSurface &dest) {
assert(src.w == dest.w && src.h == dest.h);

if (src.format.bytesPerPixel == 1) {
Graphics::Surface *s = src.convertTo(dest.format, _decoder->getPalette());
dest.blitFrom(*s);
s->free();
delete s;
} else {
byte a, r, g, b;
assert(src.format.bytesPerPixel == 4 && dest.format.bytesPerPixel == 2);
uint16 transPixel = _videoSurface->getTransparencyColor();

for (uint y = 0; y < src.h; ++y) {
const uint32 *pSrc = (const uint32 *)src.getBasePtr(0, y);
uint16 *pDest = (uint16 *)dest.getBasePtr(0, y);

for (uint x = 0; x < src.w; ++x, ++pSrc, ++pDest) {
src.format.colorToARGB(*pSrc, a, r, g, b);
assert(a == 0 || a == 0xff);

*pDest = (a == 0) ? transPixel : dest.format.RGBToColor(r, g, b);
}
}
}
}

uint AVISurface::getWidth() const {
return _decoder->getWidth();
}
Expand Down Expand Up @@ -309,23 +336,22 @@ bool AVISurface::renderFrame() {

// Make a copy of each decoder's video frame
for (int idx = 0; idx < _streamCount; ++idx) {
const Graphics::Surface *frame = (idx == 0) ?
_decoder->decodeNextFrame() : _decoder->decodeNextTransparency();
const Graphics::Surface *frame;

if (!_movieFrameSurface[idx]) {
// Setup frame surface
_movieFrameSurface[idx] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
_decoder->getVideoTrack(idx).getPixelFormat());
}
if (idx == 0) {
frame = _decoder->decodeNextFrame();
if (!_movieFrameSurface[0])
_movieFrameSurface[0] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
g_system->getScreenFormat());

if (_movieFrameSurface[idx]->format == frame->format) {
_movieFrameSurface[idx]->blitFrom(*frame);
copyMovieFrame(*frame, *_movieFrameSurface[0]);
} else {
Graphics::Surface *s = frame->convertTo(_movieFrameSurface[idx]->format,
_decoder->getPalette());
_movieFrameSurface[idx]->blitFrom(*s);
s->free();
delete s;
frame = _decoder->decodeNextTransparency();
if (!_movieFrameSurface[1])
_movieFrameSurface[1] = new Graphics::ManagedSurface(_decoder->getWidth(), _decoder->getHeight(),
Graphics::PixelFormat::createFormatCLUT8());

_movieFrameSurface[1]->blitFrom(*frame);
}
}

Expand Down Expand Up @@ -397,7 +423,7 @@ Graphics::ManagedSurface *AVISurface::duplicateTransparency() const {
return nullptr;
} else {
Graphics::ManagedSurface *dest = new Graphics::ManagedSurface(_movieFrameSurface[1]->w,
_movieFrameSurface[1]->h, _movieFrameSurface[1]->format);
_movieFrameSurface[1]->h, Graphics::PixelFormat::createFormatCLUT8());
dest->blitFrom(*_movieFrameSurface[1]);
return dest;
}
Expand Down
10 changes: 10 additions & 0 deletions engines/titanic/support/avi_surface.h
Expand Up @@ -78,6 +78,16 @@ class AVISurface {
* Sets up for video decompression
*/
void setupDecompressor();

/**
* Copys a movie frame into a local 16-bit frame surface
* @param src Source raw movie frame
* @param dest Destination 16-bit copy of the frame
* @remarks The important thing this methods different from a straight
* copy is that any pixels marked as fully transparent are replaced with
* the special transparent color value.
*/
void copyMovieFrame(const Graphics::Surface &src, Graphics::ManagedSurface &dest);
protected:
/**
* Start playback at the specified frame
Expand Down
2 changes: 1 addition & 1 deletion engines/titanic/support/mouse_cursor.cpp
Expand Up @@ -74,7 +74,7 @@ void CMouseCursor::loadCursorImages() {
CURSOR_DATA[idx][3]);

// Create the surface
CVideoSurface *surface = _screenManager->createSurface(CURSOR_SIZE, CURSOR_SIZE, 16);
CVideoSurface *surface = _screenManager->createSurface(CURSOR_SIZE, CURSOR_SIZE);
_cursors[idx]._videoSurface = surface;

// Open the cursors video and move to the given frame
Expand Down
5 changes: 2 additions & 3 deletions engines/titanic/support/movie.cpp
Expand Up @@ -88,8 +88,7 @@ OSMovie::OSMovie(const CResourceKey &name, CVideoSurface *surface) :
_field28 = 0;
_field2C = 0;

surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight(),
_aviSurface.getBitDepth() == 32 ? 32 : 16);
surface->resize(_aviSurface.getWidth(), _aviSurface.getHeight());
_aviSurface.setVideoSurface(surface);
}

Expand Down Expand Up @@ -119,7 +118,7 @@ void OSMovie::play(uint startFrame, uint endFrame, uint initialFrame, uint flags

void OSMovie::playCutscene(const Rect &drawRect, uint startFrame, uint endFrame) {
if (!_movieSurface)
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 16);
_movieSurface = CScreenManager::_screenManagerPtr->createSurface(600, 340, 32);

// Set a new event target whilst the clip plays, so standard scene drawing isn't called
CEventTarget eventTarget;
Expand Down
8 changes: 4 additions & 4 deletions engines/titanic/support/screen_manager.h
Expand Up @@ -185,12 +185,12 @@ class CScreenManager {
/**
* Resize the passed surface
*/
virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp) = 0;
virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp = 16) = 0;

/**
* Creates a surface of a given size
*/
virtual CVideoSurface *createSurface(int w, int h, int bpp) = 0;
virtual CVideoSurface *createSurface(int w, int h, int bpp = 16) = 0;

/**
* Creates a surface from a specified resource
Expand Down Expand Up @@ -367,12 +367,12 @@ class OSScreenManager: CScreenManager {
/**
* Resize the passed surface
*/
virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp);
virtual void resizeSurface(CVideoSurface *surface, int width, int height, int bpp = 16);

/**
* Creates a surface of a given size
*/
virtual CVideoSurface *createSurface(int w, int h, int bpp);
virtual CVideoSurface *createSurface(int w, int h, int bpp = 16);

/**
* Creates a surface from a specified resource
Expand Down

0 comments on commit 8b4a1a7

Please sign in to comment.