mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-22 09:49:11 +00:00
WINTERMUTE: Add displayTiled function to replace repeatLastDraw
This avoids queueing many tickets for a UITiledImage, replacing them by a single tiled ticket.
This commit is contained in:
parent
4e12600d70
commit
057b01951a
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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<RenderTicket *> _renderQueue;
|
||||
RenderQueueIterator _lastAddedTicket;
|
||||
RenderTicket *_previousTicket;
|
||||
|
||||
bool _needsFlip;
|
||||
uint32 _drawNum; ///< The global number of the current draw-operation.
|
||||
|
@ -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<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();
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user