[Scummvm-git-logs] scummvm master -> 051ff0ed9db0c80cd8bd238ea858c71b6dd05097

aquadran noreply at scummvm.org
Thu Jun 12 04:35:35 UTC 2025


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
051ff0ed9d WINTERMUTE: Reduce direct access to surface pixel buffers


Commit: 051ff0ed9db0c80cd8bd238ea858c71b6dd05097
    https://github.com/scummvm/scummvm/commit/051ff0ed9db0c80cd8bd238ea858c71b6dd05097
Author: Cameron Cawley (ccawley2011 at gmail.com)
Date: 2025-06-12T06:35:31+02:00

Commit Message:
WINTERMUTE: Reduce direct access to surface pixel buffers

Changed paths:
    engines/wintermute/base/font/base_font_truetype.cpp
    engines/wintermute/base/gfx/base_image.cpp
    engines/wintermute/base/gfx/base_image.h
    engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
    engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
    engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
    engines/wintermute/base/gfx/osystem/base_surface_osystem.h
    engines/wintermute/base/gfx/osystem/render_ticket.cpp
    engines/wintermute/video/video_theora_player.cpp
    engines/wintermute/video/video_theora_player.h


diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
index 26b6e291d4b..69063d6c4f8 100644
--- a/engines/wintermute/base/font/base_font_truetype.cpp
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -298,7 +298,9 @@ BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width,
 		Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat();
 		uint32 *pixels = (uint32 *)surface->getPixels();
 
-		// This is a Surface we created ourselves, so no empty space between rows.
+		assert(surface->pitch == surface->w * 4);
+		assert(surface->format.bytesPerPixel == 4);
+
 		for (int i = 0; i < surface->w * surface->h; ++i) {
 			uint8 a, r, g, b;
 			format.colorToRGB(*pixels, r, g, b);
diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp
index b8fb3267c0a..aece1331ca2 100644
--- a/engines/wintermute/base/gfx/base_image.cpp
+++ b/engines/wintermute/base/gfx/base_image.cpp
@@ -91,16 +91,6 @@ bool BaseImage::loadFile(const Common::String &filename) {
 	return true;
 }
 
-byte BaseImage::getAlphaAt(int x, int y) const {
-	if (!_surface) {
-		return 0xFF;
-	}
-	uint32 color = *(const uint32 *)_surface->getBasePtr(x, y);
-	byte r, g, b, a;
-	_surface->format.colorToARGB(color, a, r, g, b);
-	return a;
-}
-
 //////////////////////////////////////////////////////////////////////////
 bool BaseImage::saveBMPFile(const Common::String &filename) const {
 	Common::WriteStream *stream = openSfmFileForWrite(filename);
diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h
index a5f309573b4..119089f3002 100644
--- a/engines/wintermute/base/gfx/base_image.h
+++ b/engines/wintermute/base/gfx/base_image.h
@@ -58,7 +58,6 @@ public:
 	uint16 getPaletteCount() const {
 		return _paletteCount;
 	}
-	byte getAlphaAt(int x, int y) const;
 	bool writeBMPToStream(Common::WriteStream *stream) const;
 	bool saveBMPFile(const Common::String &filename) const;
 	void copyFrom(const Graphics::Surface *surface, int newWidth = 0, int newHeight = 0, byte flip = 0);
diff --git a/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp b/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
index 692f66164eb..25845f3b106 100644
--- a/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
+++ b/engines/wintermute/base/gfx/opengl/base_surface_opengl3d.cpp
@@ -60,8 +60,7 @@ bool BaseSurfaceOpenGL3D::invalidate() {
 bool BaseSurfaceOpenGL3D::isTransparentAt(int x, int y) {
 	prepareToDraw();
 
-	uint8 alpha = reinterpret_cast<uint8 *>(_imageData->getPixels())[y * _width * 4 + x * 4 + 3];
-	return alpha < 128;
+	return isTransparentAtLite(x, y);
 }
 
 bool BaseSurfaceOpenGL3D::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, Graphics::TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
index d1fca551cad..bbf61904d7e 100644
--- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -143,14 +143,14 @@ bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) {
 
 bool BaseRenderOSystem::indicatorFlip() {
 	if (_indicatorWidthDrawn > 0 && _indicatorHeight > 0) {
-		g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight);
+		g_system->copyRectToScreen(_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight);
 		g_system->updateScreen();
 	}
 	return STATUS_OK;
 }
 
 bool BaseRenderOSystem::forcedFlip() {
-	g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+	g_system->copyRectToScreen(_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
 	g_system->updateScreen();
 	return STATUS_OK;
 }
@@ -196,9 +196,9 @@ bool BaseRenderOSystem::flip() {
 
 	if (_needsFlip || _disableDirtyRects || screenChanged) {
 		if (_disableDirtyRects || screenChanged) {
-			g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+			g_system->copyRectToScreen(_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());
+		//  g_system->copyRectToScreen(_renderSurface->getPixels(), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
 		delete _dirtyRect;
 		_dirtyRect = nullptr;
 		_needsFlip = false;
@@ -452,7 +452,7 @@ void BaseRenderOSystem::drawTickets() {
 		// Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldn't become clear-color)
 		ticket->_wantsDraw = false;
 	}
-	g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
+	g_system->copyRectToScreen(_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
 
 	it = _renderQueue.begin();
 	// Clean out the old tickets
@@ -580,7 +580,7 @@ void BaseRenderOSystem::endSaveLoad() {
 	_lastFrameIter = _renderQueue.end();
 
 	_renderSurface->fillRect(Common::Rect(0, 0, _renderSurface->w, _renderSurface->h), _renderSurface->format.ARGBToColor(255, 0, 0, 0));
-	g_system->copyRectToScreen((byte *)_renderSurface->getPixels(), _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+	g_system->fillScreen(Common::Rect(0, 0, _renderSurface->w, _renderSurface->h), _renderSurface->format.ARGBToColor(255, 0, 0, 0));
 	g_system->updateScreen();
 }
 
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
index 29959ac6d53..083de50e0a8 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -165,16 +165,17 @@ bool BaseSurfaceOSystem::finishLoad() {
 	// Some Rosemary sprites have non-fully transparent pixels
 	// In original WME it wasn't seen because sprites were downscaled
 	// Let's set alpha to 0 if it is smaller then some treshold
-	if (BaseEngine::instance().getGameId() == "rosemary" && _filename.hasPrefix("actors") && _surface->format.bytesPerPixel == 4) {
-		uint8 treshold = 16;
+	if (BaseEngine::instance().getGameId() == "rosemary" && _filename.hasPrefix("actors") &&
+            _alphaType == Graphics::ALPHA_FULL && _surface->format.aBits() > 4) {
+		uint32 mask = _surface->format.ARGBToColor(255, 0, 0, 0);
+		uint32 treshold = _surface->format.ARGBToColor(16, 0, 0, 0);
+		uint32 blank = _surface->format.ARGBToColor(0, 0, 0, 0);
+
 		for (int x = 0; x < _surface->w; x++) {
 			for (int y = 0; y < _surface->h; y++) {
-				uint32 pixel = getPixelAt(_surface, x, y);
-				uint8 r, g, b, a;
-				_surface->format.colorToARGB(pixel, a, r, g, b);
-				if (a > 0 && a < treshold) {
-					uint32 *p = (uint32 *)_surface->getBasePtr(x, y);
-					*p = _surface->format.ARGBToColor(0, 0, 0, 0);
+				uint32 pixel = _surface->getPixel(x, y);
+				if ((pixel & mask) > blank && (pixel & mask) < treshold) {
+					_surface->setPixel(x, y, blank);
 				}
 			}
 		}
@@ -209,7 +210,7 @@ void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) {
 	bool hasTransparency = false;
 	for (int y = 0; y < surface->h; y++) {
 		for (int x = 0; x < surface->w; x++) {
-			uint32 pixel = getPixelAt(surface, x, y);
+			uint32 pixel = surface->getPixel(x, y);
 
 			uint8 r, g, b, a;
 			surface->format.colorToARGB(pixel, a, r, g, b);
@@ -232,41 +233,6 @@ void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) {
 	}
 }
 
-//////////////////////////////////////////////////////////////////////////
-uint32 BaseSurfaceOSystem::getPixelAt(Graphics::Surface *surface, int x, int y) {
-	int bpp = surface->format.bytesPerPixel;
-	/* Here p is the address to the pixel we want to retrieve */
-	uint8 *p = (uint8 *)surface->getBasePtr(x, y);
-
-	switch (bpp) {
-	case 1:
-		return *p;
-		break;
-
-	case 2:
-		return *(uint16 *)p;
-		break;
-
-	case 3:
-#ifdef SCUMM_BIG_ENDIAN
-		//  if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
-		return p[0] << 16 | p[1] << 8 | p[2];
-#else
-		//else
-		return p[0] | p[1] << 8 | p[2] << 16;
-#endif
-		break;
-
-	case 4:
-		return *(uint32 *)p;
-		break;
-
-	default:
-		return 0;       /* shouldn't happen, but avoids warnings */
-	}
-	return 0;
-}
-
 //////////////////////////////////////////////////////////////////////////
 bool BaseSurfaceOSystem::create(int width, int height) {
 	_width = width;
@@ -290,18 +256,14 @@ bool BaseSurfaceOSystem::isTransparentAtLite(int x, int y) {
 		return true;
 	}
 
-	if (_surface->format.bytesPerPixel == 4) {
-		uint32 pixel = *(uint32 *)_surface->getBasePtr(x, y);
-		uint8 r, g, b, a;
-		_surface->format.colorToARGB(pixel, a, r, g, b);
-		if (a <= 128) {
-			return true;
-		} else {
-			return false;
-		}
+	uint32 pixel = _surface->getPixel(x, y);
+	uint8 r, g, b, a;
+	_surface->format.colorToARGB(pixel, a, r, g, b);
+	if (a <= 128) {
+		return true;
+	} else {
+		return false;
 	}
-
-	return false;
 }
 
 //////////////////////////////////////////////////////////////////////////
@@ -422,10 +384,8 @@ bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect,
 
 bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) {
 	_loaded = true;
-	if (surface.format == _surface->format && surface.pitch == _surface->pitch && surface.h == _surface->h) {
-		const byte *src = (const byte *)surface.getBasePtr(0, 0);
-		byte *dst = (byte *)_surface->getBasePtr(0, 0);
-		memcpy(dst, src, surface.pitch * surface.h);
+	if (surface.format == _surface->format && surface.w == _surface->w && surface.h == _surface->h) {
+		_surface->copyRectToSurface(surface, 0, 0, Common::Rect(surface.w, surface.h));
 	} else {
 		_surface->free();
 		_surface->copyFrom(surface);
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
index 2e668e556b5..83e1eecd7c8 100644
--- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
@@ -83,7 +83,7 @@ public:
 			finishLoad();
 		}
 		if (_surface) {
-			uint32 pixel = getPixelAt(_surface, x, y);
+			uint32 pixel = _surface->getPixel(x, y);
 			_surface->format.colorToARGB(pixel, *a, *r, *g, *b);
 			return STATUS_OK;
 		}
@@ -97,7 +97,6 @@ private:
 	bool finishLoad();
 	bool drawSprite(int x, int y, Rect32 *rect, Rect32 *newRect, Graphics::TransformStruct transformStruct);
 	void genAlphaMask(Graphics::Surface *surface);
-	uint32 getPixelAt(Graphics::Surface *surface, int x, int y);
 
 	float _rotation;
 	Graphics::AlphaType _alphaType;
diff --git a/engines/wintermute/base/gfx/osystem/render_ticket.cpp b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
index 2107601e397..d9d73812073 100644
--- a/engines/wintermute/base/gfx/osystem/render_ticket.cpp
+++ b/engines/wintermute/base/gfx/osystem/render_ticket.cpp
@@ -45,14 +45,12 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
 	        _wantsDraw(true),
 	        _transform(transform) {
 	if (surf) {
-		_surface = new Graphics::Surface();
-		_surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format);
-		assert(_surface->format.bytesPerPixel == 4);
-		// Get a clipped copy of the surface
-		for (int i = 0; i < _surface->h; i++) {
-			memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel);
-		}
-		// Then scale it if necessary
+		assert(surf->format.bytesPerPixel == 4);
+
+		// Get a clipped view of the surface
+		const Graphics::Surface temp = surf->getSubArea(*srcRect);
+
+		// Then copy and scale it as necessary
 		//
 		// NB: The numTimesX/numTimesY properties don't yet mix well with
 		// scaling and rotation, but there is no need for that functionality at
@@ -61,17 +59,14 @@ RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *s
 		// (Mirroring should most likely be done before rotation. See also
 		// TransformTools.)
 		if (_transform._angle != Graphics::kDefaultAngle) {
-			Graphics::Surface *temp = _surface->rotoscale(transform, owner->_gameRef->getBilinearFiltering());
-			_surface->free();
-			delete _surface;
-			_surface = temp;
+			_surface = temp.rotoscale(transform, owner->_gameRef->getBilinearFiltering());
 		} else if ((dstRect->width() != srcRect->width() ||
 					dstRect->height() != srcRect->height()) &&
 					_transform._numTimesX * _transform._numTimesY == 1) {
-			Graphics::Surface *temp = _surface->scale(dstRect->width(), dstRect->height(), owner->_gameRef->getBilinearFiltering());
-			_surface->free();
-			delete _surface;
-			_surface = temp;
+			_surface = temp.scale(dstRect->width(), dstRect->height(), owner->_gameRef->getBilinearFiltering());
+		} else {
+			_surface = new Graphics::Surface();
+			_surface->copyFrom(temp);
 		}
 	} else {
 		_surface = nullptr;
diff --git a/engines/wintermute/video/video_theora_player.cpp b/engines/wintermute/video/video_theora_player.cpp
index a1ebba08b02..7953874c38b 100644
--- a/engines/wintermute/video/video_theora_player.cpp
+++ b/engines/wintermute/video/video_theora_player.cpp
@@ -318,10 +318,8 @@ bool VideoTheoraPlayer::update() {
 			if (!_theoraDecoder->endOfVideo() && _theoraDecoder->getTimeToNextFrame() == 0) {
 				const Graphics::Surface *decodedFrame = _theoraDecoder->decodeNextFrame();
 				if (decodedFrame) {
-					if (decodedFrame->format == _surface.format && decodedFrame->pitch == _surface.pitch && decodedFrame->h == _surface.h) {
-						const byte *src = (const byte *)decodedFrame->getBasePtr(0, 0);
-						byte *dst = (byte *)_surface.getBasePtr(0, 0);
-						memcpy(dst, src, _surface.pitch * _surface.h);
+					if (decodedFrame->format == _surface.format && decodedFrame->w == _surface.w && decodedFrame->h == _surface.h) {
+						_surface.copyRectToSurface(*decodedFrame, 0, 0, Common::Rect(decodedFrame->w, decodedFrame->h));
 					} else {
 						_surface.free();
 						_surface.copyFrom(*decodedFrame);
@@ -386,7 +384,9 @@ bool VideoTheoraPlayer::writeVideo() {
 
 void VideoTheoraPlayer::writeAlpha() {
 	if (_alphaImage && _surface.w == _alphaImage->getSurface()->w && _surface.h == _alphaImage->getSurface()->h) {
+		assert(_alphaImage->getSurface()->pitch == _alphaImage->getSurface()->w * 4);
 		assert(_alphaImage->getSurface()->format.bytesPerPixel == 4);
+		assert(_surface.pitch == _surface.w * 4);
 		assert(_surface.format.bytesPerPixel == 4);
 		const byte *alphaData = (const byte *)_alphaImage->getSurface()->getPixels();
 #ifdef SCUMM_LITTLE_ENDIAN
@@ -450,16 +450,6 @@ bool VideoTheoraPlayer::setAlphaImage(const Common::String &filename) {
 	return STATUS_OK;
 }
 
-//////////////////////////////////////////////////////////////////////////
-byte VideoTheoraPlayer::getAlphaAt(int x, int y) const {
-	if (_alphaImage) {
-		return _alphaImage->getAlphaAt(x, y);
-	} else {
-		return 0xFF;
-	}
-}
-
-
 //////////////////////////////////////////////////////////////////////////
 inline int intlog(int num) {
 	int r = 0;
diff --git a/engines/wintermute/video/video_theora_player.h b/engines/wintermute/video/video_theora_player.h
index 4e2bc075f96..4a4123f2670 100644
--- a/engines/wintermute/video/video_theora_player.h
+++ b/engines/wintermute/video/video_theora_player.h
@@ -90,7 +90,6 @@ public:
 	BaseImage *_alphaImage;
 	Common::String _alphaFilename;
 	bool setAlphaImage(const Common::String &filename);
-	byte getAlphaAt(int x, int y) const;
 	void writeAlpha();
 
 	bool seekToTime(uint32 Time);




More information about the Scummvm-git-logs mailing list