diff options
10 files changed, 163 insertions, 194 deletions
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 4a1bfb867d..39691628ab 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -52,17 +52,14 @@ BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) { _renderSurface = new Graphics::Surface(); _blankSurface = new Graphics::Surface(); _drawNum = 1; + _lastFrameIter = _renderQueue.end(); _needsFlip = true; - _spriteBatch = false; - _batchNum = 0; _skipThisFrame = false; - _previousTicket = nullptr; _borderLeft = _borderRight = _borderTop = _borderBottom = 0; _ratioX = _ratioY = 1.0f; _dirtyRect = nullptr; _disableDirtyRects = false; - _tempDisableDirtyRects = 0; if (ConfMan.hasKey("dirty_rects")) { _disableDirtyRects = !ConfMan.getBool("dirty_rects"); } @@ -154,9 +151,6 @@ bool BaseRenderOSystem::indicatorFlip() { } bool BaseRenderOSystem::flip() { - if (_renderQueue.size() > DIRTY_RECT_LIMIT) { - _tempDisableDirtyRects++; - } if (_skipThisFrame) { _skipThisFrame = false; delete _dirtyRect; @@ -164,10 +158,11 @@ bool BaseRenderOSystem::flip() { g_system->updateScreen(); _needsFlip = false; _drawNum = 1; + _lastFrameIter = _renderQueue.end(); addDirtyRect(_renderRect); return true; } - if (!_tempDisableDirtyRects && !_disableDirtyRects) { + if (!_disableDirtyRects) { drawTickets(); } else { // Clear the scale-buffered tickets that wasn't reused. @@ -183,8 +178,8 @@ bool BaseRenderOSystem::flip() { } } } - if (_needsFlip || _disableDirtyRects || _tempDisableDirtyRects) { - if (_disableDirtyRects || _tempDisableDirtyRects) { + if (_needsFlip || _disableDirtyRects) { + if (_disableDirtyRects) { g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); } // g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height()); @@ -194,22 +189,7 @@ bool BaseRenderOSystem::flip() { _needsFlip = false; } _drawNum = 1; - - if (_tempDisableDirtyRects && !_disableDirtyRects) { - _tempDisableDirtyRects--; - if (!_tempDisableDirtyRects) { - Common::Rect screen(_screenRect.top, _screenRect.left, _screenRect.bottom, _screenRect.right); - addDirtyRect(screen); - - // The queue has been ignored but updated, and is guaranteed to be in draw-order when run without dirty-rects. - RenderQueueIterator it = _renderQueue.begin(); - int drawNum = 1; - while (it != _renderQueue.end()) { - (*it)->_drawNum = drawNum++; - ++it; - } - } - } + _lastFrameIter = _renderQueue.end(); return STATUS_OK; } @@ -217,7 +197,7 @@ bool BaseRenderOSystem::flip() { ////////////////////////////////////////////////////////////////////////// bool BaseRenderOSystem::fill(byte r, byte g, byte b, Common::Rect *rect) { _clearColor = _renderSurface->format.ARGBToColor(0xFF, r, g, b); - if (!_disableDirtyRects && !_tempDisableDirtyRects) { + if (!_disableDirtyRects) { return STATUS_OK; } if (!rect) { @@ -278,11 +258,10 @@ Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const { void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) { - if (_tempDisableDirtyRects || _disableDirtyRects) { + if (_disableDirtyRects) { RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform); ticket->_wantsDraw = true; _renderQueue.push_back(ticket); - _previousTicket = ticket; drawFromSurface(ticket); return; } @@ -300,10 +279,6 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S if (owner) { // Fade-tickets are owner-less RenderTicket compare(owner, nullptr, srcRect, dstRect, transform); - compare._batchNum = _batchNum; - if (_spriteBatch) { - _batchNum++; - } RenderQueueIterator it; // Avoid calling end() and operator* every time, when potentially going through // LOTS of tickets. @@ -315,12 +290,7 @@ void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::S if (_disableDirtyRects) { drawFromSurface(compareTicket); } else { - drawFromTicket(compareTicket); - _previousTicket = compareTicket; - } - if (_renderQueue.size() > DIRTY_RECT_LIMIT) { - drawTickets(); - _tempDisableDirtyRects = 3; + drawFromQueuedTicket(it); } return; } @@ -329,57 +299,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 (!_tempDisableDirtyRects && !_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; @@ -397,59 +323,40 @@ void BaseRenderOSystem::invalidateTicketsFromSurface(BaseSurfaceOSystem *surf) { void BaseRenderOSystem::drawFromTicket(RenderTicket *renderTicket) { renderTicket->_wantsDraw = true; - // A new item always has _drawNum == 0 - if (renderTicket->_drawNum == 0) { - // In-order - if (_renderQueue.empty() || _drawNum > (_renderQueue.back())->_drawNum) { - renderTicket->_drawNum = _drawNum++; - _renderQueue.push_back(renderTicket); - addDirtyRect(renderTicket->_dstRect); - ++_lastAddedTicket; - } else { - // Before something - RenderQueueIterator pos; - for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) { - if ((*pos)->_drawNum >= _drawNum) { - break; - } - } - _renderQueue.insert(pos, renderTicket); - renderTicket->_drawNum = _drawNum++; - // Increment the following tickets, so they still are in line - RenderQueueIterator it; - for (it = pos; it != _renderQueue.end(); ++it) { - (*it)->_drawNum++; - (*it)->_wantsDraw = false; - } - addDirtyRect(renderTicket->_dstRect); - _lastAddedTicket = pos; - } + + ++_lastFrameIter; + // In-order + if (_renderQueue.empty() || _lastFrameIter == _renderQueue.end()) { + _lastFrameIter--; + _renderQueue.push_back(renderTicket); + ++_lastFrameIter; + addDirtyRect(renderTicket->_dstRect); + ++_lastAddedTicket; } else { - // Was drawn last round, still in the same order - if (_drawNum == renderTicket->_drawNum) { - _drawNum++; - ++_lastAddedTicket; - } else { - // Remove the ticket from the list - RenderQueueIterator it = _renderQueue.begin(); - while (it != _renderQueue.end()) { - if ((*it) == renderTicket) { - it = _renderQueue.erase(it); - break; - } else { - ++it; - } - } - if (it != _renderQueue.end()) { - // Decreement the following tickets. - for (; it != _renderQueue.end(); ++it) { - (*it)->_drawNum--; - } - } - // Is not in order, so readd it as if it was a new ticket - renderTicket->_drawNum = 0; - drawFromTicket(renderTicket); - } + // Before something + RenderQueueIterator pos = _lastFrameIter; + _renderQueue.insert(pos, renderTicket); + --_lastFrameIter; + addDirtyRect(renderTicket->_dstRect); + _lastAddedTicket = pos; + } +} + +void BaseRenderOSystem::drawFromQueuedTicket(const RenderQueueIterator &ticket) { + RenderTicket *renderTicket = *ticket; + renderTicket->_wantsDraw = true; + + ++_lastFrameIter; + // Was drawn last round, still in the same order + if (*_lastFrameIter == renderTicket) { + _drawNum++; + ++_lastAddedTicket; + } else { + --_lastFrameIter; + // Remove the ticket from the list + _renderQueue.erase(ticket); + // Is not in order, so readd it as if it was a new ticket + drawFromTicket(renderTicket); } } @@ -468,16 +375,13 @@ void BaseRenderOSystem::drawTickets() { // Note: We draw invalid tickets too, otherwise we wouldn't be honouring // the draw request they obviously made BEFORE becoming invalid, either way // we have a copy of their data, so their invalidness won't affect us. - uint32 decrement = 0; while (it != _renderQueue.end()) { if ((*it)->_wantsDraw == false) { RenderTicket *ticket = *it; addDirtyRect((*it)->_dstRect); it = _renderQueue.erase(it); delete ticket; - decrement++; } else { - (*it)->_drawNum -= decrement; ++it; } } @@ -494,9 +398,9 @@ void BaseRenderOSystem::drawTickets() { // Apply the clear-color to the dirty rect. _renderSurface->fillRect(*_dirtyRect, _clearColor); _drawNum = 1; + _lastFrameIter = _renderQueue.end(); for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) { RenderTicket *ticket = *it; - assert(ticket->_drawNum == _drawNum); ++_drawNum; if (ticket->_dstRect.intersects(*_dirtyRect)) { // dstClip is the area we want redrawn. @@ -520,16 +424,13 @@ void BaseRenderOSystem::drawTickets() { it = _renderQueue.begin(); // Clean out the old tickets - decrement = 0; while (it != _renderQueue.end()) { if ((*it)->_isValid == false) { RenderTicket *ticket = *it; addDirtyRect((*it)->_dstRect); it = _renderQueue.erase(it); delete ticket; - decrement++; } else { - (*it)->_drawNum -= decrement; ++it; } } @@ -549,7 +450,7 @@ void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *dstR bool BaseRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) { // This function isn't used outside of indicator-displaying, and thus quite unused in // BaseRenderOSystem when dirty-rects are enabled. - if (!_tempDisableDirtyRects && !_disableDirtyRects && !_indicatorDisplay) { + if (!_disableDirtyRects && !_indicatorDisplay) { error("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet"); } @@ -656,11 +557,11 @@ 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; _drawNum = 1; + _lastFrameIter = _renderQueue.end(); _renderSurface->fillRect(Common::Rect(0, 0, _renderSurface->h, _renderSurface->w), _renderSurface->format.ARGBToColor(255, 0, 0, 0)); g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h); @@ -668,14 +569,10 @@ void BaseRenderOSystem::endSaveLoad() { } bool BaseRenderOSystem::startSpriteBatch() { - _spriteBatch = true; - _batchNum = 1; return STATUS_OK; } bool BaseRenderOSystem::endSpriteBatch() { - _spriteBatch = false; - _batchNum = 0; return STATUS_OK; } diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h index 2ae3b6cfeb..de977916fd 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -62,6 +62,8 @@ public: BaseRenderOSystem(BaseGame *inGame); ~BaseRenderOSystem(); + typedef Common::List<RenderTicket *>::iterator RenderQueueIterator; + Common::String getName() const; bool initRenderer(int width, int height, bool windowed) override; @@ -79,11 +81,16 @@ public: void invalidateTicket(RenderTicket *renderTicket); void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf); /** - * Insert a ticket into the queue, adding a dirty rect if it's - * new, or out-of-order from last draw from the ticket. + * Insert a new ticket into the queue, adding a dirty rect * param renderTicket the ticket to be added. */ void drawFromTicket(RenderTicket *renderTicket); + /** + * Re-insert an existing ticket into the queue, adding a dirty rect + * out-of-order from last draw from the ticket. + * param ticket iterator pointing to the ticket to be added. + */ + void drawFromQueuedTicket(const RenderQueueIterator &ticket); bool setViewport(int left, int top, int right, int bottom) override; bool setViewport(Rect32 *rect) override { return BaseRenderer::setViewport(rect); } @@ -104,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: /** @@ -120,14 +126,13 @@ private: void drawFromSurface(RenderTicket *ticket); // Dirty-rects: void drawFromSurface(RenderTicket *ticket, Common::Rect *dstRect, Common::Rect *clipRect); - typedef Common::List<RenderTicket *>::iterator RenderQueueIterator; Common::Rect *_dirtyRect; Common::List<RenderTicket *> _renderQueue; RenderQueueIterator _lastAddedTicket; - RenderTicket *_previousTicket; bool _needsFlip; uint32 _drawNum; ///< The global number of the current draw-operation. + RenderQueueIterator _lastFrameIter; Common::Rect _renderRect; Graphics::Surface *_renderSurface; Graphics::Surface *_blankSurface; @@ -138,9 +143,6 @@ private: int _borderBottom; bool _disableDirtyRects; - uint32 _tempDisableDirtyRects; - bool _spriteBatch; - uint32 _batchNum; float _ratioX; float _ratioY; uint32 _clearColor; 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 @@ -381,6 +381,14 @@ bool BaseSurfaceOSystem::displayTransform(int x, int y, Rect32 rect, Rect32 newR } ////////////////////////////////////////////////////////////////////////// +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<BaseRenderOSystem *>(_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<BaseRenderOSystem *>(_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 94512eb583..7a926c3e36 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp +++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp @@ -38,11 +38,9 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s _owner(owner), _srcRect(*srcRect), _dstRect(*dstRect), - _drawNum(0), _isValid(true), _wantsDraw(true), _transform(transform) { - _batchNum = 0; if (surf) { _surface = new Graphics::Surface(); _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format); @@ -52,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(); @@ -87,7 +91,6 @@ RenderTicket::~RenderTicket() { bool RenderTicket::operator==(const RenderTicket &t) const { if ((t._owner != _owner) || - (t._batchNum != _batchNum) || (t._transform != _transform) || (t._dstRect != _dstRect) || (t._srcRect != _srcRect) @@ -112,7 +115,19 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface) const { src.setAlphaMode(_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 { @@ -121,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) { @@ -132,7 +147,47 @@ void RenderTicket::drawToSurface(Graphics::Surface *_targetSurface, Common::Rect src.setAlphaMode(_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; } diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.h b/engines/wintermute/base/gfx/osystem/render_ticket.h index 875102d01c..e824c09fe7 100644 --- a/engines/wintermute/base/gfx/osystem/render_ticket.h +++ b/engines/wintermute/base/gfx/osystem/render_ticket.h @@ -52,7 +52,7 @@ class BaseSurfaceOSystem; class RenderTicket { public: RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, TransformStruct transform); - RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0), _transform(TransformStruct()) {} + RenderTicket() : _isValid(true), _wantsDraw(false), _transform(TransformStruct()) {} ~RenderTicket(); const Graphics::Surface *getSurface() const { return _surface; } // Non-dirty-rects: @@ -61,11 +61,9 @@ public: void drawToSurface(Graphics::Surface *_targetSurface, Common::Rect *dstRect, Common::Rect *clipRect) const; Common::Rect _dstRect; - uint32 _batchNum; bool _isValid; bool _wantsDraw; - uint32 _drawNum; TransformStruct _transform; diff --git a/engines/wintermute/graphics/transform_struct.cpp b/engines/wintermute/graphics/transform_struct.cpp index 643c6b413f..822c06f42f 100644 --- a/engines/wintermute/graphics/transform_struct.cpp +++ b/engines/wintermute/graphics/transform_struct.cpp @@ -35,6 +35,8 @@ void TransformStruct::init(Point32 zoom, uint32 angle, Point32 hotspot, bool alp _flip += TransparentSurface::FLIP_H * mirrorX; _flip += TransparentSurface::FLIP_V * mirrorY; _offset = offset; + _numTimesX = 1; + _numTimesY = 1; } TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 rgbaMod, bool mirrorX, bool mirrorY, int32 offsetX, int32 offsetY) { @@ -83,6 +85,19 @@ TransformStruct::TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 h Point32(kDefaultOffsetX, kDefaultOffsetY)); } +TransformStruct::TransformStruct(int32 numTimesX, int32 numTimesY) { + init(Point32(kDefaultZoomX, kDefaultZoomY), + kDefaultAngle, + Point32(kDefaultHotspotX, kDefaultHotspotY), + false, + BLEND_NORMAL, + kDefaultRgbaMod, + false, false, + Point32(kDefaultOffsetX, kDefaultOffsetY)); + _numTimesX = numTimesX; + _numTimesY = numTimesY; +} + TransformStruct::TransformStruct() { init(Point32(kDefaultZoomX, kDefaultZoomY), kDefaultAngle, diff --git a/engines/wintermute/graphics/transform_struct.h b/engines/wintermute/graphics/transform_struct.h index 90a4c1f846..d5a03ea331 100644 --- a/engines/wintermute/graphics/transform_struct.h +++ b/engines/wintermute/graphics/transform_struct.h @@ -51,6 +51,7 @@ public: TransformStruct(float zoomX, float zoomY, uint32 angle, int32 hotspotX, int32 hotspotY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false, int32 offsetX = 0, int32 offsetY = 0); TransformStruct(int32 zoomX, int32 zoomY, TSpriteBlendMode blendMode, uint32 alpha, bool mirrorX = false, bool mirrorY = false); TransformStruct(int32 zoomX, int32 zoomY, uint32 angle, int32 hotspotX = 0, int32 hotspotY = 0); + TransformStruct(int32 numTimesX, int32 numTimesY); TransformStruct(); Point32 _zoom; ///< Zoom; 100 = no zoom @@ -61,6 +62,8 @@ public: TSpriteBlendMode _blendMode; uint32 _rgbaMod; ///< RGBa Point32 _offset; + int32 _numTimesX; + int32 _numTimesY; bool getMirrorX() const; bool getMirrorY() const; @@ -72,7 +75,9 @@ public: compare._offset == _offset && compare._alphaDisable == _alphaDisable && compare._rgbaMod == _rgbaMod && - compare._blendMode == _blendMode + compare._blendMode == _blendMode && + compare._numTimesX == _numTimesX && + compare._numTimesY == _numTimesY ); } diff --git a/engines/wintermute/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp index de4b86a6dd..7c28c139f4 100644 --- a/engines/wintermute/ui/ui_tiled_image.cpp +++ b/engines/wintermute/ui/ui_tiled_image.cpp @@ -75,8 +75,6 @@ bool UITiledImage::display(int x, int y, int width, int height) { int nuColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth; int nuRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight; - int col, row; - _gameRef->_renderer->startSpriteBatch(); // top left/right @@ -88,27 +86,24 @@ bool UITiledImage::display(int x, int y, int width, int height) { _image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downRight); // left/right - int yyy = y + (_upMiddle.bottom - _upMiddle.top); - for (row = 0; row < nuRows; row++) { - _image->_surface->displayTrans(x, yyy, _middleLeft); - _image->_surface->displayTrans(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight); - yyy += tileWidth; + if (nuRows > 0) { + int yyy = y + (_upMiddle.bottom - _upMiddle.top); + _image->_surface->displayTiled(x, yyy, _middleLeft, 1, nuRows); + _image->_surface->displayTiled(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight, 1, nuRows); } // top/bottom - int xxx = x + (_upLeft.right - _upLeft.left); - for (col = 0; col < nuColumns; col++) { - _image->_surface->displayTrans(xxx, y, _upMiddle); - _image->_surface->displayTrans(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle); - xxx += tileWidth; + if (nuColumns > 0) { + int xxx = x + (_upLeft.right - _upLeft.left); + _image->_surface->displayTiled(xxx, y, _upMiddle, nuColumns, 1); + _image->_surface->displayTiled(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle, nuColumns, 1); } // tiles if (nuRows > 0 && nuColumns > 0) { - yyy = y + (_upMiddle.bottom - _upMiddle.top); - xxx = x + (_upLeft.right - _upLeft.left); - _image->_surface->displayTrans(xxx, yyy, _middleMiddle); - _image->_surface->repeatLastDisplayOp(tileWidth, tileWidth, nuColumns, nuRows); + int yyy = y + (_upMiddle.bottom - _upMiddle.top); + int xxx = x + (_upLeft.right - _upLeft.left); + _image->_surface->displayTiled(xxx, yyy, _middleMiddle, nuColumns, nuRows); } _gameRef->_renderer->endSpriteBatch(); |