mirror of
https://github.com/scummvm/scummvm.git
synced 2026-05-21 05:40:43 +00:00
BACKENDS: ATARI: Additional fixes for cursor background
- leftovers after highlighted dirty rectangle - not updating _surface if moving to fast left/right from screen borders (_width == _srcRect.width()) - not drawing cursor if repeatedly intersecting with a refreshing dirty rect - leftover rectangle when leaving game overlay to the launcher - massive simplification
This commit is contained in:
@@ -70,7 +70,7 @@ void Cursor::update() {
|
||||
_dstRect.right * dstBitsPerPixel / 8, // fake 4bpp by 8bpp's width/2
|
||||
_dstRect.bottom);
|
||||
|
||||
// this is used only in intersects() and flushBackground()
|
||||
// this is used only in flushBackground()
|
||||
_alignedDstRect = _manager->alignRect(
|
||||
_dstRect.left + _xOffset,
|
||||
_dstRect.top,
|
||||
@@ -201,8 +201,14 @@ Common::Rect Cursor::flushBackground(const Common::Rect &alignedRect, bool direc
|
||||
return _savedRect;
|
||||
|
||||
if (!alignedRect.isEmpty() && alignedRect.contains(_alignedDstRect)) {
|
||||
// better would be _visibilityChanged but update() ignores it
|
||||
_positionChanged = true;
|
||||
|
||||
_savedRect = Common::Rect();
|
||||
} else if (alignedRect.isEmpty() || alignedRect.intersects(_alignedDstRect)) {
|
||||
// better would be _visibilityChanged but update() ignores it
|
||||
_positionChanged = true;
|
||||
|
||||
if (directRendering)
|
||||
restoreBackground();
|
||||
else
|
||||
@@ -232,17 +238,15 @@ void Cursor::saveBackground() {
|
||||
_savedBackground.copyRectToSurface(dstSurface, 0, 0, _savedRect);
|
||||
}
|
||||
|
||||
bool Cursor::draw(bool force) {
|
||||
if (!isVisible() || (!force && !isChanged()))
|
||||
return false;
|
||||
|
||||
void Cursor::draw() {
|
||||
Graphics::Surface &dstSurface = *_parentScreen->offsettedSurf;
|
||||
const int dstBitsPerPixel = _manager->getBitsPerPixel(dstSurface.format);
|
||||
|
||||
//atari_debug("Cursor::draw: %d %d %d %d", _dstRect.left, _dstRect.top, _dstRect.width(), _dstRect.height());
|
||||
|
||||
if (_surfaceChanged || _width != _srcRect.width()) {
|
||||
// TODO: check for change, not just different width so it's not called over and over again when clipped ...
|
||||
if (_surfaceChanged || _srcRect != _previousSrcRect) {
|
||||
_previousSrcRect = _srcRect;
|
||||
|
||||
// TODO: some sort of in-place C2P directly into convertSurfaceTo() ...
|
||||
convertSurfaceTo(dstSurface.format);
|
||||
{
|
||||
@@ -270,7 +274,6 @@ bool Cursor::draw(bool force) {
|
||||
Common::Rect(0, _srcRect.top, _surface.w, _srcRect.bottom));
|
||||
|
||||
_visibilityChanged = _positionChanged = _surfaceChanged = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cursor::restoreBackground() {
|
||||
|
||||
@@ -47,7 +47,7 @@ struct Cursor {
|
||||
_surfaceChanged = true;
|
||||
_visibilityChanged = false;
|
||||
|
||||
_savedRect = _alignedDstRect = Common::Rect();
|
||||
_savedRect = _previousSrcRect = _alignedDstRect = Common::Rect();
|
||||
}
|
||||
|
||||
// updates outOfScreen OR srcRect/dstRect (only if visible/needed)
|
||||
@@ -97,13 +97,9 @@ struct Cursor {
|
||||
return _positionChanged || _surfaceChanged || _visibilityChanged;
|
||||
}
|
||||
|
||||
bool intersects(const Common::Rect &alignedRect) const {
|
||||
return alignedRect.intersects(_alignedDstRect);
|
||||
}
|
||||
|
||||
Common::Rect flushBackground(const Common::Rect &alignedRect, bool directRendering);
|
||||
void saveBackground();
|
||||
bool draw(bool force);
|
||||
void draw();
|
||||
|
||||
private:
|
||||
void restoreBackground();
|
||||
@@ -126,8 +122,9 @@ private:
|
||||
Common::Rect _srcRect;
|
||||
Common::Rect _dstRect;
|
||||
|
||||
Graphics::Surface _savedBackground; // used by direct rendering
|
||||
Graphics::Surface _savedBackground;
|
||||
Common::Rect _savedRect;
|
||||
Common::Rect _previousSrcRect;
|
||||
Common::Rect _alignedDstRect;
|
||||
|
||||
// related to 'surface'
|
||||
|
||||
@@ -407,6 +407,7 @@ OSystem::TransactionError AtariGraphicsManager::endGFXTransaction() {
|
||||
atari_debug("endGFXTransaction");
|
||||
|
||||
_pendingState.inTransaction = false;
|
||||
_ignoreCursorChanges = false;
|
||||
|
||||
int error = OSystem::TransactionError::kTransactionSuccess;
|
||||
bool hasPendingGraphicsMode = false;
|
||||
@@ -914,7 +915,10 @@ Graphics::Surface *AtariGraphicsManager::lockOverlay() {
|
||||
}
|
||||
|
||||
bool AtariGraphicsManager::showMouse(bool visible) {
|
||||
//atari_debug("showMouse: %d", visible);
|
||||
//atari_debug("showMouse: %d; ignored: %d", visible, _ignoreCursorChanges);
|
||||
|
||||
if (_ignoreCursorChanges)
|
||||
return visible;
|
||||
|
||||
bool lastOverlay, lastFront, lastBack1 = false;
|
||||
|
||||
@@ -951,7 +955,11 @@ void AtariGraphicsManager::warpMouse(int x, int y) {
|
||||
|
||||
void AtariGraphicsManager::setMouseCursor(const void *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor,
|
||||
bool dontScale, const Graphics::PixelFormat *format, const byte *mask) {
|
||||
//atari_debug("setMouseCursor: %d, %d, %d, %d, %d, %d", w, h, hotspotX, hotspotY, keycolor, format ? format->bytesPerPixel : 1);
|
||||
//atari_debug("setMouseCursor: %d, %d, %d, %d, %d, %d; ignored: %d",
|
||||
// w, h, hotspotX, hotspotY, keycolor, format ? format->bytesPerPixel : 1, _ignoreCursorChanges);
|
||||
|
||||
if (_ignoreCursorChanges)
|
||||
return;
|
||||
|
||||
if (mask)
|
||||
atari_warning("AtariGraphicsManager::setMouseCursor: Masks are not supported");
|
||||
@@ -1001,6 +1009,8 @@ bool AtariGraphicsManager::notifyEvent(const Common::Event &event) {
|
||||
surf.fillRect(Common::Rect(surf.w, surf.h), 0);
|
||||
|
||||
_ignoreHideOverlay = true;
|
||||
// gui manager would want to hide overlay, set game cursor etc
|
||||
_ignoreCursorChanges = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -1092,10 +1102,9 @@ bool AtariGraphicsManager::updateScreenInternal(Screen *dstScreen, const Graphic
|
||||
lockSuperBlitter();
|
||||
|
||||
if (cursor.isChanged()) {
|
||||
const Common::Rect rect = cursor.flushBackground(Common::Rect(), directRendering);
|
||||
// 'updated' is skipped in direct drawing but in such case there's never triple-buffering active
|
||||
if (!directRendering && !rect.isEmpty()) {
|
||||
copyRectToSurface(*dstSurface, srcSurface, rect.left, rect.top, rect);
|
||||
const Common::Rect cursorBackgroundRect = cursor.flushBackground(Common::Rect(), directRendering);
|
||||
if (!cursorBackgroundRect.isEmpty()) {
|
||||
copyRectToSurface(*dstSurface, srcSurface, cursorBackgroundRect.left, cursorBackgroundRect.top, cursorBackgroundRect);
|
||||
updated |= true;
|
||||
}
|
||||
}
|
||||
@@ -1103,36 +1112,24 @@ bool AtariGraphicsManager::updateScreenInternal(Screen *dstScreen, const Graphic
|
||||
// update cursor rects and visibility flag (if out of screen)
|
||||
cursor.update();
|
||||
|
||||
const bool cursorDrawEnabled = cursor.isVisible();
|
||||
bool forceCursorDraw = cursorDrawEnabled && (dstScreen->fullRedraw || cursor.isChanged());
|
||||
const bool drawCursor = cursor.isVisible() && (dstScreen->fullRedraw || cursor.isChanged());
|
||||
|
||||
for (auto it = dirtyRects.begin(); it != dirtyRects.end(); ++it) {
|
||||
if (cursorDrawEnabled && !forceCursorDraw) {
|
||||
forceCursorDraw = cursor.intersects(*it);
|
||||
// any '*it' shall never intersect cursor background; that was handled in addDirtyRect()
|
||||
if (forceCursorDraw) {
|
||||
const Common::Rect rect = cursor.flushBackground(*it, directRendering);
|
||||
// 'updated' is skipped in direct drawing but in such case there's never triple-buffering active
|
||||
if (!directRendering && !rect.isEmpty()) {
|
||||
copyRectToSurface(*dstSurface, srcSurface, rect.left, rect.top, rect);
|
||||
updated |= true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!directRendering) {
|
||||
if (!directRendering) {
|
||||
for (auto it = dirtyRects.begin(); it != dirtyRects.end(); ++it) {
|
||||
copyRectToSurface(*dstSurface, srcSurface, it->left, it->top, *it);
|
||||
updated |= true;
|
||||
}
|
||||
}
|
||||
|
||||
if (directRendering && (forceCursorDraw || cursor.isChanged()))
|
||||
updated |= !dirtyRects.empty();
|
||||
} else if (drawCursor) {
|
||||
cursor.saveBackground();
|
||||
}
|
||||
|
||||
// unlock here because cursor.draw() is a software blit
|
||||
unlockSuperBlitter();
|
||||
|
||||
updated |= cursor.draw(forceCursorDraw);
|
||||
if (drawCursor) {
|
||||
cursor.draw();
|
||||
updated |= true;
|
||||
}
|
||||
|
||||
dstScreen->clearDirtyRects();
|
||||
|
||||
|
||||
@@ -245,6 +245,7 @@ private:
|
||||
int _overlayState = kOverlayHidden;
|
||||
bool _ignoreHideOverlay = true;
|
||||
Graphics::Surface _overlaySurface;
|
||||
bool _ignoreCursorChanges = false;
|
||||
|
||||
Palette _palette;
|
||||
Palette _overlayPalette;
|
||||
|
||||
@@ -159,9 +159,10 @@ void Screen::addDirtyRect(const Graphics::Surface &srcSurface, int x, int y, int
|
||||
|
||||
dirtyRects.insert(alignedRect);
|
||||
|
||||
// this takes care of a dirty rect touching the cursor background; however there's still
|
||||
// the case when a dirty rect touches the cursor itself: in such case the cursor background
|
||||
// will be restored one more time while iterating over dirty rects
|
||||
// Check whether the cursor background intersects the dirty rect. Has to be done here,
|
||||
// before the actual drawing (especially in case of direct rendering). There's one more
|
||||
// check in AtariGraphicsManager::updateScreenInternal for the case when there are no
|
||||
// dirty rectangles but the cursor itself has changed.
|
||||
const Common::Rect cursorBackgroundRect = cursor.flushBackground(alignedRect, directRendering);
|
||||
if (!cursorBackgroundRect.isEmpty()) {
|
||||
dirtyRects.insert(cursorBackgroundRect);
|
||||
|
||||
@@ -351,6 +351,8 @@ void OSystem_Atari::initBackend() {
|
||||
}
|
||||
|
||||
void OSystem_Atari::engineInit() {
|
||||
//atari_debug("engineInit");
|
||||
|
||||
g_gameEngineActive = true;
|
||||
|
||||
const Common::ConfigManager::Domain *activeDomain = ConfMan.getActiveDomain();
|
||||
@@ -381,6 +383,8 @@ void OSystem_Atari::engineInit() {
|
||||
}
|
||||
|
||||
void OSystem_Atari::engineDone() {
|
||||
//atari_debug("engineDone");
|
||||
|
||||
g_gameEngineActive = false;
|
||||
g_unalignedPitch = false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user