diff options
author | Eugene Sandulenko | 2010-07-29 19:53:02 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 21:38:20 +0000 |
commit | a683a420a9e43705c972b5e74d55e319729e1a81 (patch) | |
tree | bde6e4abd417bdfaec120aa951da9a19be36b654 /engines/sword25/gfx/opengl | |
parent | 7723d91c957d07205c51be32498d45cd0a78568f (diff) | |
download | scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.gz scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.bz2 scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.zip |
SWORD25: Importing original sources
svn-id: r53171
Diffstat (limited to 'engines/sword25/gfx/opengl')
-rwxr-xr-x | engines/sword25/gfx/opengl/glimage.cpp | 208 | ||||
-rwxr-xr-x | engines/sword25/gfx/opengl/glimage.h | 85 | ||||
-rwxr-xr-x | engines/sword25/gfx/opengl/glvectorimageblit.cpp | 133 | ||||
-rwxr-xr-x | engines/sword25/gfx/opengl/openglgfx.cpp | 505 | ||||
-rwxr-xr-x | engines/sword25/gfx/opengl/openglgfx.h | 114 | ||||
-rwxr-xr-x | engines/sword25/gfx/opengl/swimage.cpp | 125 | ||||
-rwxr-xr-x | engines/sword25/gfx/opengl/swimage.h | 69 |
7 files changed, 1239 insertions, 0 deletions
diff --git a/engines/sword25/gfx/opengl/glimage.cpp b/engines/sword25/gfx/opengl/glimage.cpp new file mode 100755 index 0000000000..1f5322516b --- /dev/null +++ b/engines/sword25/gfx/opengl/glimage.cpp @@ -0,0 +1,208 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#include "util/glsprites/glsprites.h" +#include "package/packagemanager.h" +#include "gfx/image/imageloader.h" +#include "openglgfx.h" +#include "glimage.h" + +#define BS_LOG_PREFIX "GLIMAGE" + +// ----------------------------------------------------------------------------- +// CONSTRUCTION / DESTRUCTION +// ----------------------------------------------------------------------------- + +BS_GLImage::BS_GLImage(const std::string & Filename, bool & Result) : + m_Sprite(0), + m_Width(0), + m_Height(0) +{ + Result = false; + + BS_PackageManager * pPackage = static_cast<BS_PackageManager*>(BS_Kernel::GetInstance()->GetService("package")); + BS_ASSERT(pPackage); + + // Datei laden + char* pFileData; + unsigned int FileSize; + if (!(pFileData = (char*) pPackage->GetFile(Filename, &FileSize))) + { + BS_LOG_ERRORLN("File \"%s\" could not be loaded.", Filename.c_str()); + return; + } + + // Bildeigenschaften bestimmen + BS_GraphicEngine::COLOR_FORMATS ColorFormat; + int Pitch; + if (!BS_ImageLoader::ExtractImageProperties(pFileData, FileSize, ColorFormat, m_Width, m_Height)) + { + BS_LOG_ERRORLN("Could not read image properties."); + return; + } + + // Das Bild dekomprimieren + char * pUncompressedData; + if (!BS_ImageLoader::LoadImage(pFileData, FileSize, BS_GraphicEngine::CF_ABGR32, pUncompressedData, m_Width, m_Height, Pitch)) + { + BS_LOG_ERRORLN("Could not decode image."); + return; + } + + // Dateidaten freigeben + delete[] pFileData; + + // GLS-Sprite mit den Bilddaten erstellen + GLS_Result GLSResult = GLS_NewSprite(m_Width, m_Height, + (ColorFormat == BS_GraphicEngine::CF_ARGB32) ? GLS_True : GLS_False, + pUncompressedData, + &m_Sprite); + if (Result != GLS_OK) + { + BS_LOG_ERRORLN("Could not create GLS_Sprite. Reason: %s", GLS_ResultString(GLSResult)); + return; + } + + // Bilddaten freigeben + delete[] pUncompressedData; + + Result = true; + return; +} + +// ----------------------------------------------------------------------------- + +BS_GLImage::BS_GLImage(unsigned int Width, unsigned int Height, bool & Result) : + m_Sprite(0), + m_Width(Width), + m_Height(Height) +{ + Result = false; + + // GLS-Sprite mit den Bilddaten erstellen + GLS_Result GLSResult = GLS_NewSprite(m_Width, m_Height, + GLS_True, + 0, + &m_Sprite); + if (GLSResult != GLS_OK) + { + BS_LOG_ERRORLN("Could not create GLS_Sprite. Reason: %s", GLS_ResultString(GLSResult)); + return; + } + + Result = true; + return; +} + +// ----------------------------------------------------------------------------- + +BS_GLImage::~BS_GLImage() +{ + if (m_Sprite) GLS_DeleteSprite(m_Sprite); +} + +// ----------------------------------------------------------------------------- + +bool BS_GLImage::Fill(const BS_Rect* pFillRect, unsigned int Color) +{ + BS_LOG_ERRORLN("Fill() is not supported."); + return false; +} + +// ----------------------------------------------------------------------------- + +bool BS_GLImage::SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset, unsigned int Stride) +{ + // Überprüfen, ob PixelData ausreichend viele Pixel enthält um ein Bild der Größe Width * Height zu erzeugen + if (Pixeldata.size() < static_cast<unsigned int>(m_Width * m_Height * 4)) + { + BS_LOG_ERRORLN("PixelData vector is too small to define a 32 bit %dx%d image.", m_Width, m_Height); + return false; + } + + // GLS-Sprite mit den Bilddaten füllen + GLS_Result GLSResult = GLS_SetSpriteData(m_Sprite, m_Width, m_Height, &Pixeldata[Offset], Stride / 4); + if (GLSResult != GLS_OK) + { + BS_LOG_ERRORLN("CGLS_SetSpriteData() failed. Reason: %s", GLS_ResultString(GLSResult)); + return false; + } + + return true; +} + +// ----------------------------------------------------------------------------- + +unsigned int BS_GLImage::GetPixel(int X, int Y) +{ + BS_LOG_ERRORLN("GetPixel() is not supported. Returning black."); + return 0; +} + +// ----------------------------------------------------------------------------- + +bool BS_GLImage::Blit(int PosX, int PosY, + int Flipping, + BS_Rect* pPartRect, + unsigned int Color, + int Width, int Height) +{ + // BS_Rect nach GLS_Rect konvertieren + GLS_Rect SubImage; + if (pPartRect) + { + SubImage.x1 = pPartRect->left; + SubImage.y1 = pPartRect->top; + SubImage.x2 = pPartRect->right; + SubImage.y2 = pPartRect->bottom; + } + + // Farbe nach GLS_Color konvertieren + GLS_Color GLSColor; + GLSColor.a = Color >> 24; + GLSColor.r = (Color >> 16) & 0xff; + GLSColor.g = (Color >> 8) & 0xff; + GLSColor.b = Color & 0xff; + + // Skalierungen berechnen + GLS_Float ScaleX, ScaleY; + if (Width == -1) Width = m_Width; + ScaleX = (GLS_Float) Width / (GLS_Float) m_Width; + + if (Height == -1) Height = m_Height; + ScaleY = (GLS_Float) Height / (GLS_Float) m_Height; + + // Rendern + // TODO: + // Die Bedeutung von FLIP_V und FLIP_H ist vertauscht. Allerdings glaubt der Rest der Engine auch daran, daher war es einfacher diesen Fehler + // weiterzuführen. Bei Gelegenheit ist dieses aber zu ändern. + GLS_Result Result = GLS_Blit(m_Sprite, + PosX, PosY, + pPartRect ? &SubImage : 0, &GLSColor, + (Flipping & BS_Image::FLIP_V) ? GLS_True : GLS_False, + (Flipping & BS_Image::FLIP_H) ? GLS_True : GLS_False, + ScaleX, ScaleY); + if (Result != GLS_OK) BS_LOG_ERRORLN("GLS_Blit() failed. Reason: %s", GLS_ResultString(Result)); + + return Result == GLS_OK; +} diff --git a/engines/sword25/gfx/opengl/glimage.h b/engines/sword25/gfx/opengl/glimage.h new file mode 100755 index 0000000000..d9c81dc4a5 --- /dev/null +++ b/engines/sword25/gfx/opengl/glimage.h @@ -0,0 +1,85 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +#ifndef BS_GL_IMAGE_H +#define BS_GL_IMAGE_H + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#include "kernel/common.h" +#include "gfx/image/image.h" +#include "gfx/graphicengine.h" + +#include <vector> + +// ----------------------------------------------------------------------------- +// FORWARD DECLARATION +// ----------------------------------------------------------------------------- + +typedef void * GLS_Sprite; + +// ----------------------------------------------------------------------------- +// CLASS DEFINITION +// ----------------------------------------------------------------------------- + +class BS_GLImage : public BS_Image +{ +public: + BS_GLImage(const std::string & Filename, bool & Result); + + /** + @brief Erzeugt ein leeres BS_GLImage + + @param Width die Breite des zu erzeugenden Bildes. + @param Height die Höhe des zu erzeugenden Bildes + @param Result gibt dem Aufrufer bekannt, ob der Konstruktor erfolgreich ausgeführt wurde. Wenn es nach dem Aufruf false enthalten sollte, + dürfen keine Methoden am Objekt aufgerufen werden und das Objekt ist sofort zu zerstören. + */ + BS_GLImage(unsigned int Width, unsigned int Height, bool & Result); + virtual ~BS_GLImage(); + + virtual int GetWidth() const { return m_Width; } + virtual int GetHeight() const { return m_Height; } + virtual BS_GraphicEngine::COLOR_FORMATS GetColorFormat() const { return BS_GraphicEngine::CF_ARGB32; } + + virtual bool Blit(int PosX = 0, int PosY = 0, + int Flipping = BS_Image::FLIP_NONE, + BS_Rect* pPartRect = NULL, + unsigned int Color = BS_ARGB(255, 255, 255, 255), + int Width = -1, int Height = -1); + virtual bool Fill(const BS_Rect* pFillRect, unsigned int Color); + virtual bool SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset = 0, unsigned int Stride = 0); + virtual unsigned int GetPixel(int X, int Y); + + virtual bool IsBlitSource() const { return true; } + virtual bool IsBlitTarget() const { return false; } + virtual bool IsScalingAllowed() const { return true; } + virtual bool IsFillingAllowed() const { return false; } + virtual bool IsAlphaAllowed() const { return true; } + virtual bool IsColorModulationAllowed() const { return true; } + virtual bool IsSetContentAllowed() const { return true; } +private: + GLS_Sprite m_Sprite; + int m_Width; + int m_Height; +}; + +#endif diff --git a/engines/sword25/gfx/opengl/glvectorimageblit.cpp b/engines/sword25/gfx/opengl/glvectorimageblit.cpp new file mode 100755 index 0000000000..38cfd9fa85 --- /dev/null +++ b/engines/sword25/gfx/opengl/glvectorimageblit.cpp @@ -0,0 +1,133 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// Includes +// ----------------------------------------------------------------------------- + +#include "gfx/image/vectorimage.h" +#include "gfx/image/vectorimagerenderer.h" +#include "util/glsprites/glsprites.h" + +#include <vector> +using namespace std; + +#define BS_LOG_PREFIX "GLVECTORIMAGEBLIT" + +// ----------------------------------------------------------------------------- + +namespace +{ + const float LINE_SCALE_FACTOR = 1.0f; +} + +// ----------------------------------------------------------------------------- + +bool BS_VectorImage::Blit(int PosX, int PosY, + int Flipping, + BS_Rect* pPartRect, + unsigned int Color, + int Width, int Height) +{ + static BS_VectorImageRenderer VectorImageRenderer; + static vector<char> PixelData; + static GLS_Sprite Sprite = 0; + static BS_VectorImage * OldThis = 0; + static int OldWidth; + static int OldHeight; + static GLS_Rect OldSubImage; + + // Falls Breite oder Höhe 0 sind, muss nichts dargestellt werden. + if (Width == 0 || Height == 0) return true; + + // Sprite erstellen, falls es noch nicht erstellt wurde + if (Sprite == 0) + { + GLS_Result Result = GLS_NewSprite(512, 512, GLS_True, 0, &Sprite); + if (Result != GLS_OK) + { + BS_LOG_ERRORLN("Could not create GLS_Sprite. Reason: %s", GLS_ResultString(Result)); + return false; + } + } + + // Feststellen, ob das alte Bild im Cache nicht wiederbenutzt werden kann und neu Berechnet werden muss + if (!(OldThis == this && OldWidth == Width && OldHeight == Height && Sprite != 0)) + { + float ScaleFactorX = (Width == - 1) ? 1 : static_cast<float>(Width) / static_cast<float>(GetWidth()); + float ScaleFactorY = (Height == - 1) ? 1: static_cast<float>(Height) / static_cast<float>(GetHeight()); + + unsigned int RenderedWidth; + unsigned int RenderedHeight; + if (!VectorImageRenderer.Render(*this, ScaleFactorX, ScaleFactorY, RenderedWidth, RenderedHeight, PixelData, LINE_SCALE_FACTOR)) + { + BS_LOG_ERRORLN("Call to BS_VectorImageRenderer::Render() failed."); + return false; + } + + if (RenderedWidth > 512 || RenderedHeight > 512) + { + BS_LOG_WARNINGLN("Currently the maximum size for scaled vector images is 512x512."); + return true; + } + + GLS_Result Result = GLS_SetSpriteData(Sprite, RenderedWidth, RenderedHeight, &PixelData[0], 0); + if (Result != GLS_OK) + { + BS_LOG_ERRORLN("Call to GLS_SetSpriteData() failed. Reason: %s", GLS_ResultString(Result)); + return false; + } + + OldThis = this; + OldHeight = Height; + OldWidth = Width; + + OldSubImage.x1 = 0; + OldSubImage.y1 = 0; + OldSubImage.x2 = RenderedWidth; + OldSubImage.y2 = RenderedHeight; + } + + // Rendern + // ------- + + // pDest wird ignoriert. Es wird einfach angenommen, dass der Backbuffer gemeint ist, da nur auf den Backbuffer gerendert werden kann. + // Ebenso werden pPartRect ignoriert. Es wird immer das gesamte Sprite gerendert. + + // Farbe nach GLS_Color konvertieren + GLS_Color GLSColor; + GLSColor.a = Color >> 24; + GLSColor.r = (Color >> 16) & 0xff; + GLSColor.g = (Color >> 8) & 0xff; + GLSColor.b = Color & 0xff; + + // Rendern + // TODO: + // Die Bedeutung von FLIP_V und FLIP_H ist vertauscht. Allerdings glaubt der Rest der Engine auch daran, daher war es einfacher diesen Fehler + // weiterzuführen. Bei Gelegenheit ist dieses aber zu ändern. + GLS_Result Result = GLS_Blit(Sprite, + PosX, PosY, + &OldSubImage, &GLSColor, + (Flipping & BS_Image::FLIP_V) ? GLS_True : GLS_False, + (Flipping & BS_Image::FLIP_H) ? GLS_True : GLS_False, + 1.0f, 1.0f); + if (Result != GLS_OK) BS_LOG_ERRORLN("GLS_Blit() failed. Reason: %s", GLS_ResultString(Result)); + + return Result == GLS_OK; +} diff --git a/engines/sword25/gfx/opengl/openglgfx.cpp b/engines/sword25/gfx/opengl/openglgfx.cpp new file mode 100755 index 0000000000..6131a229a5 --- /dev/null +++ b/engines/sword25/gfx/opengl/openglgfx.cpp @@ -0,0 +1,505 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <GL/GL.h> + +#include "util/glsprites/glsprites.h" +#include "../bitmapresource.h" +#include "../animationresource.h" +#include "../fontresource.h" +#include "../panel.h" +#include "../renderobjectmanager.h" +#include "../image/vectorimage.h" +#include "package/packagemanager.h" +#include "kernel/inputpersistenceblock.h" +#include "kernel/outputpersistenceblock.h" + +#include "openglgfx.h" +#include "glimage.h" +#include "swimage.h" + +#include <algorithm> + +using namespace std; + +#define BS_LOG_PREFIX "OPENGLGFX" + + +// ----------------------------------------------------------------------------- +// CONSTANTS +// ----------------------------------------------------------------------------- + +namespace +{ + const unsigned int BIT_DEPTH = 32; + const unsigned int BACKBUFFER_COUNT = 1; + const std::string PNG_EXTENSION(".png"); + const std::string PNG_S_EXTENSION("_s.png"); + const std::string ANI_EXTENSION("_ani.xml"); + const std::string FNT_EXTENSION("_fnt.xml"); + const std::string SWF_EXTENSION(".swf"); + const std::string B25S_EXTENSION(".b25s"); +} + + +// ----------------------------------------------------------------------------- +// CONSTRUCTION / DESTRUCTION +// ----------------------------------------------------------------------------- + +BS_OpenGLGfx::BS_OpenGLGfx(BS_Kernel * pKernel) : + BS_GraphicEngine(pKernel), + m_GLspritesInitialized(false) +{ +} + +// ----------------------------------------------------------------------------- + +BS_OpenGLGfx::~BS_OpenGLGfx() +{ + if (m_GLspritesInitialized) GLS_Quit(); +} + +// ----------------------------------------------------------------------------- + +BS_Service * BS_OpenGLGfx_CreateObject(BS_Kernel* pKernel) +{ + return new BS_OpenGLGfx(pKernel); +} + + +// ----------------------------------------------------------------------------- +// INTERFACE +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::Init(int Width, int Height, int BitDepth, int BackbufferCount, bool Windowed) +{ + // 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; + } + + // 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; + } + + // 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; + + // GLsprites initialisieren + HWND hwnd = reinterpret_cast<HWND>(BS_Kernel::GetInstance()->GetWindow()->GetWindowHandle()); + GLS_Result Result = GLS_InitExternalWindow(Width, Height, Windowed ? GLS_False : GLS_True, hwnd); + if (Result != GLS_OK) + { + BS_LOG_ERRORLN("Could not initialize GLsprites. Reason: %s", GLS_ResultString(Result)); + return false; + } + m_GLspritesInitialized = true; + + // Standardmäßig ist Vsync an. + SetVsync(true); + + // Layer-Manager initialisieren. + m_RenderObjectManagerPtr.reset(new BS_RenderObjectManager(Width, Height, BackbufferCount + 1)); + + // Hauptpanel erstellen + m_MainPanelPtr = m_RenderObjectManagerPtr->GetTreeRoot()->AddPanel(Width, Height, BS_ARGB(0,0,0,0)); + if (!m_MainPanelPtr.IsValid()) return false; + m_MainPanelPtr->SetVisible(true); + + return true; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::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(); + + // Den Layer-Manager auf den nächsten Frame vorbereiten + m_RenderObjectManagerPtr->StartFrame(); + + // GLsprites bescheidgeben + GLS_Result Result = GLS_StartFrame(); + if (Result != GLS_OK) + { + BS_LOG_ERRORLN("Call to GLS_StartFrame() failed. Reason: %s", GLS_ResultString(Result)); + return false; + } + + return true; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::EndFrame() +{ + // Scene zeichnen + m_RenderObjectManagerPtr->Render(); + + // Debug-Lines zeichnen + if (!m_DebugLines.empty()) + { + glEnable(GL_LINE_SMOOTH); + glBegin(GL_LINES); + + std::vector<DebugLine>::const_iterator iter = m_DebugLines.begin(); + for (; iter != m_DebugLines.end(); ++iter) + { + const unsigned int & Color = (*iter).Color; + const BS_Vertex & Start = (*iter).Start; + const BS_Vertex & End = (*iter).End; + + glColor4ub((Color >> 16) & 0xff, (Color >> 8) & 0xff, Color & 0xff, Color >> 24); + glVertex2d(Start.X, Start.Y); + glVertex2d(End.X, End.Y); + } + + glEnd(); + glDisable(GL_LINE_SMOOTH); + + m_DebugLines.clear(); + } + + // Flippen + GLS_Result Result = GLS_EndFrame(); + if (Result != GLS_OK) + { + BS_LOG_ERRORLN("Call to GLS_EndFrame() failed. Reason: %s", GLS_ResultString(Result)); + return false; + } + + // Framecounter aktualisieren + m_FPSCounter.Update(); + + return true; +} + +// ----------------------------------------------------------------------------- + +BS_RenderObjectPtr<BS_Panel> BS_OpenGLGfx::GetMainPanel() +{ + return m_MainPanelPtr; +} + +// ----------------------------------------------------------------------------- + +void BS_OpenGLGfx::SetVsync(bool Vsync) +{ + GLS_Result Result = GLS_SetVSync(Vsync ? GLS_True : GLS_False); + if (Result != GLS_OK) BS_LOG_WARNINGLN("Could not set vsync status. Reason: %s", GLS_ResultString(Result)); +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::GetVsync() const +{ + GLS_Bool Status; + GLS_Result Result = GLS_IsVsync(&Status); + if (Result != GLS_OK) + { + BS_LOG_WARNINGLN("Could not get vsync status. Returning false. Reason: %s", GLS_ResultString(Result)); + return false; + } + + return Status == GLS_True ? true : false; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::Fill(const BS_Rect* FillRectPtr, unsigned int Color) +{ + BS_Rect Rect; + + if (!FillRectPtr) + { + Rect.left = 0; + Rect.top = 0; + Rect.right = m_Width; + Rect.bottom = m_Height; + FillRectPtr = &Rect; + } + + glBegin(GL_QUADS); + glColor4ub((Color >> 16) & 0xff, (Color >> 8) & 0xff, Color & 0xff, Color >> 24); + + glVertex2i(FillRectPtr->left, FillRectPtr->top); + glVertex2i(FillRectPtr->right, FillRectPtr->top); + glVertex2i(FillRectPtr->right, FillRectPtr->bottom); + glVertex2i(FillRectPtr->left, FillRectPtr->bottom); + glEnd(); + + return glGetError() == 0; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::GetScreenshot(unsigned int & Width, unsigned int & Height, vector<unsigned int> & Data) +{ + if (!ReadFramebufferContents(m_Width, m_Height, Data)) return false; + + // Die Größe des Framebuffers zurückgeben. + Width = m_Width; + Height = m_Height; + + // Bilddaten vom OpenGL-Format in unser eigenes Format umwandeln. + ReverseRGBAComponentOrder(Data); + FlipImagedataVertical(Width, Height, Data); + + return true; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::ReadFramebufferContents(unsigned int Width, unsigned int Height, std::vector<unsigned int> & Data) +{ + Data.resize(Width * Height); + glReadPixels(0, 0, Width, Height, GL_RGBA, GL_UNSIGNED_BYTE, &Data[0]); + + if (glGetError() == 0) + return true; + else + { + Data.clear(); + return false; + } +} + +// ----------------------------------------------------------------------------- + +void BS_OpenGLGfx::ReverseRGBAComponentOrder(vector<unsigned int> & Data) +{ + vector<unsigned int>::iterator It = Data.begin(); + while (It != Data.end()) + { + unsigned int Pixel = *It; + *It = (Pixel & 0xff00ff00) | ((Pixel >> 16) & 0xff) | ((Pixel & 0xff) << 16); + ++It; + } +} + +// ----------------------------------------------------------------------------- + +void BS_OpenGLGfx::FlipImagedataVertical(unsigned int Width, unsigned int Height, vector<unsigned int> & Data) +{ + vector<unsigned int> LineBuffer(Width); + + for (unsigned int Y = 0; Y < Height / 2; ++Y) + { + vector<unsigned int>::iterator Line1It = Data.begin() + Y * Width; + vector<unsigned int>::iterator Line2It = Data.begin() + (Height - 1 - Y) * Width; + copy(Line1It, Line1It + Width, LineBuffer.begin()); + copy(Line2It, Line2It + Width, Line1It); + copy(LineBuffer.begin(), LineBuffer.end(), Line2It); + } +} + +// ----------------------------------------------------------------------------- +// RESOURCE MANAGING +// ----------------------------------------------------------------------------- + +static bool DoesStringEndWith(const std::string & String, const std::string & OtherString) +{ + std::string::size_type StringPos = String.rfind(OtherString); + if (StringPos == std::string::npos) return false; + + return StringPos + OtherString.size() == String.size(); +} + +// ----------------------------------------------------------------------------- + +BS_Resource * BS_OpenGLGfx::LoadResource(const std::string& FileName) +{ + BS_ASSERT(CanLoadResource(FileName)); + + // Bild für den Softwarebuffer laden + if (DoesStringEndWith(FileName, PNG_S_EXTENSION)) + { + bool Result; + BS_SWImage * pImage = new BS_SWImage(FileName, Result); + if (!Result) + { + delete pImage; + return 0; + } + + BS_BitmapResource * pResource = new BS_BitmapResource(FileName, pImage); + if (!pResource->IsValid()) + { + delete pResource; + return 0; + } + + return pResource; + } + + // Sprite-Bild laden + if (DoesStringEndWith(FileName, PNG_EXTENSION) || DoesStringEndWith(FileName, B25S_EXTENSION)) + { + bool Result; + BS_GLImage * pImage = new BS_GLImage(FileName, Result); + if (!Result) + { + delete pImage; + return 0; + } + + BS_BitmapResource * pResource = new BS_BitmapResource(FileName, pImage); + if (!pResource->IsValid()) + { + delete pResource; + return 0; + } + + return pResource; + } + + + // Vectorgraphik laden + if (DoesStringEndWith(FileName, SWF_EXTENSION)) + { + // Pointer auf Package-Manager holen + BS_PackageManager * pPackage = BS_Kernel::GetInstance()->GetPackage(); + BS_ASSERT(pPackage); + + // Datei laden + unsigned char* pFileData; + unsigned int FileSize; + if (!(pFileData = static_cast<unsigned char*>(pPackage->GetFile(FileName, &FileSize)))) + { + BS_LOG_ERRORLN("File \"%s\" could not be loaded.", FileName.c_str()); + return 0; + } + + bool Result; + BS_VectorImage * pImage = new BS_VectorImage(pFileData, FileSize, Result); + if (!Result) + { + delete pImage; + delete [] pFileData; + return 0; + } + + BS_BitmapResource * pResource = new BS_BitmapResource(FileName, pImage); + if (!pResource->IsValid()) + { + delete pResource; + delete [] pFileData; + return 0; + } + + delete [] pFileData; + return pResource; + } + + // Animation laden + if (DoesStringEndWith(FileName, ANI_EXTENSION)) + { + BS_AnimationResource * pResource = new BS_AnimationResource(FileName); + if (pResource->IsValid()) + return pResource; + else + { + delete pResource; + return 0; + } + } + + // Font laden + if (DoesStringEndWith(FileName, FNT_EXTENSION)) + { + BS_FontResource * pResource = new BS_FontResource(BS_Kernel::GetInstance(), FileName); + if (pResource->IsValid()) + return pResource; + else + { + delete pResource; + return 0; + } + } + + BS_LOG_ERRORLN("Service cannot load \"%s\".", FileName.c_str()); + return 0; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::CanLoadResource(const std::string& FileName) +{ + return DoesStringEndWith(FileName, PNG_EXTENSION) || + DoesStringEndWith(FileName, ANI_EXTENSION) || + DoesStringEndWith(FileName, FNT_EXTENSION) || + DoesStringEndWith(FileName, SWF_EXTENSION) || + DoesStringEndWith(FileName, B25S_EXTENSION); +} + + +// ----------------------------------------------------------------------------- +// DEBUGGING +// ----------------------------------------------------------------------------- + +void BS_OpenGLGfx::DrawDebugLine(const BS_Vertex & Start, const BS_Vertex & End, unsigned int Color) +{ + m_DebugLines.push_back(DebugLine(Start, End, Color)); +} + +// ----------------------------------------------------------------------------- +// PERSISTENZ +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::Persist(BS_OutputPersistenceBlock & Writer) +{ + bool result = true; + + result &= BS_GraphicEngine::Persist(Writer); + result &= m_RenderObjectManagerPtr->Persist(Writer); + + return result; +} + +// ----------------------------------------------------------------------------- + +bool BS_OpenGLGfx::Unpersist(BS_InputPersistenceBlock & Reader) +{ + bool result = true; + + result &= BS_GraphicEngine::Unpersist(Reader); + result &= m_RenderObjectManagerPtr->Unpersist(Reader); + + return result && Reader.IsGood(); +} diff --git a/engines/sword25/gfx/opengl/openglgfx.h b/engines/sword25/gfx/opengl/openglgfx.h new file mode 100755 index 0000000000..ec305bee8f --- /dev/null +++ b/engines/sword25/gfx/opengl/openglgfx.h @@ -0,0 +1,114 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +#ifndef BS_OPENGLGFX_H +#define BS_OPENGLGFX_H + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#include "kernel/memlog_off.h" +#include <memory> +#include <vector> +#include "kernel/memlog_on.h" + +#include "kernel/common.h" +#include "../graphicengine.h" +#include "../renderobjectptr.h" +#include "util/glsprites/glsprites.h" + +// ----------------------------------------------------------------------------- +// FORWARD DECLARATIONS +// ----------------------------------------------------------------------------- + +class BS_Kernel; +class BS_Service; +class BS_Resource; +class BS_Panel; +class BS_Image; +class BS_RenderObjectManager; + + +// ----------------------------------------------------------------------------- +// CLASS DECLARATION +// ----------------------------------------------------------------------------- + +class BS_OpenGLGfx : public BS_GraphicEngine +{ +public: + BS_OpenGLGfx(BS_Kernel* pKernel); + virtual ~BS_OpenGLGfx(); + + // Interface + // --------- + virtual bool Init(int Width, int Height, int BitDepth, int BackbufferCount, bool Windowed); + virtual bool StartFrame(bool UpdateAll); + virtual bool EndFrame(); + + virtual BS_RenderObjectPtr<BS_Panel> GetMainPanel(); + + virtual void SetVsync(bool Vsync); + virtual bool GetVsync() const; + + virtual bool Fill(const BS_Rect* FillRectPtr = 0, unsigned int Color = BS_RGB(0, 0, 0)); + virtual bool GetScreenshot(unsigned int & Width, unsigned int & Height, std::vector<unsigned int> & Data); + + // Resource-Managing Methoden + // -------------------------- + virtual BS_Resource* LoadResource(const std::string& FileName); + virtual bool CanLoadResource(const std::string& FileName); + + // Debugging Methoden + // ------------------ + virtual void DrawDebugLine(const BS_Vertex & Start, const BS_Vertex & End, unsigned int Color); + static const char * GetGLSResultString(GLS_Result Result); + + // Persistenz Methoden + // ------------------- + virtual bool Persist(BS_OutputPersistenceBlock & Writer); + virtual bool Unpersist(BS_InputPersistenceBlock & Reader); + +private: + bool m_GLspritesInitialized; + + BS_RenderObjectPtr<BS_Panel> m_MainPanelPtr; + + std::auto_ptr<BS_RenderObjectManager> m_RenderObjectManagerPtr; + + struct DebugLine + { + DebugLine(const BS_Vertex & _Start, const BS_Vertex & _End, unsigned int _Color) : + Start(_Start), + End(_End), + Color(_Color) {}; + + BS_Vertex Start; + BS_Vertex End; + unsigned int Color; + }; + + std::vector<DebugLine> m_DebugLines; + + static bool ReadFramebufferContents(unsigned int Width, unsigned int Height, std::vector<unsigned int> & Data); + static void ReverseRGBAComponentOrder(std::vector<unsigned int> & Data); + static void FlipImagedataVertical(unsigned int Width, unsigned int Height, std::vector<unsigned int> & Data); +}; + +#endif diff --git a/engines/sword25/gfx/opengl/swimage.cpp b/engines/sword25/gfx/opengl/swimage.cpp new file mode 100755 index 0000000000..7bc36b5f69 --- /dev/null +++ b/engines/sword25/gfx/opengl/swimage.cpp @@ -0,0 +1,125 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#include "package/packagemanager.h" +#include "gfx/image/imageloader.h" + +#include "swimage.h" + +#define BS_LOG_PREFIX "SWIMAGE" + + +// ----------------------------------------------------------------------------- +// CONSTRUCTION / DESTRUCTION +// ----------------------------------------------------------------------------- + +BS_SWImage::BS_SWImage(const std::string & Filename, bool & Result) : + _ImageDataPtr(0), + m_Width(0), + m_Height(0) +{ + Result = false; + + BS_PackageManager * pPackage = static_cast<BS_PackageManager*>(BS_Kernel::GetInstance()->GetService("package")); + BS_ASSERT(pPackage); + + // Datei laden + char* pFileData; + unsigned int FileSize; + if (!(pFileData = (char*) pPackage->GetFile(Filename, &FileSize))) + { + BS_LOG_ERRORLN("File \"%s\" could not be loaded.", Filename.c_str()); + return; + } + + // Bildeigenschaften bestimmen + BS_GraphicEngine::COLOR_FORMATS ColorFormat; + int Pitch; + if (!BS_ImageLoader::ExtractImageProperties(pFileData, FileSize, ColorFormat, m_Width, m_Height)) + { + BS_LOG_ERRORLN("Could not read image properties."); + return; + } + + // Das Bild dekomprimieren + char * pUncompressedData; + if (!BS_ImageLoader::LoadImage(pFileData, FileSize, BS_GraphicEngine::CF_ABGR32, pUncompressedData, m_Width, m_Height, Pitch)) + { + BS_LOG_ERRORLN("Could not decode image."); + return; + } + + // Dateidaten freigeben + delete[] pFileData; + + _ImageDataPtr = (unsigned int *) pUncompressedData; + + Result = true; + return; +} + +// ----------------------------------------------------------------------------- + +BS_SWImage::~BS_SWImage() +{ + delete [] _ImageDataPtr; +} + + +// ----------------------------------------------------------------------------- + +bool BS_SWImage::Blit(int PosX, int PosY, + int Flipping, + BS_Rect* pPartRect, + unsigned int Color, + int Width, int Height) +{ + BS_LOG_ERRORLN("Blit() is not supported."); + return false; +} + +// ----------------------------------------------------------------------------- + +bool BS_SWImage::Fill(const BS_Rect* pFillRect, unsigned int Color) +{ + BS_LOG_ERRORLN("Fill() is not supported."); + return false; +} + +// ----------------------------------------------------------------------------- + +bool BS_SWImage::SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset, unsigned int Stride) +{ + BS_LOG_ERRORLN("SetContent() is not supported."); + return false; +} + +// ----------------------------------------------------------------------------- + +unsigned int BS_SWImage::GetPixel(int X, int Y) +{ + BS_ASSERT(X >= 0 && X < m_Width); + BS_ASSERT(Y >= 0 && Y < m_Height); + + return _ImageDataPtr[m_Width * Y + X]; +} diff --git a/engines/sword25/gfx/opengl/swimage.h b/engines/sword25/gfx/opengl/swimage.h new file mode 100755 index 0000000000..1f48c238b3 --- /dev/null +++ b/engines/sword25/gfx/opengl/swimage.h @@ -0,0 +1,69 @@ +// ----------------------------------------------------------------------------- +// This file is part of Broken Sword 2.5 +// Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer +// +// Broken Sword 2.5 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 2 of the License, or +// (at your option) any later version. +// +// Broken Sword 2.5 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 Broken Sword 2.5; if not, write to the Free Software +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +// ----------------------------------------------------------------------------- + +#ifndef BS_SWIMAGE_H +#define BS_SWIMAGE_H + +// ----------------------------------------------------------------------------- +// INCLUDES +// ----------------------------------------------------------------------------- + +#include "kernel/common.h" +#include "gfx/image/image.h" +#include "gfx/graphicengine.h" + + +// ----------------------------------------------------------------------------- +// CLASS DEFINITION +// ----------------------------------------------------------------------------- + +class BS_SWImage : public BS_Image +{ +public: + BS_SWImage(const std::string & Filename, bool & Result); + virtual ~BS_SWImage(); + + virtual int GetWidth() const { return m_Width; } + virtual int GetHeight() const { return m_Height; } + virtual BS_GraphicEngine::COLOR_FORMATS GetColorFormat() const { return BS_GraphicEngine::CF_ARGB32; } + + virtual bool Blit(int PosX = 0, int PosY = 0, + int Flipping = BS_Image::FLIP_NONE, + BS_Rect* pPartRect = NULL, + unsigned int Color = BS_ARGB(255, 255, 255, 255), + int Width = -1, int Height = -1); + virtual bool Fill(const BS_Rect* FillRectPtr, unsigned int Color); + virtual bool SetContent(const std::vector<unsigned char> & Pixeldata, unsigned int Offset, unsigned int Stride); + virtual unsigned int GetPixel(int X, int Y); + + virtual bool IsBlitSource() const { return false; } + virtual bool IsBlitTarget() const { return false; } + virtual bool IsScalingAllowed() const { return false; } + virtual bool IsFillingAllowed() const { return false; } + virtual bool IsAlphaAllowed() const { return false; } + virtual bool IsColorModulationAllowed() const { return false; } + virtual bool IsSetContentAllowed() const { return false; } +private: + unsigned int * _ImageDataPtr; + + int m_Width; + int m_Height; +}; + +#endif |