From 36a0b666b3096da5a7ef169c598897be1cb06078 Mon Sep 17 00:00:00 2001 From: RichieSams Date: Sun, 15 Sep 2013 14:41:45 -0500 Subject: ZVISION: Add better alpha support for blitting Instead of blitting directly to the working window, we cache the alpha pixels, then blit directly to the backbuffer instead of to the working window. This ensures that if the alpha'd content changes, the old changes won't appear in any new frames --- engines/zvision/render_manager.cpp | 49 +++++++++++++++++++++++++++++++------- engines/zvision/render_manager.h | 13 ++++++++++ 2 files changed, 54 insertions(+), 8 deletions(-) diff --git a/engines/zvision/render_manager.cpp b/engines/zvision/render_manager.cpp index 62580323d3..72fa5d3fc6 100644 --- a/engines/zvision/render_manager.cpp +++ b/engines/zvision/render_manager.cpp @@ -98,11 +98,37 @@ void RenderManager::renderBackbufferToScreen() { // TODO: Add menu rendering + // Render alpha entries + processAlphaEntries(); + if (!_backBufferDirtyRect.isEmpty()) { _system->copyRectToScreen(_backBuffer.getBasePtr(_backBufferDirtyRect.left, _backBufferDirtyRect.top), _backBuffer.pitch, _backBufferDirtyRect.left, _backBufferDirtyRect.top, _backBufferDirtyRect.width(), _backBufferDirtyRect.height()); } } +void RenderManager::processAlphaEntries() { + for (Common::List::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); iter++) { + uint32 destOffset = 0; + uint32 sourceOffset = 0; + uint16 *backbufferPtr = (uint16 *)_backBuffer.getBasePtr((*iter).destX + _workingWindow.left, (*iter).destY + _workingWindow.top); + uint16 *entryPtr = (uint16 *)(*iter).data->getPixels(); + + for (int32 y = 0; y < (*iter).height; y++) { + for (int32 x = 0; x < (*iter).width; x++) { + uint16 color = entryPtr[sourceOffset + x]; + if (color != (*iter).alphaColor) { + backbufferPtr[destOffset + x] = color; + } + } + + destOffset += _workingWidth; + sourceOffset += (*iter).width; + } + + _backBufferDirtyRect.extend(Common::Rect((*iter).destX + _workingWindow.left, (*iter).destY + _workingWindow.top, (*iter).destX + _workingWindow.left + (*iter).width, (*iter).destY + _workingWindow.top + (*iter).height)); + } +} + void RenderManager::clearWorkingWindowTo555Color(uint16 color) { uint32 workingWindowSize = _workingWidth * _workingHeight; byte r, g, b; @@ -295,24 +321,31 @@ void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, i } void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor) { - uint32 destOffset = 0; + AlphaDataEntry entry; + entry.alphaColor = alphaColor; + entry.data = new Graphics::Surface(); + entry.data->create(width, height, _pixelFormat); + entry.destX = destX; + entry.destY = destY; + entry.width = width; + entry.height = height; + uint32 sourceOffset = 0; - uint16 *workingWindowBufferPtr = (uint16 *)_workingWindowBuffer.getBasePtr(destX, destY); + uint32 destOffset = 0; + uint16 *surfacePtr = (uint16 *)entry.data->getPixels(); for (int32 y = 0; y < height; y++) { for (int32 x = 0; x < width; x++) { - uint16 color = buffer[sourceOffset + x]; - if (color != alphaColor) { - workingWindowBufferPtr[destOffset + x] = color; - } + surfacePtr[destOffset + x] = buffer[sourceOffset + x]; } - destOffset += _workingWidth; + destOffset += width; sourceOffset += imageWidth; } - _workingWindowDirtyRect.extend(Common::Rect(destX, destY, destX + width, destY + height)); + _alphaDataEntries.push_back(entry); } + void RenderManager::copyWorkingWindowSubRectToSurface(Graphics::Surface *destSurface, uint16 destX, uint16 destY, Common::Rect subRect) const { uint32 destOffset = 0; uint32 sourceOffset = 0; diff --git a/engines/zvision/render_manager.h b/engines/zvision/render_manager.h index ce5c774917..f6106b39a3 100644 --- a/engines/zvision/render_manager.h +++ b/engines/zvision/render_manager.h @@ -48,6 +48,16 @@ public: RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat); ~RenderManager(); +private: + struct AlphaDataEntry { + Graphics::Surface *data; + uint16 alphaColor; + uint16 destX; + uint16 destY; + uint16 width; + uint16 height; + }; + private: OSystem *_system; const Graphics::PixelFormat _pixelFormat; @@ -56,6 +66,7 @@ private: // It's used for panorama/tilt warping and for clearing the workingWindow to a single color Graphics::Surface _workingWindowBuffer; Graphics::Surface _backBuffer; + Common::List _alphaDataEntries; Common::Rect _workingWindowDirtyRect; Common::Rect _backBufferDirtyRect; @@ -108,6 +119,8 @@ public: */ void renderBackbufferToScreen(); + void processAlphaEntries(); + void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height); void copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor); -- cgit v1.2.3