From ea19c4162d24d6bf32246671aa5fab285ca7ad39 Mon Sep 17 00:00:00 2001 From: Einar Johan Trøan Sømåen Date: Tue, 20 Aug 2013 18:00:17 +0200 Subject: WINTERMUTE: Add binary alpha-blitting. For now, no RLE, or anything, but the infrastructure for it is put in place here. --- .../base/gfx/osystem/base_surface_osystem.cpp | 18 +++++----- .../base/gfx/osystem/base_surface_osystem.h | 4 ++- .../wintermute/base/gfx/osystem/render_ticket.cpp | 17 +++++++-- engines/wintermute/graphics/transform_struct.h | 6 ---- .../wintermute/graphics/transparent_surface.cpp | 41 +++++++++++++++++++--- engines/wintermute/graphics/transparent_surface.h | 8 ++++- 6 files changed, 71 insertions(+), 23 deletions(-) (limited to 'engines/wintermute') diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index aed0129b3a..6506abd29c 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -48,7 +48,7 @@ namespace Wintermute { BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) { _surface = new Graphics::Surface(); _alphaMask = nullptr; - _alphaType = ALPHA_FULL; + _alphaType = TransparentSurface::ALPHA_FULL; _lockPixels = nullptr; _lockPitch = 0; _loaded = false; @@ -71,10 +71,10 @@ BaseSurfaceOSystem::~BaseSurfaceOSystem() { renderer->invalidateTicketsFromSurface(this); } -AlphaType hasTransparencyType(const Graphics::Surface *surf) { +TransparentSurface::AlphaType hasTransparencyType(const Graphics::Surface *surf) { if (surf->format.bytesPerPixel != 4) { warning("hasTransparencyType:: non 32 bpp surface passed as argument"); - return ALPHA_OPAQUE; + return TransparentSurface::ALPHA_OPAQUE; } uint8 r, g, b, a; bool seenAlpha = false; @@ -96,11 +96,11 @@ AlphaType hasTransparencyType(const Graphics::Surface *surf) { } } if (seenFullAlpha) { - return ALPHA_FULL; + return TransparentSurface::ALPHA_FULL; } else if (seenAlpha) { - return ALPHA_BINARY; + return TransparentSurface::ALPHA_BINARY; } else { - return ALPHA_OPAQUE; + return TransparentSurface::ALPHA_OPAQUE; } } @@ -438,7 +438,7 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, // But no checking is in place for that yet. // Optimize by not doing alpha-blits if we lack alpha - if (_alphaType == ALPHA_OPAQUE && !transform._alphaDisable) { + if (_alphaType == TransparentSurface::ALPHA_OPAQUE && !transform._alphaDisable) { transform._alphaDisable = true; } @@ -457,9 +457,9 @@ bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAl _surface->free(); _surface->copyFrom(surface); if (hasAlpha) { - _alphaType = ALPHA_FULL; + _alphaType = TransparentSurface::ALPHA_FULL; } else { - _alphaType = ALPHA_OPAQUE; + _alphaType = TransparentSurface::ALPHA_OPAQUE; } BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); renderer->invalidateTicketsFromSurface(this); diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index ad1e9cf737..6cf19d00fb 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -30,6 +30,7 @@ #define WINTERMUTE_BASE_SURFACESDL_H #include "graphics/surface.h" +#include "engines/wintermute/graphics/transparent_surface.h" #include "engines/wintermute/base/gfx/base_surface.h" #include "common/list.h" @@ -81,6 +82,7 @@ public: return _height; } + TransparentSurface::AlphaType getAlphaType() const { return _alphaType; } private: Graphics::Surface *_surface; bool _loaded; @@ -90,7 +92,7 @@ private: uint32 getPixelAt(Graphics::Surface *surface, int x, int y); uint32 _rotation; - AlphaType _alphaType; + TransparentSurface::AlphaType _alphaType; void *_lockPixels; int _lockPitch; byte *_alphaMask; diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index 98739e0778..b1720c1b0b 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -28,6 +28,7 @@ #include "engines/wintermute/base/gfx/osystem/render_ticket.h" +#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h" #include "engines/wintermute/graphics/transform_tools.h" #include "common/textconsole.h" @@ -104,7 +105,13 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { clipRect.setWidth(getSurface()->w); clipRect.setHeight(getSurface()->h); - src._enableAlphaBlit = !_transform._alphaDisable; + if (_owner) { + if (_transform._alphaDisable) { + src._alphaMode = TransparentSurface::ALPHA_OPAQUE; + } else { + src._alphaMode = _owner->getAlphaType(); + } + } src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); } @@ -118,7 +125,13 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect clipRect->setHeight(getSurface()->h); } - src._enableAlphaBlit = !_transform._alphaDisable; + if (_owner) { + if (_transform._alphaDisable) { + src._alphaMode = TransparentSurface::ALPHA_OPAQUE; + } else { + src._alphaMode = _owner->getAlphaType(); + } + } src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height()); if (doDelete) { delete clipRect; diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h index f4f97d1ea9..a54c4cc5d0 100644 --- a/engines/wintermute/graphics/transform_struct.h +++ b/engines/wintermute/graphics/transform_struct.h @@ -42,12 +42,6 @@ const int32 kDefaultOffsetX = 0; const int32 kDefaultOffsetY = 0; const int32 kDefaultAngle = 0; -enum AlphaType { - ALPHA_OPAQUE = 0, - ALPHA_BINARY = 1, - ALPHA_FULL = 2 -}; - struct TransformStruct { private: void init(Point32 zoom, uint32 angle, Point32 hotspot, bool alphaDisable, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX, bool mirrorY, Point32 offset); diff --git a/engines/wintermute/graphics/transparent_surface.cpp b/engines/wintermute/graphics/transparent_surface.cpp index 9539b68c85..249d30f7d9 100644 --- a/engines/wintermute/graphics/transparent_surface.cpp +++ b/engines/wintermute/graphics/transparent_surface.cpp @@ -140,9 +140,9 @@ void TransparentSurface::copyPixelNearestNeighbor(float projX, float projY, int } #endif -TransparentSurface::TransparentSurface() : Surface(), _enableAlphaBlit(true) {} +TransparentSurface::TransparentSurface() : Surface(), _alphaMode(ALPHA_FULL) {} -TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _enableAlphaBlit(true) { +TransparentSurface::TransparentSurface(const Surface &surf, bool copyData) : Surface(), _alphaMode(ALPHA_FULL) { if (copyData) { copyFrom(surf); } else { @@ -179,6 +179,37 @@ void doBlitOpaque(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pit } } +void doBlitBinary(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { + byte *in, *out; + +#ifdef SCUMM_LITTLE_ENDIAN + const int aIndex = 0; +#else + const int aIndex = 3; +#endif + const int aShift = 0;//img->format.aShift; + + for (uint32 i = 0; i < height; i++) { + out = outo; + in = ino; + for (uint32 j = 0; j < width; j++) { + uint32 pix = *(uint32 *)in; + int a = (pix >> aShift) & 0xff; + in += inStep; + + if (a == 0) { // Full transparency + out += 4; + } else { // Full opacity (Any value not exactly 0 is Opaque here) + *(uint32 *)out = pix; + out[aIndex] = 0xFF; + out += 4; + } + } + outo += pitch; + ino += inoStep; + } +} + void doBlitAlpha(byte *ino, byte *outo, uint32 width, uint32 height, uint32 pitch, int32 inStep, int32 inoStep) { byte *in, *out; @@ -388,9 +419,11 @@ Common::Rect TransparentSurface::blit(Graphics::Surface &target, int posX, int p const int rShiftTarget = 24;//target.format.rShift; if (ca == 255 && cb == 255 && cg == 255 && cr == 255) { - if (_enableAlphaBlit) { + if (_alphaMode == ALPHA_FULL) { doBlitAlpha(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); - } else { + } else if (_alphaMode == ALPHA_BINARY) { + doBlitBinary(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); + } else if (_alphaMode == ALPHA_OPAQUE) { doBlitOpaque(ino, outo, img->w, img->h, target.pitch, inStep, inoStep); } } else { diff --git a/engines/wintermute/graphics/transparent_surface.h b/engines/wintermute/graphics/transparent_surface.h index 828c4dd9a9..598aaa55d7 100644 --- a/engines/wintermute/graphics/transparent_surface.h +++ b/engines/wintermute/graphics/transparent_surface.h @@ -75,7 +75,13 @@ struct TransparentSurface : public Graphics::Surface { FLIP_VH = FLIP_H | FLIP_V }; - bool _enableAlphaBlit; + enum AlphaType { + ALPHA_OPAQUE = 0, + ALPHA_BINARY = 1, + ALPHA_FULL = 2 + }; + + AlphaType _alphaMode; /** @brief renders the surface to another surface -- cgit v1.2.3