Initial commit
This commit is contained in:
664
engines/titanic/support/video_surface.cpp
Normal file
664
engines/titanic/support/video_surface.cpp
Normal file
@@ -0,0 +1,664 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#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), _flipVertically(false), _fastBlitFlag(false),
|
||||
_transparencySurface(nullptr), _transparencyMode(TRANS_DEFAULT),
|
||||
_freeTransparencySurface(DisposeAfterUse::NO), _hasFrame(true), _lockCount(0) {
|
||||
_videoSurfaceNum = _videoSurfaceCounter++;
|
||||
}
|
||||
|
||||
CVideoSurface::~CVideoSurface() {
|
||||
--_videoSurfaceCounter;
|
||||
|
||||
if (_freeTransparencySurface == DisposeAfterUse::YES)
|
||||
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;
|
||||
}
|
||||
|
||||
void CVideoSurface::blitFrom(const Point &destPos, CVideoSurface *src, const Rect *srcRect) {
|
||||
if (loadIfReady() && src->loadIfReady() && _ddSurface && src->_ddSurface) {
|
||||
Rect srcBounds, destBounds;
|
||||
clipBounds(srcBounds, destBounds, src, srcRect, &destPos);
|
||||
|
||||
if (src->_flipVertically)
|
||||
flippedBlitRect(srcBounds, destBounds, src);
|
||||
else
|
||||
blitRect(srcBounds, destBounds, src);
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoSurface::blitFrom(const Point &destPos, const Graphics::Surface *src) {
|
||||
lock();
|
||||
_rawSurface->blitFrom(*src, destPos);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void CVideoSurface::clipBounds(Rect &srcRect, Rect &destRect,
|
||||
CVideoSurface *srcSurface, const Rect *subRect, const Point *destPos) {
|
||||
// Figure out initial source rect and dest rect, based on whether
|
||||
// specific subRect and/or destPos have been passed
|
||||
if (destPos) {
|
||||
destRect.left = destPos->x;
|
||||
destRect.top = destPos->y;
|
||||
} else {
|
||||
destRect.left = destRect.top = 0;
|
||||
}
|
||||
|
||||
if (subRect) {
|
||||
destRect.right = destRect.left + subRect->width();
|
||||
destRect.bottom = destRect.top + subRect->height();
|
||||
srcRect = *subRect;
|
||||
} else {
|
||||
srcRect.right = srcRect.left + srcSurface->getWidth();
|
||||
srcRect.bottom = srcRect.top + srcSurface->getHeight();
|
||||
srcRect = Rect(0, 0, srcSurface->getWidth(), srcSurface->getHeight());
|
||||
}
|
||||
|
||||
// Clip destination rect to be on-screen
|
||||
if (destRect.left < 0) {
|
||||
srcRect.left -= destRect.left;
|
||||
destRect.left = 0;
|
||||
}
|
||||
if (destRect.top < 0) {
|
||||
srcRect.top -= destRect.top;
|
||||
destRect.top = 0;
|
||||
}
|
||||
if (destRect.right > getWidth()) {
|
||||
srcRect.right += getWidth() - destRect.right;
|
||||
destRect.right = getWidth();
|
||||
}
|
||||
if (destRect.bottom > getHeight()) {
|
||||
srcRect.bottom += getHeight() - destRect.bottom;
|
||||
destRect.bottom = getHeight();
|
||||
}
|
||||
|
||||
// Clip source rect to be within the source surface
|
||||
if (srcRect.left < 0) {
|
||||
destRect.left -= srcRect.left;
|
||||
srcRect.left = 0;
|
||||
}
|
||||
if (srcRect.top < 0) {
|
||||
destRect.top -= srcRect.top;
|
||||
srcRect.top = 0;
|
||||
}
|
||||
if (srcRect.right > srcSurface->getWidth()) {
|
||||
destRect.right += srcSurface->getWidth() - srcRect.right;
|
||||
srcRect.right = srcSurface->getWidth();
|
||||
}
|
||||
if (srcRect.bottom > srcSurface->getHeight()) {
|
||||
destRect.bottom += srcSurface->getHeight() - srcRect.bottom;
|
||||
srcRect.bottom = srcSurface->getHeight();
|
||||
}
|
||||
|
||||
// Validate that the resulting rects are valid
|
||||
if (destRect.left >= destRect.right || destRect.top >= destRect.bottom
|
||||
|| srcRect.left >= srcRect.right || srcRect.top >= srcRect.bottom)
|
||||
error("Invalid rect");
|
||||
}
|
||||
|
||||
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 (src->getTransparencySurface()) {
|
||||
transBlitRect(srcRect, destRect, src, false);
|
||||
} else if (lock()) {
|
||||
if (src->lock()) {
|
||||
const Graphics::ManagedSurface *srcSurface = src->_rawSurface;
|
||||
Graphics::ManagedSurface *destSurface = _rawSurface;
|
||||
const uint transColor = src->getTransparencyColor();
|
||||
|
||||
destSurface->transBlitFrom(*srcSurface, srcRect, destRect, transColor);
|
||||
|
||||
src->unlock();
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
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()) {
|
||||
Graphics::ManagedSurface *srcSurface = src->_rawSurface;
|
||||
Graphics::ManagedSurface *destSurface = _rawSurface;
|
||||
const Graphics::Surface srcArea = srcSurface->getSubArea(srcRect);
|
||||
const uint transColor = src->getTransparencyColor();
|
||||
|
||||
// Vertically flip the source area
|
||||
Graphics::ManagedSurface flippedArea(srcArea.w, srcArea.h, srcArea.format);
|
||||
for (int y = 0; y < srcArea.h; ++y) {
|
||||
const byte *pSrc = (const byte *)srcArea.getBasePtr(0, y);
|
||||
byte *pDest = (byte *)flippedArea.getBasePtr(0, flippedArea.h - y - 1);
|
||||
Common::copy(pSrc, pSrc + srcArea.pitch, pDest);
|
||||
}
|
||||
|
||||
destSurface->transBlitFrom(flippedArea,
|
||||
Common::Point(destRect.left, destRect.top), transColor);
|
||||
|
||||
src->unlock();
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void CVideoSurface::transBlitRect(const Rect &srcRect, const Rect &destRect, CVideoSurface *src, bool flipFlag) {
|
||||
assert(srcRect.width() == destRect.width() && srcRect.height() == destRect.height());
|
||||
assert(src->getPixelDepth() == 2);
|
||||
|
||||
if (lock()) {
|
||||
if (src->lock()) {
|
||||
Graphics::ManagedSurface *srcSurface = src->_rawSurface;
|
||||
Graphics::ManagedSurface *destSurface = _rawSurface;
|
||||
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.isPixelOpaque())
|
||||
*lineDestP = *lineSrcP;
|
||||
else if (!transSurface.isPixelTransparent())
|
||||
copyPixel(lineDestP, lineSrcP, transSurface.getAlpha() >> 3, 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();
|
||||
}
|
||||
|
||||
unlock();
|
||||
}
|
||||
}
|
||||
|
||||
uint CVideoSurface::getTransparencyColor() {
|
||||
return getPixelDepth() == 2 ? 0xf81f : 0x7c1f;
|
||||
}
|
||||
|
||||
bool CVideoSurface::hasFrame() {
|
||||
if (_hasFrame) {
|
||||
_hasFrame = false;
|
||||
return true;
|
||||
} else if (_movie) {
|
||||
return _movie->hasVideoFrame();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#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 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) {
|
||||
_ddSurface = surface;
|
||||
}
|
||||
|
||||
OSVideoSurface::OSVideoSurface(CScreenManager *screenManager, const CResourceKey &key, bool pendingLoad) :
|
||||
CVideoSurface(screenManager) {
|
||||
_ddSurface = nullptr;
|
||||
_pendingLoad = pendingLoad;
|
||||
|
||||
if (_pendingLoad) {
|
||||
loadResource(key);
|
||||
} else {
|
||||
_resourceKey = key;
|
||||
load();
|
||||
}
|
||||
}
|
||||
|
||||
OSVideoSurface::~OSVideoSurface() {
|
||||
if (_ddSurface)
|
||||
_videoSurfaceCounter -= OSVideoSurface::freeSurface();
|
||||
}
|
||||
|
||||
void OSVideoSurface::loadResource(const CResourceKey &key) {
|
||||
_resourceKey = key;
|
||||
_pendingLoad = true;
|
||||
|
||||
if (hasSurface())
|
||||
load();
|
||||
}
|
||||
|
||||
void OSVideoSurface::loadTarga(const CResourceKey &key) {
|
||||
// Decode the image
|
||||
CTargaDecode decoder;
|
||||
decoder.decode(*this, key.getString());
|
||||
|
||||
if (getPixelDepth() == 2)
|
||||
shiftColors();
|
||||
|
||||
_resourceKey = key;
|
||||
|
||||
}
|
||||
|
||||
void OSVideoSurface::loadJPEG(const CResourceKey &key) {
|
||||
// Decode the image
|
||||
CJPEGDecode decoder;
|
||||
decoder.decode(*this, key.getString());
|
||||
|
||||
if (getPixelDepth() == 2)
|
||||
shiftColors();
|
||||
|
||||
_resourceKey = key;
|
||||
}
|
||||
|
||||
void OSVideoSurface::loadTarga(const CString &name) {
|
||||
CResourceKey key(name);
|
||||
loadTarga(key);
|
||||
}
|
||||
|
||||
void OSVideoSurface::loadMovie(const CResourceKey &key, bool destroyFlag) {
|
||||
// Delete any prior movie
|
||||
if (_movie) {
|
||||
delete _movie;
|
||||
_movie = nullptr;
|
||||
}
|
||||
|
||||
// Create the new movie and load the first frame to the video surface
|
||||
_movie = g_vm->_movieManager.createMovie(key, this);
|
||||
_movie->setFrame(0);
|
||||
|
||||
// If flagged to destroy, then immediately destroy movie instance
|
||||
if (destroyFlag) {
|
||||
delete _movie;
|
||||
_movie = nullptr;
|
||||
}
|
||||
|
||||
_resourceKey = key;
|
||||
}
|
||||
|
||||
bool OSVideoSurface::lock() {
|
||||
if (!loadIfReady())
|
||||
return false;
|
||||
|
||||
++_lockCount;
|
||||
_rawSurface = _ddSurface->lock(nullptr, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void OSVideoSurface::unlock() {
|
||||
if (!--_lockCount) {
|
||||
if (_rawSurface)
|
||||
_ddSurface->unlock();
|
||||
_rawSurface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool OSVideoSurface::hasSurface() {
|
||||
return _ddSurface != nullptr;
|
||||
}
|
||||
|
||||
int OSVideoSurface::getWidth() {
|
||||
if (!loadIfReady())
|
||||
error("Could not load resource");
|
||||
|
||||
return _ddSurface->getWidth();
|
||||
}
|
||||
|
||||
int OSVideoSurface::getHeight() {
|
||||
if (!loadIfReady())
|
||||
error("Could not load resource");
|
||||
|
||||
return _ddSurface->getHeight();
|
||||
}
|
||||
|
||||
int OSVideoSurface::getPitch() {
|
||||
if (!loadIfReady())
|
||||
error("Could not load resource");
|
||||
|
||||
return _ddSurface->getPitch();
|
||||
}
|
||||
|
||||
int OSVideoSurface::getBpp() {
|
||||
if (!loadIfReady())
|
||||
error("Could not load resource");
|
||||
|
||||
return getPixelDepth();
|
||||
}
|
||||
|
||||
void OSVideoSurface::recreate(int width, int height, int bpp) {
|
||||
freeSurface();
|
||||
|
||||
_screenManager->resizeSurface(this, width, height, bpp);
|
||||
if (_ddSurface)
|
||||
_videoSurfaceCounter += _ddSurface->getSize();
|
||||
}
|
||||
|
||||
void OSVideoSurface::resize(int width, int height, int bpp) {
|
||||
if (!_ddSurface || _ddSurface->getWidth() != width ||
|
||||
_ddSurface->getHeight() != height)
|
||||
recreate(width, height, bpp);
|
||||
}
|
||||
|
||||
void OSVideoSurface::detachSurface() {
|
||||
_ddSurface = nullptr;
|
||||
}
|
||||
|
||||
int OSVideoSurface::getPixelDepth() {
|
||||
if (!loadIfReady())
|
||||
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
|
||||
result = 0;
|
||||
|
||||
unlock();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool OSVideoSurface::load() {
|
||||
if (!_resourceKey.scanForFile())
|
||||
return false;
|
||||
|
||||
switch (_resourceKey.fileTypeSuffix()) {
|
||||
case FILETYPE_IMAGE:
|
||||
switch (_resourceKey.imageTypeSuffix()) {
|
||||
case IMAGETYPE_TARGA:
|
||||
loadTarga(_resourceKey);
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
loadJPEG(_resourceKey);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
|
||||
case FILETYPE_MOVIE:
|
||||
loadMovie(_resourceKey);
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 OSVideoSurface::getPixel(const Common::Point &pt) {
|
||||
if (!loadIfReady())
|
||||
return 0;
|
||||
|
||||
if (pt.x >= 0 && pt.y >= 0 && pt.x < getWidth() && pt.y < getHeight()) {
|
||||
if (_transparencySurface) {
|
||||
// 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();
|
||||
}
|
||||
|
||||
lock();
|
||||
uint16 pixel = *(uint16 *)_rawSurface->getBasePtr(pt.x, pt.y);
|
||||
unlock();
|
||||
return pixel;
|
||||
} else {
|
||||
return getTransparencyColor();
|
||||
}
|
||||
}
|
||||
|
||||
void OSVideoSurface::setPixel(const Point &pt, uint pixel) {
|
||||
assert(getPixelDepth() == 2);
|
||||
|
||||
uint16 *pixelP = (uint16 *)_rawSurface->getBasePtr(pt.x, pt.y);
|
||||
*pixelP = pixel;
|
||||
}
|
||||
|
||||
void OSVideoSurface::shiftColors() {
|
||||
if (!loadIfReady())
|
||||
return;
|
||||
|
||||
// Currently no further processing is needed, since for ScummVM,
|
||||
// we already convert 16-bit surfaces as soon as they're loaded
|
||||
}
|
||||
|
||||
void OSVideoSurface::clear() {
|
||||
if (!loadIfReady())
|
||||
error("Could not load resource");
|
||||
|
||||
_ddSurface->fill(nullptr, 0);
|
||||
}
|
||||
|
||||
void OSVideoSurface::playMovie(uint flags, CGameObject *obj) {
|
||||
if (loadIfReady() && _movie)
|
||||
_movie->play(flags, obj);
|
||||
}
|
||||
|
||||
void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint flags, CGameObject *obj) {
|
||||
if (loadIfReady() && _movie) {
|
||||
_movie->play(startFrame, endFrame, flags, obj);
|
||||
_movie->pause();
|
||||
}
|
||||
}
|
||||
|
||||
void OSVideoSurface::playMovie(uint startFrame, uint endFrame, uint initialFrame, uint flags, CGameObject *obj) {
|
||||
if (loadIfReady() && _movie) {
|
||||
_movie->play(startFrame, endFrame, initialFrame, flags, obj);
|
||||
}
|
||||
}
|
||||
|
||||
void OSVideoSurface::stopMovie() {
|
||||
if (_movie)
|
||||
_movie->stop();
|
||||
}
|
||||
|
||||
void OSVideoSurface::setMovieFrame(uint frameNumber) {
|
||||
if (loadIfReady() && _movie)
|
||||
_movie->setFrame(frameNumber);
|
||||
}
|
||||
|
||||
void OSVideoSurface::addMovieEvent(int frameNumber, CGameObject *obj) {
|
||||
if (_movie)
|
||||
_movie->addEvent(frameNumber, obj);
|
||||
}
|
||||
|
||||
void OSVideoSurface::setMovieFrameRate(double rate) {
|
||||
if (_movie)
|
||||
_movie->setFrameRate(rate);
|
||||
}
|
||||
|
||||
const CMovieRangeInfoList *OSVideoSurface::getMovieRangeInfo() const {
|
||||
return _movie ? _movie->getMovieRangeInfo() : nullptr;
|
||||
}
|
||||
|
||||
void OSVideoSurface::flipVertically(bool needsLock) {
|
||||
if (!loadIfReady() || !_flipVertically)
|
||||
return;
|
||||
|
||||
if (needsLock)
|
||||
lock();
|
||||
|
||||
byte lineBuffer[SCREEN_WIDTH * 2];
|
||||
int pitch = getBpp() * getWidth();
|
||||
assert(pitch < (SCREEN_WIDTH * 2));
|
||||
|
||||
for (int yp = 0; yp < (_rawSurface->h / 2); ++yp) {
|
||||
byte *line1P = (byte *)_rawSurface->getBasePtr(0, yp);
|
||||
byte *line2P = (byte *)_rawSurface->getBasePtr(0, _rawSurface->h - yp - 1);
|
||||
|
||||
Common::copy(line1P, line1P + pitch, lineBuffer);
|
||||
Common::copy(line2P, line2P + pitch, line1P);
|
||||
Common::copy(lineBuffer, lineBuffer + pitch, line1P);
|
||||
}
|
||||
|
||||
_flipVertically = false;
|
||||
if (needsLock)
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool OSVideoSurface::loadIfReady() {
|
||||
_videoSurfaceNum = _videoSurfaceCounter;
|
||||
|
||||
if (hasSurface()) {
|
||||
return true;
|
||||
} else if (_pendingLoad) {
|
||||
_hasFrame = true;
|
||||
load();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void OSVideoSurface::transPixelate() {
|
||||
if (!loadIfReady())
|
||||
return;
|
||||
|
||||
lock();
|
||||
Graphics::ManagedSurface *surface = _rawSurface;
|
||||
uint transColor = getTransparencyColor();
|
||||
// TODO: Check whether color is correct
|
||||
uint pixelColor = surface->format.RGBToColor(0x50, 0, 0);
|
||||
|
||||
for (int yp = 0; yp < surface->h; ++yp) {
|
||||
uint16 *pixelsP = (uint16 *)surface->getBasePtr(0, yp);
|
||||
bool bitFlag = (yp % 2) == 0;
|
||||
int replaceCtr = yp & 3;
|
||||
|
||||
for (int xp = 0; xp < surface->w; ++xp, ++pixelsP) {
|
||||
if (bitFlag && *pixelsP == transColor && replaceCtr == 0)
|
||||
*pixelsP = pixelColor;
|
||||
|
||||
bitFlag = !bitFlag;
|
||||
replaceCtr = (replaceCtr + 1) & 3;
|
||||
}
|
||||
}
|
||||
|
||||
surface->markAllDirty();
|
||||
unlock();
|
||||
}
|
||||
|
||||
Graphics::ManagedSurface *OSVideoSurface::dupMovieTransparency() const {
|
||||
return _movie ? _movie->duplicateTransparency() : nullptr;
|
||||
}
|
||||
|
||||
int OSVideoSurface::freeSurface() {
|
||||
if (!_ddSurface)
|
||||
return 0;
|
||||
int surfaceSize = _ddSurface->getSize();
|
||||
|
||||
delete _movie;
|
||||
_movie = nullptr;
|
||||
delete _ddSurface;
|
||||
_ddSurface = nullptr;
|
||||
|
||||
return surfaceSize;
|
||||
}
|
||||
|
||||
uint16 *OSVideoSurface::getBasePtr(int x, int y) {
|
||||
assert(_rawSurface);
|
||||
return (uint16 *)_rawSurface->getBasePtr(x, y);
|
||||
}
|
||||
|
||||
} // End of namespace Titanic
|
||||
Reference in New Issue
Block a user