diff options
Diffstat (limited to 'engines/sword25/gfx/graphicengine.cpp')
-rw-r--r-- | engines/sword25/gfx/graphicengine.cpp | 395 |
1 files changed, 189 insertions, 206 deletions
diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp index ea0c8c82c5..44b9932de1 100644 --- a/engines/sword25/gfx/graphicengine.cpp +++ b/engines/sword25/gfx/graphicengine.cpp @@ -52,108 +52,90 @@ #include "sword25/gfx/graphicengine.h" -namespace Lua { -extern "C" -{ #include "sword25/util/lua/lua.h" #include "sword25/util/lua/lauxlib.h" -} -} - -namespace { -const int BIT_DEPTH = 32; -const int BACKBUFFER_COUNT = 1; -const Common::String PNG_EXTENSION(".png"); -const Common::String PNG_S_EXTENSION("_s.png"); -const Common::String ANI_EXTENSION("_ani.xml"); -const Common::String FNT_EXTENSION("_fnt.xml"); -const Common::String SWF_EXTENSION(".swf"); -const Common::String B25S_EXTENSION(".b25s"); -} +enum { + BIT_DEPTH = 32, + BACKBUFFER_COUNT = 1 +}; namespace Sword25 { -using namespace Lua; - static const uint FRAMETIME_SAMPLE_COUNT = 5; // Anzahl der Framezeiten über die, die Framezeit gemittelt wird GraphicEngine::GraphicEngine(Kernel *pKernel) : - m_Width(0), - m_Height(0), - m_BitDepth(0), - m_Windowed(0), - m_LastTimeStamp((uint64) - 1), // max. BS_INT64 um beim ersten Aufruf von _UpdateLastFrameDuration() einen Reset zu erzwingen - m_LastFrameDuration(0), - m_TimerActive(true), - m_FrameTimeSampleSlot(0), - m_RepaintedPixels(0), + _width(0), + _height(0), + _bitDepth(0), + _windowed(0), + _lastTimeStamp((uint) -1), // max. BS_INT64 um beim ersten Aufruf von _UpdateLastFrameDuration() einen Reset zu erzwingen + _lastFrameDuration(0), + _timerActive(true), + _frameTimeSampleSlot(0), + _repaintedPixels(0), _thumbnail(NULL), ResourceService(pKernel) { - m_FrameTimeSamples.resize(FRAMETIME_SAMPLE_COUNT); + _frameTimeSamples.resize(FRAMETIME_SAMPLE_COUNT); - if (!RegisterScriptBindings()) + if (!registerScriptBindings()) BS_LOG_ERRORLN("Script bindings could not be registered."); else BS_LOGLN("Script bindings registered."); } GraphicEngine::~GraphicEngine() { + unregisterScriptBindings(); _backSurface.free(); _frameBuffer.free(); delete _thumbnail; } -Service *GraphicEngine_CreateObject(Kernel *pKernel) { - return new GraphicEngine(pKernel); -} - -bool GraphicEngine::Init(int Width, int Height, int BitDepth, int BackbufferCount, bool Windowed) { +bool GraphicEngine::init(int width, int height, int bitDepth, int backbufferCount, bool isWindowed_) { // Warnung ausgeben, wenn eine nicht unterstützte Bittiefe gewählt wurde. - if (BitDepth != BIT_DEPTH) { - BS_LOG_WARNINGLN("Can't use a bit depth of %d (not supported). Falling back to %d.", BitDepth, BIT_DEPTH); - m_BitDepth = BIT_DEPTH; + if (bitDepth != BIT_DEPTH) { + BS_LOG_WARNINGLN("Can't use a bit depth of %d (not supported). Falling back to %d.", bitDepth, BIT_DEPTH); + _bitDepth = BIT_DEPTH; } // Warnung ausgeben, wenn nicht genau ein Backbuffer gewählt wurde. - if (BackbufferCount != BACKBUFFER_COUNT) { - BS_LOG_WARNINGLN("Can't use %d backbuffers (not supported). Falling back to %d.", BackbufferCount, BACKBUFFER_COUNT); - BackbufferCount = BACKBUFFER_COUNT; + if (backbufferCount != BACKBUFFER_COUNT) { + BS_LOG_WARNINGLN("Can't use %d backbuffers (not supported). Falling back to %d.", backbufferCount, BACKBUFFER_COUNT); + backbufferCount = BACKBUFFER_COUNT; } // Parameter in lokale Variablen kopieren - m_Width = Width; - m_Height = Height; - m_BitDepth = BitDepth; - m_Windowed = Windowed; - m_ScreenRect.left = 0; - m_ScreenRect.top = 0; - m_ScreenRect.right = m_Width; - m_ScreenRect.bottom = m_Height; - - _backSurface.create(Width, Height, 4); - _frameBuffer.create(Width, Height, 4); + _width = width; + _height = height; + _bitDepth = bitDepth; + _windowed = isWindowed_; + _screenRect.left = 0; + _screenRect.top = 0; + _screenRect.right = _width; + _screenRect.bottom = _height; + + _backSurface.create(width, height, 4); + _frameBuffer.create(width, height, 4); // Standardmäßig ist Vsync an. - SetVsync(true); + setVsync(true); // Layer-Manager initialisieren. - _renderObjectManagerPtr.reset(new RenderObjectManager(Width, Height, BackbufferCount + 1)); + _renderObjectManagerPtr.reset(new RenderObjectManager(width, height, backbufferCount + 1)); // Hauptpanel erstellen - m_MainPanelPtr = _renderObjectManagerPtr->getTreeRoot()->addPanel(Width, Height, BS_ARGB(0, 0, 0, 0)); - if (!m_MainPanelPtr.isValid()) return false; - m_MainPanelPtr->setVisible(true); + _mainPanelPtr = _renderObjectManagerPtr->getTreeRoot()->addPanel(width, height, BS_ARGB(0, 0, 0, 0)); + if (!_mainPanelPtr.isValid()) + return false; + _mainPanelPtr->setVisible(true); return true; } -// ----------------------------------------------------------------------------- - -bool GraphicEngine::StartFrame(bool UpdateAll) { +bool GraphicEngine::startFrame(bool updateAll) { // Berechnen, wie viel Zeit seit dem letzten Frame vergangen ist. // Dieser Wert kann über GetLastFrameDuration() von Modulen abgefragt werden, die zeitabhängig arbeiten. - UpdateLastFrameDuration(); + updateLastFrameDuration(); // Den Layer-Manager auf den nächsten Frame vorbereiten _renderObjectManagerPtr->startFrame(); @@ -161,9 +143,7 @@ bool GraphicEngine::StartFrame(bool UpdateAll) { return true; } -// ----------------------------------------------------------------------------- - -bool GraphicEngine::EndFrame() { +bool GraphicEngine::endFrame() { // Scene zeichnen _renderObjectManagerPtr->render(); @@ -179,7 +159,7 @@ bool GraphicEngine::EndFrame() { g_system->updateScreen(); // Debug-Lines zeichnen - if (!m_DebugLines.empty()) { + if (!_debugLines.empty()) { #if 0 glEnable(GL_LINE_SMOOTH); glBegin(GL_LINES); @@ -201,55 +181,76 @@ bool GraphicEngine::EndFrame() { warning("STUB: Drawing debug lines"); - m_DebugLines.clear(); + _debugLines.clear(); } // Framecounter aktualisieren - m_FPSCounter.Update(); + _FPSCounter.update(); return true; } -// ----------------------------------------------------------------------------- - -RenderObjectPtr<Panel> GraphicEngine::GetMainPanel() { - return m_MainPanelPtr; +RenderObjectPtr<Panel> GraphicEngine::getMainPanel() { + return _mainPanelPtr; } -// ----------------------------------------------------------------------------- - -void GraphicEngine::SetVsync(bool Vsync) { - warning("STUB: SetVsync(%d)", Vsync); +void GraphicEngine::setVsync(bool vsync) { + warning("STUB: SetVsync(%d)", vsync); } -// ----------------------------------------------------------------------------- - -bool GraphicEngine::GetVsync() const { - warning("STUB: GetVsync()"); +bool GraphicEngine::getVsync() const { + warning("STUB: getVsync()"); return true; } -// ----------------------------------------------------------------------------- - bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) { - Common::Rect rect(m_Width - 1, m_Height - 1); + Common::Rect rect(_width - 1, _height - 1); + + int ca = (color >> 24) & 0xff; + + if (ca == 0) + return true; + + int cr = (color >> 16) & 0xff; + int cg = (color >> 8) & 0xff; + int cb = (color >> 0) & 0xff; if (fillRectPtr) { rect = *fillRectPtr; } - if (fillRectPtr->width() > 0 && fillRectPtr->height() > 0) { - _backSurface.fillRect(rect, color); - g_system->copyRectToScreen((byte *)_backSurface.getBasePtr(fillRectPtr->left, fillRectPtr->top), _backSurface.pitch, fillRectPtr->left, fillRectPtr->top, fillRectPtr->width(), fillRectPtr->height()); + if (rect.width() > 0 && rect.height() > 0) { + if (ca == 0xff) { + _backSurface.fillRect(rect, color); + } else { + byte *outo = (byte *)_backSurface.getBasePtr(rect.left, rect.top); + byte *out; + + for (int i = rect.top; i < rect.bottom; i++) { + out = outo; + for (int j = rect.left; j < rect.right; j++) { + *out += (byte)(((cb - *out) * ca) >> 8); + out++; + *out += (byte)(((cg - *out) * ca) >> 8); + out++; + *out += (byte)(((cr - *out) * ca) >> 8); + out++; + *out = 255; + out++; + } + + outo += _backSurface.pitch; + } + } + + g_system->copyRectToScreen((byte *)_backSurface.getBasePtr(rect.left, rect.top), _backSurface.pitch, rect.left, rect.top, rect.width(), rect.height()); } return true; } -// ----------------------------------------------------------------------------- - -Graphics::Surface *GraphicEngine::GetScreenshot() { +Graphics::Surface *GraphicEngine::getScreenshot() { return &_frameBuffer; } @@ -257,19 +258,19 @@ Graphics::Surface *GraphicEngine::GetScreenshot() { // RESOURCE MANAGING // ----------------------------------------------------------------------------- -Resource *GraphicEngine::loadResource(const Common::String &FileName) { - BS_ASSERT(canLoadResource(FileName)); +Resource *GraphicEngine::loadResource(const Common::String &filename) { + BS_ASSERT(canLoadResource(filename)); - // Bild für den Softwarebuffer laden - if (FileName.hasSuffix(PNG_S_EXTENSION)) { - bool Result = false; - SWImage *pImage = new SWImage(FileName, Result); - if (!Result) { + // Load image for "software buffer" (FIXME: Whatever that means?) + if (filename.hasSuffix("_s.png")) { + bool result = false; + SWImage *pImage = new SWImage(filename, result); + if (!result) { delete pImage; return 0; } - BitmapResource *pResource = new BitmapResource(FileName, pImage); + BitmapResource *pResource = new BitmapResource(filename, pImage); if (!pResource->isValid()) { delete pResource; return 0; @@ -278,16 +279,16 @@ Resource *GraphicEngine::loadResource(const Common::String &FileName) { return pResource; } - // Sprite-Bild laden - if (FileName.hasSuffix(PNG_EXTENSION) || FileName.hasSuffix(B25S_EXTENSION)) { - bool Result = false; - RenderedImage *pImage = new RenderedImage(FileName, Result); - if (!Result) { + // Load sprite image + if (filename.hasSuffix(".png") || filename.hasSuffix(".b25s")) { + bool result = false; + RenderedImage *pImage = new RenderedImage(filename, result); + if (!result) { delete pImage; return 0; } - BitmapResource *pResource = new BitmapResource(FileName, pImage); + BitmapResource *pResource = new BitmapResource(filename, pImage); if (!pResource->isValid()) { delete pResource; return 0; @@ -297,31 +298,32 @@ Resource *GraphicEngine::loadResource(const Common::String &FileName) { } - // Vectorgraphik laden - if (FileName.hasSuffix(SWF_EXTENSION)) { - debug(2, "VectorImage: %s", FileName.c_str()); + // Load vector graphics + if (filename.hasSuffix(".swf")) { + debug(2, "VectorImage: %s", filename.c_str()); // Pointer auf Package-Manager holen - PackageManager *pPackage = Kernel::GetInstance()->GetPackage(); + PackageManager *pPackage = Kernel::getInstance()->getPackage(); BS_ASSERT(pPackage); // Datei laden byte *pFileData; - uint FileSize; - if (!(pFileData = static_cast<byte *>(pPackage->getFile(FileName, &FileSize)))) { - BS_LOG_ERRORLN("File \"%s\" could not be loaded.", FileName.c_str()); + uint fileSize; + pFileData = pPackage->getFile(filename, &fileSize); + if (!pFileData) { + BS_LOG_ERRORLN("File \"%s\" could not be loaded.", filename.c_str()); return 0; } - bool Result = false; - VectorImage *pImage = new VectorImage(pFileData, FileSize, Result, FileName); - if (!Result) { + bool result = false; + VectorImage *pImage = new VectorImage(pFileData, fileSize, result, filename); + if (!result) { delete pImage; - delete [] pFileData; + delete[] pFileData; return 0; } - BitmapResource *pResource = new BitmapResource(FileName, pImage); + BitmapResource *pResource = new BitmapResource(filename, pImage); if (!pResource->isValid()) { delete pResource; delete[] pFileData; @@ -332,9 +334,9 @@ Resource *GraphicEngine::loadResource(const Common::String &FileName) { return pResource; } - // Animation laden - if (FileName.hasSuffix(ANI_EXTENSION)) { - AnimationResource *pResource = new AnimationResource(FileName); + // Load animation + if (filename.hasSuffix("_ani.xml")) { + AnimationResource *pResource = new AnimationResource(filename); if (pResource->isValid()) return pResource; else { @@ -343,10 +345,10 @@ Resource *GraphicEngine::loadResource(const Common::String &FileName) { } } - // Font laden - if (FileName.hasSuffix(FNT_EXTENSION)) { - FontResource *pResource = new FontResource(Kernel::GetInstance(), FileName); - if (pResource->IsValid()) + // Load font + if (filename.hasSuffix("_fnt.xml")) { + FontResource *pResource = new FontResource(Kernel::getInstance(), filename); + if (pResource->isValid()) return pResource; else { delete pResource; @@ -354,18 +356,18 @@ Resource *GraphicEngine::loadResource(const Common::String &FileName) { } } - BS_LOG_ERRORLN("Service cannot load \"%s\".", FileName.c_str()); + BS_LOG_ERRORLN("Service cannot load \"%s\".", filename.c_str()); return 0; } // ----------------------------------------------------------------------------- -bool GraphicEngine::canLoadResource(const Common::String &FileName) { - return FileName.hasSuffix(PNG_EXTENSION) || - FileName.hasSuffix(ANI_EXTENSION) || - FileName.hasSuffix(FNT_EXTENSION) || - FileName.hasSuffix(SWF_EXTENSION) || - FileName.hasSuffix(B25S_EXTENSION); +bool GraphicEngine::canLoadResource(const Common::String &filename) { + return filename.hasSuffix(".png") || + filename.hasSuffix("_ani.xml") || + filename.hasSuffix("_fnt.xml") || + filename.hasSuffix(".swf") || + filename.hasSuffix(".b25s"); } @@ -373,57 +375,33 @@ bool GraphicEngine::canLoadResource(const Common::String &FileName) { // DEBUGGING // ----------------------------------------------------------------------------- -void GraphicEngine::DrawDebugLine(const Vertex &Start, const Vertex &End, uint Color) { - m_DebugLines.push_back(DebugLine(Start, End, Color)); +void GraphicEngine::drawDebugLine(const Vertex &start, const Vertex &end, uint color) { + _debugLines.push_back(DebugLine(start, end, color)); } -void GraphicEngine::UpdateLastFrameDuration() { - // Aktuelle Zeit holen - uint64_t CurrentTime = Kernel::GetInstance()->GetMicroTicks(); - - // Verstrichene Zeit seit letztem Frame berechnen und zu große Zeitsprünge ( > 250 msek.) unterbinden - // (kann vorkommen bei geladenen Spielständen, während des Debuggings oder Hardwareungenauigkeiten) - m_FrameTimeSamples[m_FrameTimeSampleSlot] = static_cast<uint>(CurrentTime - m_LastTimeStamp); - if (m_FrameTimeSamples[m_FrameTimeSampleSlot] > 250000) m_FrameTimeSamples[m_FrameTimeSampleSlot] = 250000; - m_FrameTimeSampleSlot = (m_FrameTimeSampleSlot + 1) % FRAMETIME_SAMPLE_COUNT; - - // Die Framezeit wird über mehrere Frames gemittelt um Ausreisser zu eliminieren - Common::Array<uint>::const_iterator it = m_FrameTimeSamples.begin(); - uint Sum = *it; - for (it++; it != m_FrameTimeSamples.end(); it++) Sum += *it; - m_LastFrameDuration = Sum / FRAMETIME_SAMPLE_COUNT; - - // _LastTimeStamp auf die Zeit des aktuellen Frames setzen - m_LastTimeStamp = CurrentTime; +void GraphicEngine::updateLastFrameDuration() { + // Record current time + const uint currentTime = Kernel::getInstance()->getMilliTicks(); + + // Compute the elapsed time since the last frame and prevent too big ( > 250 msecs) time jumps. + // These can occur when loading save states, during debugging or due to hardware inaccuracies. + _frameTimeSamples[_frameTimeSampleSlot] = static_cast<uint>(currentTime - _lastTimeStamp); + if (_frameTimeSamples[_frameTimeSampleSlot] > 250000) + _frameTimeSamples[_frameTimeSampleSlot] = 250000; + _frameTimeSampleSlot = (_frameTimeSampleSlot + 1) % FRAMETIME_SAMPLE_COUNT; + + // Compute the average frame duration over multiple frames to eliminate outliers. + Common::Array<uint>::const_iterator it = _frameTimeSamples.begin(); + uint sum = *it; + for (it++; it != _frameTimeSamples.end(); it++) + sum += *it; + _lastFrameDuration = sum * 1000 / FRAMETIME_SAMPLE_COUNT; + + // Update m_LastTimeStamp with the current frame's timestamp + _lastTimeStamp = currentTime; } -namespace { -bool DoSaveScreenshot(GraphicEngine &GraphicEngine, const Common::String &Filename) { - Graphics::Surface *data = GraphicEngine.GetScreenshot(); - if (!data) { - BS_LOG_ERRORLN("Call to GetScreenshot() failed. Cannot save screenshot."); - return false; - } - - Common::FSNode f(Filename); - Common::WriteStream *stream = f.createWriteStream(); - if (!stream) { - BS_LOG_ERRORLN("Call to GetScreenshot() failed. Cannot save screenshot."); - return false; - } - - bool result = Screenshot::SaveToFile(data, stream); - delete stream; - - return result; -} -} - -bool GraphicEngine::SaveScreenshot(const Common::String &Filename) { - return DoSaveScreenshot(*this, Filename); -} - -bool GraphicEngine::SaveThumbnailScreenshot(const Common::String &Filename) { +bool GraphicEngine::saveThumbnailScreenshot(const Common::String &filename) { // Note: In ScumMVM, rather than saivng the thumbnail to a file, we store it in memory // until needed when creating savegame files delete _thumbnail; @@ -431,59 +409,64 @@ bool GraphicEngine::SaveThumbnailScreenshot(const Common::String &Filename) { return true; } -void GraphicEngine::ARGBColorToLuaColor(lua_State *L, uint Color) { - lua_Number Components[4] = { - (Color >> 16) & 0xff, // Rot - (Color >> 8) & 0xff, // Grün - Color & 0xff, // Blau - Color >> 24, // Alpha +void GraphicEngine::ARGBColorToLuaColor(lua_State *L, uint color) { + lua_Number components[4] = { + (color >> 16) & 0xff, // Rot + (color >> 8) & 0xff, // Grün + color & 0xff, // Blau + color >> 24, // Alpha }; lua_newtable(L); for (uint i = 1; i <= 4; i++) { lua_pushnumber(L, i); - lua_pushnumber(L, Components[i - 1]); + lua_pushnumber(L, components[i - 1]); lua_settable(L, -3); } } -uint GraphicEngine::LuaColorToARGBColor(lua_State *L, int StackIndex) { +uint GraphicEngine::luaColorToARGBColor(lua_State *L, int stackIndex) { #ifdef DEBUG int __startStackDepth = lua_gettop(L); #endif // Sicherstellen, dass wir wirklich eine Tabelle betrachten - luaL_checktype(L, StackIndex, LUA_TTABLE); + luaL_checktype(L, stackIndex, LUA_TTABLE); // Größe der Tabelle auslesen - uint n = luaL_getn(L, StackIndex); + uint n = luaL_getn(L, stackIndex); // RGB oder RGBA Farben werden unterstützt und sonst keine - if (n != 3 && n != 4) luaL_argcheck(L, 0, StackIndex, "at least 3 of the 4 color components have to be specified"); - - // Rote Farbkomponente auslesen - lua_rawgeti(L, StackIndex, 1); - uint Red = static_cast<uint>(lua_tonumber(L, -1)); - if (!lua_isnumber(L, -1) || Red >= 256) luaL_argcheck(L, 0, StackIndex, "red color component must be an integer between 0 and 255"); + if (n != 3 && n != 4) + luaL_argcheck(L, 0, stackIndex, "at least 3 of the 4 color components have to be specified"); + + // Red color component reading + lua_rawgeti(L, stackIndex, 1); + uint red = static_cast<uint>(lua_tonumber(L, -1)); + if (!lua_isnumber(L, -1) || red >= 256) + luaL_argcheck(L, 0, stackIndex, "red color component must be an integer between 0 and 255"); lua_pop(L, 1); - // Grüne Farbkomponente auslesen - lua_rawgeti(L, StackIndex, 2); - uint Green = static_cast<uint>(lua_tonumber(L, -1)); - if (!lua_isnumber(L, -1) || Green >= 256) luaL_argcheck(L, 0, StackIndex, "green color component must be an integer between 0 and 255"); + // Green color component reading + lua_rawgeti(L, stackIndex, 2); + uint green = static_cast<uint>(lua_tonumber(L, -1)); + if (!lua_isnumber(L, -1) || green >= 256) + luaL_argcheck(L, 0, stackIndex, "green color component must be an integer between 0 and 255"); lua_pop(L, 1); - // Blaue Farbkomponente auslesen - lua_rawgeti(L, StackIndex, 3); - uint Blue = static_cast<uint>(lua_tonumber(L, -1)); - if (!lua_isnumber(L, -1) || Blue >= 256) luaL_argcheck(L, 0, StackIndex, "blue color component must be an integer between 0 and 255"); + // Blue color component reading + lua_rawgeti(L, stackIndex, 3); + uint blue = static_cast<uint>(lua_tonumber(L, -1)); + if (!lua_isnumber(L, -1) || blue >= 256) + luaL_argcheck(L, 0, stackIndex, "blue color component must be an integer between 0 and 255"); lua_pop(L, 1); - // Alpha Farbkomponente auslesen - uint Alpha = 0xff; + // Alpha color component reading + uint alpha = 0xff; if (n == 4) { - lua_rawgeti(L, StackIndex, 4); - Alpha = static_cast<uint>(lua_tonumber(L, -1)); - if (!lua_isnumber(L, -1) || Alpha >= 256) luaL_argcheck(L, 0, StackIndex, "alpha color component must be an integer between 0 and 255"); + lua_rawgeti(L, stackIndex, 4); + alpha = static_cast<uint>(lua_tonumber(L, -1)); + if (!lua_isnumber(L, -1) || alpha >= 256) + luaL_argcheck(L, 0, stackIndex, "alpha color component must be an integer between 0 and 255"); lua_pop(L, 1); } @@ -491,11 +474,11 @@ uint GraphicEngine::LuaColorToARGBColor(lua_State *L, int StackIndex) { BS_ASSERT(__startStackDepth == lua_gettop(L)); #endif - return (Alpha << 24) | (Red << 16) | (Green << 8) | Blue; + return (alpha << 24) | (red << 16) | (green << 8) | blue; } bool GraphicEngine::persist(OutputPersistenceBlock &writer) { - writer.write(m_TimerActive); + writer.write(_timerActive); bool result = _renderObjectManagerPtr->persist(writer); @@ -503,7 +486,7 @@ bool GraphicEngine::persist(OutputPersistenceBlock &writer) { } bool GraphicEngine::unpersist(InputPersistenceBlock &reader) { - reader.read(m_TimerActive); + reader.read(_timerActive); _renderObjectManagerPtr->unpersist(reader); return reader.isGood(); |