[Scummvm-git-logs] scummvm master -> b39f380b8e73f9d17abe3f2746a1a69500f504cd
sev-
noreply at scummvm.org
Sun Apr 5 22:32:22 UTC 2026
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
43f42b8db2 GRAPHICS: Split out dirty rectangle tracking from Graphics::Screen
5576fe97e8 3DS: Improve dirty rectangle tracking for emulated pixel formats
b39f380b8e 3DS: Implement OSystem::fillScreen()
Commit: 43f42b8db22798100dc278cb0422f92113dd6d14
https://github.com/scummvm/scummvm/commit/43f42b8db22798100dc278cb0422f92113dd6d14
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2026-04-06T00:32:17+02:00
Commit Message:
GRAPHICS: Split out dirty rectangle tracking from Graphics::Screen
Changed paths:
A graphics/dirtyrects.cpp
A graphics/dirtyrects.h
engines/petka/objects/object_case.cpp
engines/petka/video.cpp
engines/petka/video.h
graphics/module.mk
graphics/screen.cpp
graphics/screen.h
diff --git a/engines/petka/objects/object_case.cpp b/engines/petka/objects/object_case.cpp
index 4a89e385b4b..ec8a6001223 100644
--- a/engines/petka/objects/object_case.cpp
+++ b/engines/petka/objects/object_case.cpp
@@ -103,10 +103,10 @@ void QObjectCase::draw() {
QSystem *sys = g_vm->getQSystem();
- const Common::List<Common::Rect> &dirty = g_vm->videoSystem()->rects();
+ const Graphics::DirtyRectList &dirty = g_vm->videoSystem()->rects();
const Common::Array<Common::Rect> &mskRects = flc->getMskRects();
- for (Common::List<Common::Rect>::const_iterator it = dirty.begin(); it != dirty.end(); ++it) {
+ for (Graphics::DirtyRectList::const_iterator it = dirty.begin(); it != dirty.end(); ++it) {
for (uint i = 0; i < mskRects.size(); ++i) {
Common::Rect destRect = mskRects[i].findIntersectingRect(*it);
Common::Rect srcRect = destRect;
diff --git a/engines/petka/video.cpp b/engines/petka/video.cpp
index 5cc2ef1155d..5f2dd779c1c 100644
--- a/engines/petka/video.cpp
+++ b/engines/petka/video.cpp
@@ -51,13 +51,13 @@ void VideoSystem::update() {
interface->update(time - _time);
- mergeDirtyRects();
+ _dirtyRects.merge();
_allowAddingRects = false;
interface->draw();
_allowAddingRects = true;
- for (Common::Rect &r : _dirtyRects) {
+ for (const Common::Rect &r : _dirtyRects) {
const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
g_system->copyRectToScreen(srcP, pitch, r.left, r.top, r.width(), r.height());
}
@@ -103,7 +103,7 @@ void VideoSystem::addDirtyMskRects(FlicDecoder &flc) {
addDirtyMskRects(Common::Point(0, 0), flc);
}
-const Common::List<Common::Rect> &VideoSystem::rects() const {
+const Graphics::DirtyRectList &VideoSystem::rects() const {
return _dirtyRects;
}
diff --git a/engines/petka/video.h b/engines/petka/video.h
index 1dce23b3cfb..8fe55fc3825 100644
--- a/engines/petka/video.h
+++ b/engines/petka/video.h
@@ -22,6 +22,7 @@
#ifndef PETKA_SCREEN_H
#define PETKA_SCREEN_H
+#include "graphics/dirtyrects.h"
#include "graphics/screen.h"
namespace Petka {
@@ -46,7 +47,7 @@ public:
void setShake(bool shake);
- const Common::List<Common::Rect> &rects() const;
+ const Graphics::DirtyRectList &rects() const;
private:
PetkaEngine &_vm;
diff --git a/graphics/dirtyrects.cpp b/graphics/dirtyrects.cpp
new file mode 100644
index 00000000000..96ca17963e1
--- /dev/null
+++ b/graphics/dirtyrects.cpp
@@ -0,0 +1,55 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "graphics/dirtyrects.h"
+
+namespace Graphics {
+
+void DirtyRectList::merge() {
+ Common::List<Common::Rect>::iterator rOuter, rInner;
+
+ // Process the dirty rect list to find any rects to merge
+ for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
+ rInner = rOuter;
+ while (++rInner != _dirtyRects.end()) {
+
+ if ((*rOuter).intersects(*rInner)) {
+ // These two rectangles overlap, so merge them
+ unionRectangle(*rOuter, *rOuter, *rInner);
+
+ // remove the inner rect from the list
+ _dirtyRects.erase(rInner);
+
+ // move back to beginning of list
+ rInner = rOuter;
+ }
+ }
+ }
+}
+
+bool DirtyRectList::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
+ destRect = src1;
+ destRect.extend(src2);
+
+ return !destRect.isEmpty();
+}
+
+} // End of namespace Graphics
diff --git a/graphics/dirtyrects.h b/graphics/dirtyrects.h
new file mode 100644
index 00000000000..2205a5429df
--- /dev/null
+++ b/graphics/dirtyrects.h
@@ -0,0 +1,110 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef GRAPHICS_DIRTYRECTS_H
+#define GRAPHICS_DIRTYRECTS_H
+
+#include "common/list.h"
+#include "common/rect.h"
+
+namespace Graphics {
+
+/**
+ * @defgroup graphics_dirtyrects DirtyRects
+ * @ingroup graphics
+ *
+ * @brief DirtyRectList class for tracking dirty rectangles.
+ *
+ * @{
+ */
+
+/**
+ * This class keeps track of any areas of a surface that are updated
+ * by drawing calls.
+ */
+class DirtyRectList {
+public:
+ typedef Common::List<Common::Rect>::const_iterator const_iterator; /*!< Const-qualified list iterator. */
+
+protected:
+ /**
+ * List of affected areas of the screen
+ */
+ Common::List<Common::Rect> _dirtyRects;
+
+protected:
+ /**
+ * Returns the union of two dirty area rectangles
+ */
+ bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
+
+public:
+ /**
+ * Merges together overlapping dirty areas of the screen
+ */
+ void merge();
+
+ /**
+ * Returns true if there are no pending screen updates (dirty areas)
+ */
+ bool empty() const { return _dirtyRects.empty(); }
+
+ /**
+ * Clear the current dirty rects list
+ */
+ void clear() { _dirtyRects.clear(); }
+
+ /**
+ * Adds a rectangle to the list of modified areas of the screen during the
+ * current frame
+ */
+ template<class... TArgs>
+ void emplace_back(TArgs &&...args) { _dirtyRects.emplace_back(Common::forward<TArgs>(args)...); }
+
+ /**
+ * Adds a rectangle to the list of modified areas of the screen during the
+ * current frame
+ */
+ void push_back(const Common::Rect &r) { _dirtyRects.push_back(r); }
+
+ /**
+ * Adds a rectangle to the list of modified areas of the screen during the
+ * current frame
+ */
+ void push_back(Common::Rect &&r) { _dirtyRects.push_back(Common::move(r)); }
+
+ /** Return a const iterator to the start of the list.
+ * This can be used, for example, to iterate from the first element
+ * of the list to the last element of the list.
+ */
+ const_iterator begin() const {
+ return _dirtyRects.begin();
+ }
+
+ /** Return a const iterator to the end of the list. */
+ const_iterator end() const {
+ return _dirtyRects.end();
+ }
+};
+ /** @} */
+} // End of namespace Graphics
+
+#endif
diff --git a/graphics/module.mk b/graphics/module.mk
index 2b7ecb44f63..5e4a60e89a2 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -9,6 +9,7 @@ MODULE_OBJS := \
blit/blit-scale.o \
color_quantizer.o \
cursorman.o \
+ dirtyrects.o \
font.o \
fontman.o \
fonts/amigafont.o \
diff --git a/graphics/screen.cpp b/graphics/screen.cpp
index be81655b064..f529790cd5e 100644
--- a/graphics/screen.cpp
+++ b/graphics/screen.cpp
@@ -40,10 +40,10 @@ Screen::Screen(int width, int height, PixelFormat pixelFormat): ManagedSurface()
void Screen::update() {
// Merge the dirty rects
- mergeDirtyRects();
+ _dirtyRects.merge();
// Loop through copying dirty areas to the physical screen
- Common::List<Common::Rect>::iterator i;
+ DirtyRectList::const_iterator i;
for (i = _dirtyRects.begin(); i != _dirtyRects.end(); ++i) {
const Common::Rect &r = *i;
const byte *srcP = (const byte *)getBasePtr(r.left, r.top);
@@ -75,35 +75,6 @@ void Screen::makeAllDirty() {
addDirtyRect(Common::Rect(0, 0, this->w, this->h));
}
-void Screen::mergeDirtyRects() {
- Common::List<Common::Rect>::iterator rOuter, rInner;
-
- // Process the dirty rect list to find any rects to merge
- for (rOuter = _dirtyRects.begin(); rOuter != _dirtyRects.end(); ++rOuter) {
- rInner = rOuter;
- while (++rInner != _dirtyRects.end()) {
-
- if ((*rOuter).intersects(*rInner)) {
- // These two rectangles overlap, so merge them
- unionRectangle(*rOuter, *rOuter, *rInner);
-
- // remove the inner rect from the list
- _dirtyRects.erase(rInner);
-
- // move back to beginning of list
- rInner = rOuter;
- }
- }
- }
-}
-
-bool Screen::unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2) {
- destRect = src1;
- destRect.extend(src2);
-
- return !destRect.isEmpty();
-}
-
void Screen::getPalette(byte palette[PALETTE_SIZE]) {
assert(format.bytesPerPixel == 1);
g_system->getPaletteManager()->grabPalette(palette, 0, PALETTE_COUNT);
diff --git a/graphics/screen.h b/graphics/screen.h
index 67d04f81c6e..5018afa8d62 100644
--- a/graphics/screen.h
+++ b/graphics/screen.h
@@ -23,10 +23,9 @@
#define GRAPHICS_SCREEN_H
#include "graphics/managed_surface.h"
+#include "graphics/dirtyrects.h"
#include "graphics/palette.h"
#include "graphics/pixelformat.h"
-#include "common/list.h"
-#include "common/rect.h"
namespace Graphics {
@@ -50,17 +49,8 @@ protected:
/**
* List of affected areas of the screen
*/
- Common::List<Common::Rect> _dirtyRects;
-protected:
- /**
- * Merges together overlapping dirty areas of the screen
- */
- void mergeDirtyRects();
+ DirtyRectList _dirtyRects;
- /**
- * Returns the union of two dirty area rectangles
- */
- bool unionRectangle(Common::Rect &destRect, const Common::Rect &src1, const Common::Rect &src2);
public:
Screen();
Screen(int width, int height);
Commit: 5576fe97e8175b8ecdad6561d6b46b7383bf26e4
https://github.com/scummvm/scummvm/commit/5576fe97e8175b8ecdad6561d6b46b7383bf26e4
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2026-04-06T00:32:17+02:00
Commit Message:
3DS: Improve dirty rectangle tracking for emulated pixel formats
Changed paths:
backends/platform/3ds/osystem-graphics.cpp
backends/platform/3ds/osystem.cpp
backends/platform/3ds/osystem.h
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index bfc9e62d097..6009f99d055 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -355,7 +355,9 @@ void OSystem_3DS::setPalette(const byte *colors, uint start, uint num) {
assert(start + num <= 256);
memcpy(_palette + 3 * start, colors, 3 * num);
Graphics::convertPaletteToMap(_paletteMap + start, colors, num, _modeCLUT8.surfaceFormat);
- _gameTextureDirty = true;
+
+ // Palette changes invalidate the entire surface
+ _dirtyRects.emplace_back(getWidth(), getHeight());
}
void OSystem_3DS::grabPalette(byte *colors, uint start, uint num) const {
@@ -394,41 +396,29 @@ void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
}
_gameScreen.copyRectToSurface(buf, pitch, x, y, w, h);
-
- if (_pfGame == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) {
- byte *dst = (byte *)_gameTopTexture.getBasePtr(x, y);
- copyRect555To5551(dst, (const byte *)buf, _gameTopTexture.pitch, pitch, w, h);
- } else if (_gfxState.gfxMode == &_modeCLUT8) {
- byte *dst = (byte *)_gameTopTexture.getBasePtr(x, y);
- Graphics::crossBlitMap(dst, (const byte *)buf, _gameTopTexture.pitch, pitch,
- w, h, _gameTopTexture.format.bytesPerPixel, _paletteMap);
- } else {
- byte *dst = (byte *)_gameTopTexture.getBasePtr(x, y);
- Graphics::crossBlit(dst, (const byte *)buf, _gameTopTexture.pitch, pitch,
- w, h, _gameTopTexture.format, _pfGame);
- }
-
- _gameTopTexture.markDirty();
+ _dirtyRects.emplace_back(x, y, x + w, y + h);
}
void OSystem_3DS::flushGameScreen() {
- if (_pfGame == _gameTopTexture.format) {
+ if (_pfGame == _gameTopTexture.format)
return;
- } else if (_pfGame == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) {
- const byte *src = (const byte *)_gameScreen.getPixels();
- byte *dst = (byte *)_gameTopTexture.getPixels();
- copyRect555To5551(dst, src, _gameTopTexture.pitch, _gameScreen.pitch,
- _gameScreen.w, _gameScreen.h);
- } else if (_gfxState.gfxMode == &_modeCLUT8) {
- const byte *src = (const byte *)_gameScreen.getPixels();
- byte *dst = (byte *)_gameTopTexture.getPixels();
- Graphics::crossBlitMap(dst, src, _gameTopTexture.pitch, _gameScreen.pitch,
- _gameScreen.w, _gameScreen.h, _gameTopTexture.format.bytesPerPixel, _paletteMap);
- } else {
- const byte *src = (const byte *)_gameScreen.getPixels();
- byte *dst = (byte *)_gameTopTexture.getPixels();
- Graphics::crossBlit(dst, src, _gameTopTexture.pitch, _gameScreen.pitch,
- _gameScreen.w, _gameScreen.h, _gameTopTexture.format, _pfGame);
+
+ _dirtyRects.merge();
+
+ for (const Common::Rect &r : _dirtyRects) {
+ const byte *src = (const byte *)_gameScreen.getBasePtr(r.left, r.top);
+ byte *dst = (byte *)_gameTopTexture.getBasePtr(r.left, r.top);
+
+ if (_pfGame == Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0)) {
+ copyRect555To5551(dst, src, _gameTopTexture.pitch, _gameScreen.pitch,
+ r.width(), r.height());
+ } else if (_gfxState.gfxMode == &_modeCLUT8) {
+ Graphics::crossBlitMap(dst, src, _gameTopTexture.pitch, _gameScreen.pitch,
+ r.width(), r.height(), _gameTopTexture.format.bytesPerPixel, _paletteMap);
+ } else {
+ Graphics::crossBlit(dst, src, _gameTopTexture.pitch, _gameScreen.pitch,
+ r.width(), r.height(), _gameTopTexture.format, _pfGame);
+ }
}
_gameTopTexture.markDirty();
@@ -445,7 +435,7 @@ void OSystem_3DS::unlockScreen() {
if (_pfGame == _gameTopTexture.format)
_gameTopTexture.markDirty();
else
- _gameTextureDirty = true;
+ _dirtyRects.emplace_back(getWidth(), getHeight());
}
void OSystem_3DS::updateScreen() {
@@ -453,9 +443,9 @@ void OSystem_3DS::updateScreen() {
return;
}
- if (_gameTextureDirty) {
+ if (!_dirtyRects.empty()) {
flushGameScreen();
- _gameTextureDirty = false;
+ _dirtyRects.clear();
}
// updateFocus();
diff --git a/backends/platform/3ds/osystem.cpp b/backends/platform/3ds/osystem.cpp
index a152d5c084b..137a5b1d5b5 100644
--- a/backends/platform/3ds/osystem.cpp
+++ b/backends/platform/3ds/osystem.cpp
@@ -77,7 +77,6 @@ OSystem_3DS::OSystem_3DS():
_magY(0),
_magWidth(400),
_magHeight(240),
- _gameTextureDirty(false),
_filteringEnabled(true),
_overlayVisible(false),
_overlayInGUI(false),
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 962f981a32b..78e02582a05 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -25,6 +25,7 @@
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h
#include "backends/base-backend.h"
+#include "graphics/dirtyrects.h"
#include "graphics/paletteman.h"
#include "base/main.h"
#include "audio/mixer_intern.h"
@@ -236,7 +237,7 @@ private:
uint32 _paletteMap[256];
Graphics::Surface _gameScreen;
- bool _gameTextureDirty;
+ Graphics::DirtyRectList _dirtyRects;
Sprite _gameTopTexture;
Sprite _gameBottomTexture;
Sprite _overlay;
Commit: b39f380b8e73f9d17abe3f2746a1a69500f504cd
https://github.com/scummvm/scummvm/commit/b39f380b8e73f9d17abe3f2746a1a69500f504cd
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2026-04-06T00:32:17+02:00
Commit Message:
3DS: Implement OSystem::fillScreen()
Changed paths:
backends/platform/3ds/osystem-graphics.cpp
backends/platform/3ds/osystem.h
diff --git a/backends/platform/3ds/osystem-graphics.cpp b/backends/platform/3ds/osystem-graphics.cpp
index 6009f99d055..f1736aa30af 100644
--- a/backends/platform/3ds/osystem-graphics.cpp
+++ b/backends/platform/3ds/osystem-graphics.cpp
@@ -387,6 +387,21 @@ static void copyRect555To5551(byte *dst, const byte *src, const uint dstPitch, c
}
}
+void OSystem_3DS::fillScreen(uint32 col) {
+ fillScreen(Common::Rect(getWidth(), getHeight()), col);
+}
+
+void OSystem_3DS::fillScreen(const Common::Rect &r, uint32 col) {
+ if (_pfGame == _gameTopTexture.format) {
+ _gameTopTexture.fillRect(r, col);
+ _gameTopTexture.markDirty();
+ return;
+ }
+
+ _gameScreen.fillRect(r, col);
+ _dirtyRects.push_back(r);
+}
+
void OSystem_3DS::copyRectToScreen(const void *buf, int pitch, int x,
int y, int w, int h) {
if (_pfGame == _gameTopTexture.format) {
diff --git a/backends/platform/3ds/osystem.h b/backends/platform/3ds/osystem.h
index 78e02582a05..8eddd741b4f 100644
--- a/backends/platform/3ds/osystem.h
+++ b/backends/platform/3ds/osystem.h
@@ -160,6 +160,8 @@ public:
int h);
Graphics::Surface *lockScreen();
void unlockScreen();
+ void fillScreen(uint32 col);
+ void fillScreen(const Common::Rect &r, uint32 col);
void updateScreen();
void setShakePos(int shakeXOffset, int shakeYOffset);
void setFocusRectangle(const Common::Rect &rect);
More information about the Scummvm-git-logs
mailing list