From 057b01951a92cc17e6c7a5121d2bd866841c4f75 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 25 Sep 2013 19:47:39 +0200 Subject: WINTERMUTE: Add displayTiled function to replace repeatLastDraw This avoids queueing many tickets for a UITiledImage, replacing them by a single tiled ticket. --- engines/wintermute/base/gfx/base_surface.h | 2 +- .../base/gfx/osystem/base_render_osystem.cpp | 48 --------------- .../base/gfx/osystem/base_render_osystem.h | 2 - .../base/gfx/osystem/base_surface_osystem.cpp | 18 +++--- .../base/gfx/osystem/base_surface_osystem.h | 2 +- .../wintermute/base/gfx/osystem/render_ticket.cpp | 68 ++++++++++++++++++++-- 6 files changed, 75 insertions(+), 65 deletions(-) (limited to 'engines/wintermute/base/gfx') diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h index 42fd593f61..a53748e9aa 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -56,7 +56,7 @@ public: virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; virtual bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) = 0; virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0; - virtual bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) = 0; + virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) = 0; virtual bool restore(); virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0; virtual bool create(int width, int height); diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp index 37f577d202..b8e35d9724 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -55,7 +55,6 @@ BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { _lastFrameIter = _renderQueue.end(); _needsFlip = true; _skipThisFrame = false; - _previousTicket = nullptr; _borderLeft = _borderRight = _borderTop = _borderBottom = 0; _ratioX = _ratioY = 1.0f; @@ -265,7 +264,6 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S ticket->_transform._rgbaMod = _colorMod; ticket->_wantsDraw = true; _renderQueue.push_back(ticket); - _previousTicket = ticket; drawFromSurface(ticket); return; } @@ -296,7 +294,6 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S drawFromSurface(compareTicket); } else { drawFromQueuedTicket(it); - _previousTicket = compareTicket; } return; } @@ -305,57 +302,13 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform); if (!_disableDirtyRects) { drawFromTicket(ticket); - _previousTicket = ticket; } else { ticket->_wantsDraw = true; _renderQueue.push_back(ticket); - _previousTicket = ticket; drawFromSurface(ticket); } } -void BaseRenderOSystem::repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY) { - if (_previousTicket && _lastAddedTicket != _renderQueue.end()) { - RenderTicket *origTicket = _previousTicket; - - // Make sure drawSurface WILL start from the correct _lastAddedTicket - if (!_disableDirtyRects && *_lastAddedTicket != origTicket) { - RenderQueueIterator it; - RenderQueueIterator endIterator = _renderQueue.end(); - for (it = _renderQueue.begin(); it != endIterator; ++it) { - if ((*it) == _previousTicket) { - _lastAddedTicket = it; - break; - } - } - } - Common::Rect srcRect(0, 0, 0, 0); - srcRect.setWidth(origTicket->getSrcRect()->width()); - srcRect.setHeight(origTicket->getSrcRect()->height()); - - Common::Rect dstRect = origTicket->_dstRect; - int initLeft = dstRect.left; - int initRight = dstRect.right; - - TransformStruct temp = TransformStruct(kDefaultZoomX, kDefaultZoomY, kDefaultAngle, kDefaultHotspotX, kDefaultHotspotY, BLEND_NORMAL, kDefaultRgbaMod, false, false, kDefaultOffsetX, kDefaultOffsetY); - - for (int i = 0; i < numTimesY; i++) { - if (i == 0) { - dstRect.translate(offsetX, 0); - } - for (int j = (i == 0 ? 1 : 0); j < numTimesX; j++) { - drawSurface(origTicket->_owner, origTicket->getSurface(), &srcRect, &dstRect, temp); - dstRect.translate(offsetX, 0); - } - dstRect.left = initLeft; - dstRect.right = initRight; - dstRect.translate(0, offsetY); - } - } else { - error("Repeat-draw failed (did you forget to draw something before this?)"); - } -} - void BaseRenderOSystem::invalidateTicket(RenderTicket *renderTicket) { addDirtyRect(renderTicket->_dstRect); renderTicket->_isValid = false; @@ -614,7 +567,6 @@ void BaseRenderOSystem::endSaveLoad() { delete ticket; } _lastAddedTicket = _renderQueue.begin(); - _previousTicket = nullptr; // HACK: After a save the buffer will be drawn before the scripts get to update it, // so just skip this single frame. _skipThisFrame = true; diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index fd5d33622e..a6634d9acc 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -111,7 +111,6 @@ public: virtual bool endSpriteBatch() override; void endSaveLoad(); void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform); - void repeatLastDraw(int offsetX, int offsetY, int numTimesX, int numTimesY); BaseSurface *createSurface() override; private: /** @@ -130,7 +129,6 @@ private: Common::Rect *_dirtyRect; Common::List _renderQueue; RenderQueueIterator _lastAddedTicket; - RenderTicket *_previousTicket; bool _needsFlip; uint32 _drawNum; ///< The global number of the current draw-operation. diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp index e04af45dd9..67d8f3f425 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -380,6 +380,14 @@ bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newR return drawSprite(x, y, &rect, &newRect, transform); } +////////////////////////////////////////////////////////////////////////// +bool BaseSurfaceOSystem::displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY) { + assert(numTimesX > 0 && numTimesY > 0); + TransformStruct transform(numTimesX, numTimesY); + return drawSprite(x, y, &rect, nullptr, transform); +} + + ////////////////////////////////////////////////////////////////////////// bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, TransformStruct transform) { BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); @@ -424,8 +432,8 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, position.setWidth(newRect->width()); position.setHeight(newRect->height()); } else { - position.setWidth((int16)((float)srcRect.width() * transform._zoom.x / kDefaultZoomX)); - position.setHeight((int16)((float)srcRect.height() * transform._zoom.y / kDefaultZoomY)); + position.setWidth((int16)((float)srcRect.width() * transform._zoom.x / kDefaultZoomX) * transform._numTimesX); + position.setHeight((int16)((float)srcRect.height() * transform._zoom.y / kDefaultZoomY) * transform._numTimesY); } renderer->modTargetRect(&position); @@ -441,12 +449,6 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, return STATUS_OK; } -bool BaseSurfaceOSystem::repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) { - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - renderer->repeatLastDraw(offsetX, offsetY, numTimesX, numTimesY); - return STATUS_OK; -} - bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) { _loaded = true; _surface->free(); diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h index 340a5a5ffc..67f45f66db 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -58,7 +58,7 @@ public: bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = kDefaultRgbaMod, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) override; bool displayTransform(int x, int y, Rect32 rect, Rect32 newRect, const TransformStruct &transform) override; - bool repeatLastDisplayOp(int offsetX, int offsetY, int numTimesX, int numTimesY) override; + virtual bool displayTiled(int x, int y, Rect32 rect, int numTimesX, int numTimesY); virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) override; /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle); static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin); diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp index 006dd77e18..11a4921f97 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -50,13 +50,19 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel); } // Then scale it if necessary + // + // NB: The numTimesX/numTimesY properties don't yet mix well with + // scaling and rotation, but there is no need for that functionality at + // the moment. if (_transform._angle != kDefaultAngle) { TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.rotoscale(transform); _surface->free(); delete _surface; _surface = temp; - } else if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) { + } else if ((dstRect->width() != srcRect->width() || + dstRect->height() != srcRect->height()) && + _transform._numTimesX * _transform._numTimesY == 1) { TransparentSurface src(*_surface, false); Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height()); _surface->free(); @@ -109,7 +115,19 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { src._alphaMode = _owner->getAlphaType(); } } - src.blit(*_targetSurface, _dstRect.left, _dstRect.top, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); + + int y = _dstRect.top; + int w = _dstRect.width() / _transform._numTimesX; + int h = _dstRect.height() / _transform._numTimesY; + + for (int ry = 0; ry < _transform._numTimesY; ++ry) { + int x = _dstRect.left; + for (int rx = 0; rx < _transform._numTimesX; ++rx) { + src.blit(*_targetSurface, x, y, _transform._flip, &clipRect, _transform._rgbaMod, clipRect.width(), clipRect.height()); + x += w; + } + y += h; + } } void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const { @@ -118,8 +136,8 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect if (!clipRect) { doDelete = true; clipRect = new Common::Rect(); - clipRect->setWidth(getSurface()->w); - clipRect->setHeight(getSurface()->h); + clipRect->setWidth(getSurface()->w * _transform._numTimesX); + clipRect->setHeight(getSurface()->h * _transform._numTimesY); } if (_owner) { @@ -129,7 +147,47 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect src._alphaMode = _owner->getAlphaType(); } } - src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height(), _transform._blendMode); + + if (_transform._numTimesX * _transform._numTimesY == 1) { + + src.blit(*_targetSurface, dstRect->left, dstRect->top, _transform._flip, clipRect, _transform._rgbaMod, clipRect->width(), clipRect->height(), _transform._blendMode); + + } else { + + // clipRect is a subrect of the full numTimesX*numTimesY rect + Common::Rect subRect; + + int y = 0; + int w = getSurface()->w; + int h = getSurface()->h; + assert(w == _dstRect.width() / _transform._numTimesX); + assert(h == _dstRect.height() / _transform._numTimesY); + + int basex = dstRect->left - clipRect->left; + int basey = dstRect->top - clipRect->top; + + for (int ry = 0; ry < _transform._numTimesY; ++ry) { + int x = 0; + for (int rx = 0; rx < _transform._numTimesX; ++rx) { + + subRect.left = x; + subRect.top = y; + subRect.setWidth(w); + subRect.setHeight(w); + + if (subRect.intersects(*clipRect)) { + subRect.clip(*clipRect); + subRect.translate(-x, -y); + src.blit(*_targetSurface, basex + x + subRect.left, basey + y + subRect.top, _transform._flip, &subRect, _transform._rgbaMod, subRect.width(), subRect.height(), _transform._blendMode); + + } + + x += w; + } + y += h; + } + } + if (doDelete) { delete clipRect; } -- cgit v1.2.3