aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute/Base/BRenderSDL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/wintermute/Base/BRenderSDL.cpp')
-rw-r--r--engines/wintermute/Base/BRenderSDL.cpp456
1 files changed, 456 insertions, 0 deletions
diff --git a/engines/wintermute/Base/BRenderSDL.cpp b/engines/wintermute/Base/BRenderSDL.cpp
new file mode 100644
index 0000000000..43b6134845
--- /dev/null
+++ b/engines/wintermute/Base/BRenderSDL.cpp
@@ -0,0 +1,456 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/Base/BRenderSDL.h"
+#include "engines/wintermute/Base/BRegistry.h"
+#include "engines/wintermute/Base/BSurfaceSDL.h"
+#include "engines/wintermute/Base/BSurfaceStorage.h"
+#include "engines/wintermute/Base/BImage.h"
+#include "engines/wintermute/MathUtil.h"
+#include "engines/wintermute/Base/BGame.h"
+#include "engines/wintermute/Base/BSprite.h"
+#include "common/system.h"
+#include "engines/wintermute/graphics/transparentSurface.h"
+
+namespace WinterMute {
+
+// TODO: Redo everything here.
+
+//////////////////////////////////////////////////////////////////////////
+CBRenderSDL::CBRenderSDL(CBGame *inGame) : CBRenderer(inGame) {
+ /* _renderer = NULL;
+ _win = NULL;*/
+ _renderSurface = NULL;
+
+ _borderLeft = _borderRight = _borderTop = _borderBottom = 0;
+ _ratioX = _ratioY = 1.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////
+CBRenderSDL::~CBRenderSDL() {
+#if 0
+ if (_renderer) SDL_DestroyRenderer(_renderer);
+ if (_win) SDL_DestroyWindow(_win);
+ SDL_Quit();
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::InitRenderer(int width, int height, bool windowed) {
+ //if (SDL_Init(SDL_INIT_VIDEO) < 0) return E_FAIL;
+
+#if 0
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
+ SDL_GL_SetAttribute(SDL_GL_RETAINED_BACKING, 1);
+#endif
+
+ _width = width;
+ _height = height;
+
+ _realWidth = width;
+ _realHeight = height;
+
+
+ // find suitable resolution
+#ifdef __IPHONEOS__
+ _realWidth = 480;
+ _realHeight = 320;
+
+ int numModes = SDL_GetNumDisplayModes(0);
+ for (int i = 0; i < numModes; i++) {
+ SDL_DisplayMode mode;
+ SDL_GetDisplayMode(0, i, &mode);
+
+ if (mode.w > mode.h) {
+ _realWidth = mode.w;
+ _realHeight = mode.h;
+ break;
+ }
+ }
+#else
+ _realWidth = Game->_registry->ReadInt("Debug", "ForceResWidth", _width);
+ _realHeight = Game->_registry->ReadInt("Debug", "ForceResHeight", _height);
+#endif
+
+ /*
+ _realWidth = 480;
+ _realHeight = 320;
+ */
+
+
+ float origAspect = (float)_width / (float)_height;
+ float realAspect = (float)_realWidth / (float)_realHeight;
+
+ float ratio;
+ if (origAspect < realAspect) {
+ // normal to wide
+ ratio = (float)_realHeight / (float)_height;
+ } else {
+ // wide to normal
+ ratio = (float)_realWidth / (float)_width;
+ }
+
+ _borderLeft = (_realWidth - (_width * ratio)) / 2;
+ _borderRight = _realWidth - (_width * ratio) - _borderLeft;
+
+ _borderTop = (_realHeight - (_height * ratio)) / 2;
+ _borderBottom = _realHeight - (_height * ratio) - _borderTop;
+
+
+
+ _ratioX = (float)(_realWidth - _borderLeft - _borderRight) / (float)_width;
+ _ratioY = (float)(_realHeight - _borderTop - _borderBottom) / (float)_height;
+
+#if 0
+ Uint32 flags = SDL_WINDOW_SHOWN;
+#endif
+#ifdef __IPHONEOS__
+ flags |= SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS;
+#endif
+
+ //_windowed = Game->_registry->ReadBool("Video", "Windowed", true);
+// if (!windowed) flags |= SDL_WINDOW_FULLSCREEN;
+
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 24, 16, 8, 0);
+ g_system->beginGFXTransaction();
+ g_system->initSize(_width, _height, &format);
+ OSystem::TransactionError gfxError = g_system->endGFXTransaction();
+
+ if (gfxError != OSystem::kTransactionSuccess) {
+ warning("Couldn't setup GFX-backend for %dx%dx%d", _width, _height, format.bytesPerPixel * 8);
+ return E_FAIL;
+ }
+#if 0
+ _win = SDL_CreateWindow("WME Lite",
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ _realWidth, _realHeight,
+ flags);
+
+ if (!_win) return E_FAIL;
+#endif
+
+ warning("TODO: Hide cursor");
+ //SDL_ShowCursor(SDL_DISABLE);
+
+#ifdef __IPHONEOS__
+ // SDL defaults to OGL ES2, which doesn't work on old devices
+ SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengles");
+#else
+ //SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
+#endif
+#if 0
+ _renderer = SDL_CreateRenderer(_win, -1, 0);
+
+ if (!_renderer) return E_FAIL;
+#endif
+ _renderSurface = new Graphics::Surface();
+ _renderSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat());
+ _active = true;
+
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::Flip() {
+
+#ifdef __IPHONEOS__
+ // hack: until viewports work correctly, we just paint black bars instead
+ SDL_SetRenderDrawColor(_renderer, 0x00, 0x00, 0x00, 0xFF);
+
+ static bool firstRefresh = true; // prevents a weird color glitch
+ if (firstRefresh) {
+ firstRefresh = false;
+ } else {
+ SDL_Rect rect;
+ if (_borderLeft > 0) {
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = _borderLeft;
+ rect.h = _realHeight;
+ SDL_RenderFillRect(_renderer, &rect);
+ }
+ if (_borderRight > 0) {
+ rect.x = (_realWidth - _borderRight);
+ rect.y = 0;
+ rect.w = _borderRight;
+ rect.h = _realHeight;
+ SDL_RenderFillRect(_renderer, &rect);
+ }
+ if (_borderTop > 0) {
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = _realWidth;
+ rect.h = _borderTop;
+ SDL_RenderFillRect(_renderer, &rect);
+ }
+ if (_borderBottom > 0) {
+ rect.x = 0;
+ rect.y = _realHeight - _borderBottom;
+ rect.w = _realWidth;
+ rect.h = _borderBottom;
+ SDL_RenderFillRect(_renderer, &rect);
+ }
+ }
+#endif
+ g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+ g_system->updateScreen();
+ //SDL_RenderPresent(_renderer);
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::Fill(byte r, byte g, byte b, RECT *rect) {
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, 0xFF);
+ //SDL_RenderClear(_renderer);
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::Fade(uint16 Alpha) {
+ uint32 dwAlpha = 255 - Alpha;
+ return FadeToColor(dwAlpha << 24);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::FadeToColor(uint32 Color, RECT *rect) {
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("Implement CBRenderSDL::FadeToColor"); // TODO.
+ hasWarned = true;
+ }
+#if 0
+ SDL_Rect fillRect;
+
+ if (rect) {
+ fillRect.x = rect->left;
+ fillRect.y = rect->top;
+ fillRect.w = rect->right - rect->left;
+ fillRect.h = rect->bottom - rect->top;
+ } else {
+ RECT rc;
+ Game->GetCurrentViewportRect(&rc);
+ fillRect.x = rc.left;
+ fillRect.y = rc.top;
+ fillRect.w = rc.right - rc.left;
+ fillRect.h = rc.bottom - rc.top;
+ }
+ ModTargetRect(&fillRect);
+
+ byte r = D3DCOLGetR(Color);
+ byte g = D3DCOLGetG(Color);
+ byte b = D3DCOLGetB(Color);
+ byte a = D3DCOLGetA(Color);
+
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, a);
+ //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
+ //SDL_RenderFillRect(_renderer, &fillRect);
+#endif
+ return S_OK;
+}
+
+// Replacement for SDL2's SDL_RenderCopy
+void CBRenderSDL::drawFromSurface(Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect) {
+ TransparentSurface src(*surf, false);
+ src.blit(*_renderSurface, dstRect->left, dstRect->top, TransparentSurface::FLIP_NONE, srcRect,BS_ARGB(255, 255, 255, 255), dstRect->width(), dstRect->height() );
+}
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::DrawLine(int X1, int Y1, int X2, int Y2, uint32 Color) {
+ static bool hasWarned = false;
+ if (!hasWarned) {
+ warning("CBRenderSDL::DrawLine - not fully ported yet");
+ hasWarned = true;
+ }
+/* byte r = D3DCOLGetR(Color);
+ byte g = D3DCOLGetG(Color);
+ byte b = D3DCOLGetB(Color);
+ byte a = D3DCOLGetA(Color);*/
+
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, a);
+ //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
+
+ POINT point1, point2;
+ point1.x = X1;
+ point1.y = Y1;
+ PointToScreen(&point1);
+
+ point2.x = X2;
+ point2.y = Y2;
+ PointToScreen(&point2);
+
+
+ //SDL_RenderDrawLine(_renderer, point1.x, point1.y, point2.x, point2.y);
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+CBImage *CBRenderSDL::TakeScreenshot() {
+// TODO: Fix this
+#if 0
+ SDL_Rect viewport;
+
+ SDL_RenderGetViewport(_renderer, &viewport);
+
+ SDL_Surface *surface = SDL_CreateRGBSurface(0, viewport.w, viewport.h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0x00000000);
+ if (!surface) return NULL;
+
+ if (SDL_RenderReadPixels(_renderer, NULL, surface->format->format, surface->pixels, surface->pitch) < 0) return NULL;
+
+ FIBITMAP *dib = FreeImage_Allocate(viewport.w, viewport.h, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
+
+ int bytespp = FreeImage_GetLine(dib) / FreeImage_GetWidth(dib);
+
+ for (unsigned y = 0; y < FreeImage_GetHeight(dib); y++) {
+ byte *bits = FreeImage_GetScanLine(dib, y);
+ byte *src = (byte *)surface->pixels + (viewport.h - y - 1) * surface->pitch;
+ memcpy(bits, src, bytespp * viewport.w);
+ }
+
+ return new CBImage(Game, dib);
+#endif
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::SwitchFullscreen() {
+ /*if (_windowed) SDL_SetWindowFullscreen(_win, SDL_TRUE);
+ else SDL_SetWindowFullscreen(_win, SDL_FALSE);
+
+ _windowed = !_windowed;
+ */
+ Game->_registry->WriteBool("Video", "Windowed", _windowed);
+
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *CBRenderSDL::GetName() {
+ if (_name.empty()) {
+#if 0
+ if (_renderer) {
+ SDL_RendererInfo info;
+ SDL_GetRendererInfo(_renderer, &info);
+ _name = AnsiString(info.name);
+ }
+#endif
+ }
+ return _name.c_str();
+}
+
+//////////////////////////////////////////////////////////////////////////
+HRESULT CBRenderSDL::SetViewport(int left, int top, int right, int bottom) {
+ Common::Rect rect;
+ // TODO: Hopefully this is the same logic that ScummVM uses.
+ rect.left = left + _borderLeft;
+ rect.top = top + _borderTop;
+ rect.right = (right - left) * _ratioX;
+ rect.bottom = (bottom - top) * _ratioY;
+
+ // TODO fix this once viewports work correctly in SDL/landscape
+#ifndef __IPHONEOS__
+ //SDL_RenderSetViewport(GetSdlRenderer(), &rect);
+#endif
+ return S_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderSDL::ModTargetRect(Common::Rect *rect) {
+#if 0
+ SDL_Rect viewportRect;
+ SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect);
+
+ rect->x = MathUtil::Round(rect->x * _ratioX + _borderLeft - viewportRect.x);
+ rect->y = MathUtil::Round(rect->y * _ratioY + _borderTop - viewportRect.y);
+ rect->w = MathUtil::RoundUp(rect->w * _ratioX);
+ rect->h = MathUtil::RoundUp(rect->h * _ratioY);
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderSDL::PointFromScreen(POINT *point) {
+#if 0
+ SDL_Rect viewportRect;
+ SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect);
+
+ point->x = point->x / _ratioX - _borderLeft / _ratioX + viewportRect.x;
+ point->y = point->y / _ratioY - _borderTop / _ratioY + viewportRect.y;
+#endif
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderSDL::PointToScreen(POINT *point) {
+#if 0
+ SDL_Rect viewportRect;
+ SDL_RenderGetViewport(GetSdlRenderer(), &viewportRect);
+
+ point->x = MathUtil::RoundUp(point->x * _ratioX) + _borderLeft - viewportRect.x;
+ point->y = MathUtil::RoundUp(point->y * _ratioY) + _borderTop - viewportRect.y;
+#endif
+}
+
+//////////////////////////////////////////////////////////////////////////
+void CBRenderSDL::DumpData(const char *Filename) {
+ FILE *f = fopen(Filename, "wt");
+ if (!f) return;
+
+ CBSurfaceStorage *Mgr = Game->_surfaceStorage;
+
+ int TotalKB = 0;
+ int TotalLoss = 0;
+ fprintf(f, "Filename;Usage;Size;KBytes\n");
+ for (int i = 0; i < Mgr->_surfaces.GetSize(); i++) {
+ CBSurfaceSDL *Surf = (CBSurfaceSDL *)Mgr->_surfaces[i];
+ if (!Surf->_filename) continue;
+ if (!Surf->_valid) continue;
+
+ fprintf(f, "%s;%d;", Surf->_filename, Surf->_referenceCount);
+ fprintf(f, "%dx%d;", Surf->GetWidth(), Surf->GetHeight());
+
+ int kb = Surf->GetWidth() * Surf->GetHeight() * 4 / 1024;
+
+ TotalKB += kb;
+ fprintf(f, "%d;", kb);
+ fprintf(f, "\n");
+ }
+ fprintf(f, "Total %d;;;%d\n", Mgr->_surfaces.GetSize(), TotalKB);
+
+
+ fclose(f);
+ Game->LOG(0, "Texture Stats Dump completed.");
+ Game->QuickMessage("Texture Stats Dump completed.");
+}
+
+} // end of namespace WinterMute