[Scummvm-cvs-logs] scummvm master -> 4a62d6c25a4994a72c59ca3b8f2913ead565a173

sev- sev at scummvm.org
Mon May 6 12:50:10 CEST 2013


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

Summary:
0a0b2f397b SWORD25: Optimize graphics drawing code
e935f85366 SWORD25: Change absolute Z calculation to match that of absolute x/y; remove old comment
176a3babc5 Merge branch 'master' of github.com:scummvm/scummvm into sword25-gfx
4fc57dac8f SWORD25: Fix blitting code
4a62d6c25a Merge pull request #320 from johndoe123/sword25-gfx


Commit: 0a0b2f397b95e6e219f2ac8c5b79bbe6300ef432
    https://github.com/scummvm/scummvm/commit/0a0b2f397b95e6e219f2ac8c5b79bbe6300ef432
Author: johndoe123 (john_doe at techie.com)
Date: 2013-04-17T03:41:49-07:00

Commit Message:
SWORD25: Optimize graphics drawing code

Changed paths:
  A engines/sword25/gfx/microtiles.cpp
  A engines/sword25/gfx/microtiles.h
    engines/sword25/gfx/animation.cpp
    engines/sword25/gfx/animation.h
    engines/sword25/gfx/bitmapresource.h
    engines/sword25/gfx/dynamicbitmap.cpp
    engines/sword25/gfx/dynamicbitmap.h
    engines/sword25/gfx/graphicengine.cpp
    engines/sword25/gfx/image/image.h
    engines/sword25/gfx/image/renderedimage.cpp
    engines/sword25/gfx/image/renderedimage.h
    engines/sword25/gfx/image/swimage.cpp
    engines/sword25/gfx/image/swimage.h
    engines/sword25/gfx/image/vectorimage.cpp
    engines/sword25/gfx/image/vectorimage.h
    engines/sword25/gfx/panel.cpp
    engines/sword25/gfx/panel.h
    engines/sword25/gfx/renderobject.cpp
    engines/sword25/gfx/renderobject.h
    engines/sword25/gfx/renderobjectmanager.cpp
    engines/sword25/gfx/renderobjectmanager.h
    engines/sword25/gfx/rootrenderobject.h
    engines/sword25/gfx/staticbitmap.cpp
    engines/sword25/gfx/staticbitmap.h
    engines/sword25/gfx/text.cpp
    engines/sword25/gfx/text.h
    engines/sword25/module.mk



diff --git a/engines/sword25/gfx/animation.cpp b/engines/sword25/gfx/animation.cpp
index 22a4dfb..1660c39 100644
--- a/engines/sword25/gfx/animation.cpp
+++ b/engines/sword25/gfx/animation.cpp
@@ -170,7 +170,7 @@ void Animation::setFrame(uint nr) {
 	forceRefresh();
 }
 
-bool Animation::doRender() {
+bool Animation::doRender(RectangleList *updateRects) {
 	AnimationDescription *animationDescriptionPtr = getAnimationDescription();
 	assert(animationDescriptionPtr);
 	assert(_currentFrame < animationDescriptionPtr->getFrameCount());
@@ -191,12 +191,14 @@ bool Animation::doRender() {
 		result = pBitmapResource->blit(_absoluteX, _absoluteY,
 		                               (animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) |
 		                               (animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0),
-		                               0, _modulationColor, _width, _height);
+		                               0, _modulationColor, _width, _height,
+									   updateRects);
 	} else {
 		result = pBitmapResource->blit(_absoluteX, _absoluteY,
 		                               (animationDescriptionPtr->getFrame(_currentFrame).flipV ? BitmapResource::FLIP_V : 0) |
 		                               (animationDescriptionPtr->getFrame(_currentFrame).flipH ? BitmapResource::FLIP_H : 0),
-		                               0, _modulationColor, -1, -1);
+		                               0, _modulationColor, -1, -1,
+									   updateRects);
 	}
 
 	// Resource freigeben
diff --git a/engines/sword25/gfx/animation.h b/engines/sword25/gfx/animation.h
index 60070be..44255e3 100644
--- a/engines/sword25/gfx/animation.h
+++ b/engines/sword25/gfx/animation.h
@@ -151,7 +151,7 @@ public:
 	void setCallbacks();
 
 protected:
-	virtual bool doRender();
+	virtual bool doRender(RectangleList *updateRects);
 
 private:
 	enum Direction {
diff --git a/engines/sword25/gfx/bitmapresource.h b/engines/sword25/gfx/bitmapresource.h
index f1278f3..72b8a3e 100644
--- a/engines/sword25/gfx/bitmapresource.h
+++ b/engines/sword25/gfx/bitmapresource.h
@@ -123,9 +123,10 @@ public:
 	          int flipping = FLIP_NONE,
 	          Common::Rect *pSrcPartRect = NULL,
 	          uint color = BS_ARGB(255, 255, 255, 255),
-	          int width = -1, int height = -1) {
+	          int width = -1, int height = -1,
+			  RectangleList *updateRects = 0) {
 		assert(_pImage);
-		return _pImage->blit(posX, posY, flipping, pSrcPartRect, color, width, height);
+		return _pImage->blit(posX, posY, flipping, pSrcPartRect, color, width, height, updateRects);
 	}
 
 	/**
@@ -202,6 +203,11 @@ public:
 		return _pImage->isColorModulationAllowed();
 	}
 
+	bool isSolid() {
+		assert(_pImage);
+		return _pImage->isSolid();
+	}
+
 private:
 	Image *_pImage;
 };
diff --git a/engines/sword25/gfx/dynamicbitmap.cpp b/engines/sword25/gfx/dynamicbitmap.cpp
index 137d943..aef04fe 100644
--- a/engines/sword25/gfx/dynamicbitmap.cpp
+++ b/engines/sword25/gfx/dynamicbitmap.cpp
@@ -53,10 +53,13 @@ DynamicBitmap::DynamicBitmap(InputPersistenceBlock &reader, RenderObjectPtr<Rend
 bool DynamicBitmap::createRenderedImage(uint width, uint height) {
 	bool result = false;
 	_image.reset(new RenderedImage(width, height, result));
-
+	
 	_originalWidth = _width = width;
 	_originalHeight = _height = height;
 
+	_image->setIsTransparent(false);
+	_isSolid = true;
+
 	return result;
 }
 
@@ -70,10 +73,12 @@ uint DynamicBitmap::getPixel(int x, int y) const {
 	return _image->getPixel(x, y);
 }
 
-bool DynamicBitmap::doRender() {
+bool DynamicBitmap::doRender(RectangleList *updateRects) {
 	// Get the frame buffer object
 	GraphicEngine *pGfx = Kernel::getInstance()->getGfx();
 	assert(pGfx);
+	
+	//return true;//DEBUG
 
 	// Draw the bitmap
 	bool result;
@@ -85,7 +90,8 @@ bool DynamicBitmap::doRender() {
 		result = _image->blit(_absoluteX, _absoluteY,
 		                       (_flipV ? BitmapResource::FLIP_V : 0) |
 		                       (_flipH ? BitmapResource::FLIP_H : 0),
-		                       0, _modulationColor, -1, -1);
+		                       0, _modulationColor, -1, -1,
+							   updateRects);
 #else
 		// WIP: A bit faster code
 
@@ -103,13 +109,15 @@ bool DynamicBitmap::doRender() {
 		result = _image->blit(_absoluteX, _absoluteY,
 		                       (_flipV ? BitmapResource::FLIP_V : 0) |
 		                       (_flipH ? BitmapResource::FLIP_H : 0),
-		                       0, _modulationColor, _width, _height);
+		                       0, _modulationColor, _width, _height,
+							   updateRects);
 	}
 
 	return result;
 }
 
 bool DynamicBitmap::setContent(const byte *pixeldata, uint size, uint offset, uint stride) {
+	++_version; // Update version to display the new video image
 	return _image->setContent(pixeldata, size, offset, stride);
 }
 
diff --git a/engines/sword25/gfx/dynamicbitmap.h b/engines/sword25/gfx/dynamicbitmap.h
index 35ed9a9..ed53776 100644
--- a/engines/sword25/gfx/dynamicbitmap.h
+++ b/engines/sword25/gfx/dynamicbitmap.h
@@ -59,7 +59,7 @@ public:
 	virtual bool unpersist(InputPersistenceBlock &reader);
 
 protected:
-	virtual bool doRender();
+	virtual bool doRender(RectangleList *updateRects);
 
 private:
 	DynamicBitmap(RenderObjectPtr<RenderObject> parentPtr, uint width, uint height);
diff --git a/engines/sword25/gfx/graphicengine.cpp b/engines/sword25/gfx/graphicengine.cpp
index 216d801..bfdb514 100644
--- a/engines/sword25/gfx/graphicengine.cpp
+++ b/engines/sword25/gfx/graphicengine.cpp
@@ -216,7 +216,6 @@ bool GraphicEngine::fill(const Common::Rect *fillRectPtr, uint color) {
 			}
 		}
 
-		g_system->copyRectToScreen(_backSurface.getBasePtr(rect.left, rect.top), _backSurface.pitch, rect.left, rect.top, rect.width(), rect.height());
 	}
 
 	return true;
diff --git a/engines/sword25/gfx/image/image.h b/engines/sword25/gfx/image/image.h
index f193465..9d7fc43 100644
--- a/engines/sword25/gfx/image/image.h
+++ b/engines/sword25/gfx/image/image.h
@@ -46,6 +46,8 @@
 
 namespace Sword25 {
 
+class RectangleList;
+
 class Image {
 public:
 	virtual ~Image() {}
@@ -129,7 +131,8 @@ public:
 	                  int flipping = FLIP_NONE,
 	                  Common::Rect *pPartRect = NULL,
 	                  uint color = BS_ARGB(255, 255, 255, 255),
-	                  int width = -1, int height = -1) = 0;
+	                  int width = -1, int height = -1,
+					  RectangleList *updateRects = 0) = 0;
 
 	/**
 	    @brief fills a rectangular section of the image with a color.
@@ -202,6 +205,8 @@ public:
 	    @brief Returns true, if the content of the BS_Image is allowed to be replaced by call of SetContent().
 	*/
 	virtual bool isSetContentAllowed() const = 0;
+	
+	virtual bool isSolid() const { return false; }
 
 	//@}
 };
diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index 27ee4ef..1de7a04 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -38,6 +38,8 @@
 #include "sword25/gfx/image/imgloader.h"
 #include "sword25/gfx/image/renderedimage.h"
 
+#include "sword25/gfx/renderobjectmanager.h"
+
 #include "common/system.h"
 
 namespace Sword25 {
@@ -99,7 +101,8 @@ static byte *readSavegameThumbnail(const Common::String &filename, uint &fileSiz
 RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
 	_data(0),
 	_width(0),
-	_height(0) {
+	_height(0),
+	_isTransparent(true) {
 	result = false;
 
 	PackageManager *pPackage = Kernel::getInstance()->getPackage();
@@ -142,6 +145,8 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
 
 	_doCleanup = true;
 
+	checkForTransparency();
+
 	return;
 }
 
@@ -149,7 +154,8 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
 
 RenderedImage::RenderedImage(uint width, uint height, bool &result) :
 	_width(width),
-	_height(height) {
+	_height(height),
+	_isTransparent(true) {
 
 	_data = new byte[width * height * 4];
 	Common::fill(_data, &_data[width * height * 4], 0);
@@ -162,7 +168,7 @@ RenderedImage::RenderedImage(uint width, uint height, bool &result) :
 	return;
 }
 
-RenderedImage::RenderedImage() : _width(0), _height(0), _data(0) {
+RenderedImage::RenderedImage() : _width(0), _height(0), _data(0), _isTransparent(true) {
 	_backSurface = Kernel::getInstance()->getGfx()->getSurface();
 
 	_doCleanup = false;
@@ -219,7 +225,7 @@ uint RenderedImage::getPixel(int x, int y) {
 
 // -----------------------------------------------------------------------------
 
-bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height) {
+bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRect, uint color, int width, int height, RectangleList *updateRects) {
 	int ca = (color >> 24) & 0xff;
 
 	// Check if we need to draw anything at all
@@ -282,156 +288,175 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
 		img = &srcImage;
 	}
 
-	// Handle off-screen clipping
-	if (posY < 0) {
-		img->h = MAX(0, (int)img->h - -posY);
-		img->pixels = (byte *)img->pixels + img->pitch * -posY;
-		posY = 0;
-	}
-
-	if (posX < 0) {
-		img->w = MAX(0, (int)img->w - -posX);
-		img->pixels = (byte *)img->pixels + (-posX * 4);
-		posX = 0;
-	}
-
-	img->w = CLIP((int)img->w, 0, (int)MAX((int)_backSurface->w - posX, 0));
-	img->h = CLIP((int)img->h, 0, (int)MAX((int)_backSurface->h - posY, 0));
-
-	if ((img->w > 0) && (img->h > 0)) {
-		int xp = 0, yp = 0;
-
-		int inStep = 4;
-		int inoStep = img->pitch;
-		if (flipping & Image::FLIP_V) {
-			inStep = -inStep;
-			xp = img->w - 1;
+	for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) {
+		const Common::Rect &clipRect = *it;
+	
+		int skipLeft = 0, skipTop = 0;
+		int drawX = posX, drawY = posY;
+		int drawWidth = img->w;
+		int drawHeight = img->h;
+	
+		// Handle clipping
+		if (drawY < clipRect.top) {
+			skipTop = clipRect.top - drawY;
+			drawHeight = MAX(0, (int)drawHeight - (clipRect.top - drawY));
+			drawY = clipRect.top;
 		}
-
-		if (flipping & Image::FLIP_H) {
-			inoStep = -inoStep;
-			yp = img->h - 1;
+	
+		if (drawX < clipRect.left) {
+			skipLeft = clipRect.left - drawX;
+			drawWidth = MAX(0, (int)drawWidth - skipLeft);
+			drawX = clipRect.left;
 		}
+		
+		if (drawX + drawWidth >= clipRect.right)
+			drawWidth = clipRect.right - drawX;
+	
+		if (drawY + drawHeight >= clipRect.bottom)
+			drawHeight = clipRect.bottom - drawY;
+			
+		if ((drawWidth > 0) && (drawHeight > 0)) {
+			int xp = 0, yp = 0;
+	
+			int inStep = 4;
+			int inoStep = img->pitch;
+			if (flipping & Image::FLIP_V) {
+				inStep = -inStep;
+				xp = img->w - 1 - skipLeft;
+			} else {
+				xp = skipLeft;
+			}
+	
+			if (flipping & Image::FLIP_H) {
+				inoStep = -inoStep;
+				yp = img->h - 1 - skipTop;
+			} else {
+				yp = skipTop;
+			}
+	
+			byte *ino = (byte *)img->getBasePtr(xp, yp);
+			byte *outo = (byte *)_backSurface->getBasePtr(drawX, drawY);
 
-		byte *ino = (byte *)img->getBasePtr(xp, yp);
-		byte *outo = (byte *)_backSurface->getBasePtr(posX, posY);
-		byte *in, *out;
-
-		for (int i = 0; i < img->h; i++) {
-			out = outo;
-			in = ino;
-			for (int j = 0; j < img->w; j++) {
-				uint32 pix = *(uint32 *)in;
-				int b = (pix >> 0) & 0xff;
-				int g = (pix >> 8) & 0xff;
-				int r = (pix >> 16) & 0xff;
-				int a = (pix >> 24) & 0xff;
-				in += inStep;
-
-				if (ca != 255) {
-					a = a * ca >> 8;
+#if defined(SCUMM_LITTLE_ENDIAN)
+			// Simple memcpy if the source bitmap doesn't have transparent pixels and the drawing transparency is 255
+			// NOTE Only possible with LE-machines at the moment, maybe it would be feasible to convert the bitmap pixels at loading time?
+			if (!_isTransparent && ca == 255) {
+				for (int i = 0; i < drawHeight; i++) {
+					memcpy(outo, ino, drawWidth * 4);
+					outo += _backSurface->pitch;
+					ino += inoStep;
 				}
-
-				switch (a) {
-				case 0: // Full transparency
-					out += 4;
-					break;
-				case 255: // Full opacity
+			} else
+#endif			 
+			{
+				byte *in, *out;
+				for (int i = 0; i < drawHeight; i++) {
+					out = outo;
+					in = ino;
+					for (int j = 0; j < drawWidth; j++) {
+						uint32 pix = *(uint32 *)in;
+						int a = (pix >> 24) & 0xff;
+						in += inStep;
+						
+						if (a == 0) {
+							// Full transparency
+							out += 4;
+							continue;
+						}
+						
+						if (ca != 255) {
+							a = a * ca >> 8;
+						}
+		
+						int b = (pix >> 0) & 0xff;
+						int g = (pix >> 8) & 0xff;
+						int r = (pix >> 16) & 0xff;
+		
+						if (a == 255) {
 #if defined(SCUMM_LITTLE_ENDIAN)
-					if (cb != 255)
-						*out++ = (b * cb) >> 8;
-					else
-						*out++ = b;
-
-					if (cg != 255)
-						*out++ = (g * cg) >> 8;
-					else
-						*out++ = g;
-
-					if (cr != 255)
-						*out++ = (r * cr) >> 8;
-					else
-						*out++ = r;
-
-					*out++ = a;
+							if (cb != 255)
+								b = (b * cb) >> 8;
+							if (cg != 255)
+								g = (g * cg) >> 8;
+							if (cr != 255)
+								r = (r * cr) >> 8;
+							*(uint32 *)out = (255 << 24) | (r << 16) | (g << 8) | b;
+							out += 4;
 #else
-					*out++ = a;
-
-					if (cr != 255)
-						*out++ = (r * cr) >> 8;
-					else
-						*out++ = r;
-
-					if (cg != 255)
-						*out++ = (g * cg) >> 8;
-					else
-						*out++ = g;
-
-					if (cb != 255)
-						*out++ = (b * cb) >> 8;
-					else
-						*out++ = b;
+							*out++ = a;
+							if (cr != 255)
+								*out++ = (r * cr) >> 8;
+							else
+								*out++ = r;
+							if (cg != 255)
+								*out++ = (g * cg) >> 8;
+							else
+								*out++ = g;
+							if (cb != 255)
+								*out++ = (b * cb) >> 8;
+							else
+								*out++ = b;
 #endif
-					break;
-
-				default: // alpha blending
+						} else {
 #if defined(SCUMM_LITTLE_ENDIAN)
-					if (cb == 0)
-						*out = 0;
-					else if (cb != 255)
-						*out += ((b - *out) * a * cb) >> 16;
-					else
-						*out += ((b - *out) * a) >> 8;
-					out++;
-					if (cg == 0)
-						*out = 0;
-					else if (cg != 255)
-						*out += ((g - *out) * a * cg) >> 16;
-					else
-						*out += ((g - *out) * a) >> 8;
-					out++;
-					if (cr == 0)
-						*out = 0;
-					else if (cr != 255)
-						*out += ((r - *out) * a * cr) >> 16;
-					else
-						*out += ((r - *out) * a) >> 8;
-					out++;
-					*out = 255;
-					out++;
+							pix = *(uint32 *)out;
+							int outb = (pix >> 0) & 0xff;
+							int outg = (pix >> 8) & 0xff;
+							int outr = (pix >> 16) & 0xff;
+							if (cb == 0)
+								outb = 0;
+							else if (cb != 255)
+								outb += ((b - outb) * a * cb) >> 16;
+							else
+								outb += ((b - outb) * a) >> 8;
+							if (cg == 0)
+								outg = 0;
+							else if (cg != 255)
+								outg += ((g - outg) * a * cg) >> 16;
+							else
+								outg += ((g - outg) * a) >> 8;
+							if (cr == 0)
+								outr = 0;
+							else if (cr != 255)
+								outr += ((r - outr) * a * cr) >> 16;
+							else
+								outr += ((r - outr) * a) >> 8;
+							*(uint32 *)out = (255 << 24) | (outr << 16) | (outg << 8) | outb;
+							out += 4;
 #else
-					*out = 255;
-					out++;
-					if (cr == 0)
-						*out = 0;
-					else if (cr != 255)
-						*out += ((r - *out) * a * cr) >> 16;
-					else
-						*out += ((r - *out) * a) >> 8;
-					out++;
-					if (cg == 0)
-						*out = 0;
-					else if (cg != 255)
-						*out += ((g - *out) * a * cg) >> 16;
-					else
-						*out += ((g - *out) * a) >> 8;
-					out++;
-					if (cb == 0)
-						*out = 0;
-					else if (cb != 255)
-						*out += ((b - *out) * a * cb) >> 16;
-					else
-						*out += ((b - *out) * a) >> 8;
-					out++;
+							*out = 255;
+							out++;
+							if (cr == 0)
+								*out = 0;
+							else if (cr != 255)
+								*out += ((r - *out) * a * cr) >> 16;
+							else
+								*out += ((r - *out) * a) >> 8;
+							out++;
+							if (cg == 0)
+								*out = 0;
+							else if (cg != 255)
+								*out += ((g - *out) * a * cg) >> 16;
+							else
+								*out += ((g - *out) * a) >> 8;
+							out++;
+							if (cb == 0)
+								*out = 0;
+							else if (cb != 255)
+								*out += ((b - *out) * a * cb) >> 16;
+							else
+								*out += ((b - *out) * a) >> 8;
+							out++;
 #endif
+						}
+					}
+					outo += _backSurface->pitch;
+					ino += inoStep;
 				}
 			}
-			outo += _backSurface->pitch;
-			ino += inoStep;
-		}
 
-		g_system->copyRectToScreen(_backSurface->getBasePtr(posX, posY), _backSurface->pitch, posX, posY,
-			img->w, img->h);
+		}
+		
 	}
 
 	if (imgScaled) {
@@ -467,6 +492,20 @@ void RenderedImage::copyDirectly(int posX, int posY) {
 	g_system->copyRectToScreen(data, _backSurface->pitch, posX, posY, w, h);
 }
 
+void RenderedImage::checkForTransparency() {
+	// Check if the source bitmap has any transparent pixels at all
+	_isTransparent = false;
+	byte *data = _data;
+	for (int i = 0; i < _height; i++) {
+		for (int j = 0; j < _width; j++) {
+			_isTransparent = data[3] != 0xff;
+			if (_isTransparent)
+				return;
+			data += 4;
+		}
+	}
+}
+
 /**
  * Scales a passed surface, creating a new surface with the result
  * @param srcImage		Source image to scale
diff --git a/engines/sword25/gfx/image/renderedimage.h b/engines/sword25/gfx/image/renderedimage.h
index f92a5b3..a25b258 100644
--- a/engines/sword25/gfx/image/renderedimage.h
+++ b/engines/sword25/gfx/image/renderedimage.h
@@ -75,7 +75,8 @@ public:
 	                  int flipping = Image::FLIP_NONE,
 	                  Common::Rect *pPartRect = NULL,
 	                  uint color = BS_ARGB(255, 255, 255, 255),
-	                  int width = -1, int height = -1);
+	                  int width = -1, int height = -1,
+					  RectangleList *updateRects = 0);
 	virtual bool fill(const Common::Rect *pFillRect, uint color);
 	virtual bool setContent(const byte *pixeldata, uint size, uint offset = 0, uint stride = 0);
 	void replaceContent(byte *pixeldata, int width, int height);
@@ -105,14 +106,19 @@ public:
 
 	static Graphics::Surface *scale(const Graphics::Surface &srcImage, int xSize, int ySize);
 
+	void setIsTransparent(bool isTransparent) { _isTransparent = isTransparent; }
+	virtual bool isSolid() const { return !_isTransparent; }
+
 private:
 	byte *_data;
 	int  _width;
 	int  _height;
 	bool _doCleanup;
+	bool _isTransparent;
 
 	Graphics::Surface *_backSurface;
 
+	void checkForTransparency();
 	static int *scaleLine(int size, int srcSize);
 };
 
diff --git a/engines/sword25/gfx/image/swimage.cpp b/engines/sword25/gfx/image/swimage.cpp
index 0b9cc11..7e4c314 100644
--- a/engines/sword25/gfx/image/swimage.cpp
+++ b/engines/sword25/gfx/image/swimage.cpp
@@ -79,7 +79,8 @@ bool SWImage::blit(int posX, int posY,
                       int flipping,
                       Common::Rect *pPartRect,
                       uint color,
-                      int width, int height) {
+                      int width, int height,
+					  RectangleList *updateRects) {
 	error("Blit() is not supported.");
 	return false;
 }
diff --git a/engines/sword25/gfx/image/swimage.h b/engines/sword25/gfx/image/swimage.h
index 5f34895..a35127a 100644
--- a/engines/sword25/gfx/image/swimage.h
+++ b/engines/sword25/gfx/image/swimage.h
@@ -58,7 +58,8 @@ public:
 	                  int flipping = Image::FLIP_NONE,
 	                  Common::Rect *pPartRect = NULL,
 	                  uint color = BS_ARGB(255, 255, 255, 255),
-	                  int width = -1, int height = -1);
+	                  int width = -1, int height = -1,
+					  RectangleList *updateRects = 0);
 	virtual bool fill(const Common::Rect *fillRectPtr, uint color);
 	virtual bool setContent(const byte *pixeldata, uint size, uint offset, uint stride);
 	virtual uint getPixel(int x, int y);
diff --git a/engines/sword25/gfx/image/vectorimage.cpp b/engines/sword25/gfx/image/vectorimage.cpp
index 81f4fc2..471081c 100644
--- a/engines/sword25/gfx/image/vectorimage.cpp
+++ b/engines/sword25/gfx/image/vectorimage.cpp
@@ -602,7 +602,8 @@ bool VectorImage::blit(int posX, int posY,
                        int flipping,
                        Common::Rect *pPartRect,
                        uint color,
-                       int width, int height) {
+                       int width, int height,
+					   RectangleList *updateRects) {
 	static VectorImage *oldThis = 0;
 	static int              oldWidth = -2;
 	static int              oldHeight = -2;
@@ -623,7 +624,7 @@ bool VectorImage::blit(int posX, int posY,
 	RenderedImage *rend = new RenderedImage();
 
 	rend->replaceContent(_pixelData, width, height);
-	rend->blit(posX, posY, flipping, pPartRect, color, width, height);
+	rend->blit(posX, posY, flipping, pPartRect, color, width, height, updateRects);
 
 	delete rend;
 
diff --git a/engines/sword25/gfx/image/vectorimage.h b/engines/sword25/gfx/image/vectorimage.h
index 959f251..d1760a4 100644
--- a/engines/sword25/gfx/image/vectorimage.h
+++ b/engines/sword25/gfx/image/vectorimage.h
@@ -212,7 +212,8 @@ public:
 	                  int flipping = FLIP_NONE,
 	                  Common::Rect *pPartRect = NULL,
 	                  uint color = BS_ARGB(255, 255, 255, 255),
-	                  int width = -1, int height = -1);
+	                  int width = -1, int height = -1,
+					  RectangleList *updateRects = 0);
 
 	class SWFBitStream;
 
diff --git a/engines/sword25/gfx/microtiles.cpp b/engines/sword25/gfx/microtiles.cpp
new file mode 100644
index 0000000..8dceed5
--- /dev/null
+++ b/engines/sword25/gfx/microtiles.cpp
@@ -0,0 +1,164 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#include "sword25/gfx/microtiles.h"
+
+namespace Sword25 {
+
+MicroTileArray::MicroTileArray(int16 width, int16 height) {
+	_tilesW = (width / TileSize) + ((width % TileSize) > 0 ? 1 : 0);
+	_tilesH = (height / TileSize) + ((height % TileSize) > 0 ? 1 : 0);
+	_tiles = new BoundingBox[_tilesW * _tilesH];
+	clear();
+}
+
+MicroTileArray::~MicroTileArray() {
+	delete[] _tiles;
+}
+
+void MicroTileArray::addRect(Common::Rect r) {
+
+	int ux0, uy0, ux1, uy1;
+	int tx0, ty0, tx1, ty1;
+	int ix0, iy0, ix1, iy1;
+
+	r.clip(Common::Rect(0, 0, 799, 599));
+
+	ux0 = r.left / TileSize;
+	uy0 = r.top / TileSize;
+	ux1 = r.right / TileSize;
+	uy1 = r.bottom / TileSize;
+
+	tx0 = r.left % TileSize;
+	ty0 = r.top % TileSize;
+	tx1 = r.right % TileSize;
+	ty1 = r.bottom % TileSize;
+
+	for (int yc = uy0; yc <= uy1; yc++) {
+		for (int xc = ux0; xc <= ux1; xc++) {
+			ix0 = (xc == ux0) ? tx0 : 0;
+			ix1 = (xc == ux1) ? tx1 : TileSize - 1;
+			iy0 = (yc == uy0) ? ty0 : 0;
+			iy1 = (yc == uy1) ? ty1 : TileSize - 1;
+			updateBoundingBox(_tiles[xc + yc * _tilesW], ix0, iy0, ix1, iy1);
+		}
+	}
+
+}
+
+void MicroTileArray::clear() {
+	memset(_tiles, 0, _tilesW * _tilesH * sizeof(BoundingBox));
+}
+
+byte MicroTileArray::TileX0(const BoundingBox &boundingBox) {
+	return (boundingBox >> 24) & 0xFF;
+}
+
+byte MicroTileArray::TileY0(const BoundingBox &boundingBox) {
+	return (boundingBox >> 16) & 0xFF;
+}
+
+byte MicroTileArray::TileX1(const BoundingBox &boundingBox) {
+	return (boundingBox >> 8) & 0xFF;
+}
+
+byte MicroTileArray::TileY1(const BoundingBox &boundingBox) {
+	return boundingBox & 0xFF;
+}
+
+bool MicroTileArray::isBoundingBoxEmpty(const BoundingBox &boundingBox) {
+	return boundingBox == EmptyBoundingBox;
+}
+
+bool MicroTileArray::isBoundingBoxFull(const BoundingBox &boundingBox) {
+	return boundingBox == FullBoundingBox;
+}
+
+void MicroTileArray::setBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1) {
+	boundingBox = (x0 << 24) | (y0 << 16) | (x1 << 8) | y1;
+}
+
+void MicroTileArray::updateBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1) {
+	if (!isBoundingBoxEmpty(boundingBox)) {
+		x0 = MIN(TileX0(boundingBox), x0);
+		y0 = MIN(TileY0(boundingBox), y0);
+		x1 = MAX(TileX1(boundingBox), x1);
+		y1 = MAX(TileY1(boundingBox), y1);
+	}
+	setBoundingBox(boundingBox, x0, y0, x1, y1);
+}
+
+RectangleList *MicroTileArray::getRectangles() {
+
+	RectangleList *rects = new RectangleList();
+
+	int x, y;
+	int x0, y0, x1, y1;
+	int i = 0;
+
+	for (y = 0; y < _tilesH; ++y) {
+		for (x = 0; x < _tilesW; ++x) {
+
+			int start;
+			int finish = 0;
+			BoundingBox boundingBox = _tiles[i];
+
+			if (isBoundingBoxEmpty(boundingBox)) {
+				++i;
+				continue;
+			}
+
+			x0 = (x * TileSize) + TileX0(boundingBox);
+			y0 = (y * TileSize) + TileY0(boundingBox);
+			y1 = (y * TileSize) + TileY1(boundingBox);
+
+			start = i;
+
+			if (TileX1(boundingBox) == TileSize - 1 && x != _tilesW - 1) {	// check if the tile continues
+				while (!finish) {
+					++x;
+					++i;
+					if (x == _tilesW || i >= _tilesW * _tilesH ||
+						TileY0(_tiles[i]) != TileY0(boundingBox) ||
+						TileY1(_tiles[i]) != TileY1(boundingBox) ||
+						TileX0(_tiles[i]) != 0)
+					{
+						--x;
+						--i;
+						finish = 1;
+					}
+				}
+			}
+
+			x1 = (x * TileSize) + TileX1(_tiles[i]);
+
+			rects->push_back(Common::Rect(x0, y0, x1 + 1, y1 + 1));
+
+			++i;
+		}
+	}
+
+	return rects;
+}
+
+} // End of namespace Sword25
diff --git a/engines/sword25/gfx/microtiles.h b/engines/sword25/gfx/microtiles.h
new file mode 100644
index 0000000..454fc39
--- /dev/null
+++ b/engines/sword25/gfx/microtiles.h
@@ -0,0 +1,65 @@
+/* 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 2
+ * 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ *
+ */
+
+#ifndef SWORD25_MICROTILES_H
+#define SWORD25_MICROTILES_H
+
+#include "common/scummsys.h"
+#include "common/list.h"
+#include "common/util.h"
+#include "common/rect.h"
+
+namespace Sword25 {
+
+typedef uint32 BoundingBox;
+
+const BoundingBox FullBoundingBox  = 0x00001F1F;
+const BoundingBox EmptyBoundingBox = 0x00000000;
+const int TileSize = 32;
+
+class RectangleList : public Common::List<Common::Rect> {
+};
+
+class MicroTileArray {
+public:
+	MicroTileArray(int16 width, int16 height);
+	~MicroTileArray();
+	void addRect(Common::Rect r);
+	void clear();
+	RectangleList *getRectangles();
+protected:
+	BoundingBox *_tiles;
+	int16 _tilesW, _tilesH;
+	byte TileX0(const BoundingBox &boundingBox);
+	byte TileY0(const BoundingBox &boundingBox);
+	byte TileX1(const BoundingBox &boundingBox);
+	byte TileY1(const BoundingBox &boundingBox);
+	bool isBoundingBoxEmpty(const BoundingBox &boundingBox);
+	bool isBoundingBoxFull(const BoundingBox &boundingBox);
+	void setBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1);
+	void updateBoundingBox(BoundingBox &boundingBox, byte x0, byte y0, byte x1, byte y1);
+};
+
+} // namespace Sword25
+
+#endif // SWORD25_MICROTILES_H
diff --git a/engines/sword25/gfx/panel.cpp b/engines/sword25/gfx/panel.cpp
index 6d5b2a6..931b9cd 100644
--- a/engines/sword25/gfx/panel.cpp
+++ b/engines/sword25/gfx/panel.cpp
@@ -36,6 +36,8 @@
 #include "sword25/gfx/graphicengine.h"
 #include "sword25/gfx/image/image.h"
 
+#include "sword25/gfx/renderobjectmanager.h"
+
 namespace Sword25 {
 
 Panel::Panel(RenderObjectPtr<RenderObject> parentPtr, int width, int height, uint color) :
@@ -67,7 +69,7 @@ Panel::Panel(InputPersistenceBlock &reader, RenderObjectPtr<RenderObject> parent
 Panel::~Panel() {
 }
 
-bool Panel::doRender() {
+bool Panel::doRender(RectangleList *updateRects) {
 	// Falls der Alphawert 0 ist, ist das Panel komplett durchsichtig und es muss nichts gezeichnet werden.
 	if (_color >> 24 == 0)
 		return true;
@@ -75,7 +77,15 @@ bool Panel::doRender() {
 	GraphicEngine *gfxPtr = Kernel::getInstance()->getGfx();
 	assert(gfxPtr);
 
-	return gfxPtr->fill(&_bbox, _color);
+	for (RectangleList::iterator it = updateRects->begin(); it != updateRects->end(); ++it) {
+		const Common::Rect &clipRect = *it;
+		if (_bbox.intersects(clipRect)) {
+			Common::Rect intersectionRect = _bbox.findIntersectingRect(clipRect);
+			gfxPtr->fill(&intersectionRect, _color);
+		}
+	}
+	
+	return true;
 }
 
 bool Panel::persist(OutputPersistenceBlock &writer) {
diff --git a/engines/sword25/gfx/panel.h b/engines/sword25/gfx/panel.h
index cbf04ce..cb94048 100644
--- a/engines/sword25/gfx/panel.h
+++ b/engines/sword25/gfx/panel.h
@@ -59,7 +59,7 @@ public:
 	virtual bool unpersist(InputPersistenceBlock &reader);
 
 protected:
-	virtual bool doRender();
+	virtual bool doRender(RectangleList *updateRects);
 
 private:
 	uint _color;
diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp
index a977eb8..f2d2577 100644
--- a/engines/sword25/gfx/renderobject.cpp
+++ b/engines/sword25/gfx/renderobject.cpp
@@ -48,6 +48,8 @@
 
 namespace Sword25 {
 
+int RenderObject::_nextGlobalVersion = 0;
+
 RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type, uint handle) :
 	_managerPtr(0),
 	_parentPtr(parentPtr),
@@ -65,7 +67,9 @@ RenderObject::RenderObject(RenderObjectPtr<RenderObject> parentPtr, TYPES type,
 	_type(type),
 	_initSuccess(false),
 	_refreshForced(true),
-	_handle(0) {
+	_handle(0),
+	_version(++_nextGlobalVersion),
+	_isSolid(false) {
 
 	// Renderobject registrieren, abhängig vom Handle-Parameter entweder mit beliebigem oder vorgegebenen Handle.
 	if (handle == 0)
@@ -106,7 +110,7 @@ RenderObject::~RenderObject() {
 	RenderObjectRegistry::instance().deregisterObject(this);
 }
 
-bool RenderObject::render() {
+bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ) {
 	// Objektänderungen validieren
 	validateObject();
 
@@ -121,17 +125,39 @@ bool RenderObject::render() {
 	}
 
 	// Objekt zeichnen.
-	doRender();
+	bool needRender = false;
+	int index = 0;
+
+	// Only draw if the bounding box intersects any update rectangle and
+	// the object is in front of the minimum Z value.
+	for (RectangleList::iterator rectIt = updateRects->begin(); !needRender && rectIt != updateRects->end(); ++rectIt, ++index)
+		needRender = (_bbox.contains(*rectIt) || _bbox.intersects(*rectIt)) && getAbsoluteZ() >= updateRectsMinZ[index];
+
+	if (needRender)
+		doRender(updateRects);
 
 	// Dann müssen die Kinder gezeichnet werden
 	RENDEROBJECT_ITER it = _children.begin();
 	for (; it != _children.end(); ++it)
-		if (!(*it)->render())
+		if (!(*it)->render(updateRects, updateRectsMinZ))
 			return false;
 
 	return true;
 }
 
+void RenderObject::collectRenderQueue(RenderObjectQueue *renderQueue) {
+
+	if (!_visible)
+		return;
+
+	renderQueue->add(this);
+
+	RENDEROBJECT_ITER it = _children.begin();
+	for (; it != _children.end(); ++it)
+		(*it)->collectRenderQueue(renderQueue);
+
+}
+
 void RenderObject::validateObject() {
 	// Die Veränderungen in den Objektvariablen aufheben
 	_oldBbox = _bbox;
@@ -157,6 +183,8 @@ bool RenderObject::updateObjectState() {
 
 		// Die Bounding-Box neu berechnen und Update-Regions registrieren.
 		updateBoxes();
+		
+		++_version;
 
 		// Änderungen Validieren
 		validateObject();
@@ -289,6 +317,13 @@ void RenderObject::setZ(int z) {
 		_z = z;
 }
 
+int RenderObject::getAbsoluteZ() const {
+	if (_parentPtr.isValid())
+		return _parentPtr->getAbsoluteZ() + _z;
+	else
+		return _z;
+}
+
 void RenderObject::setVisible(bool visible) {
 	_visible = visible;
 }
diff --git a/engines/sword25/gfx/renderobject.h b/engines/sword25/gfx/renderobject.h
index f963cca..a22893a 100644
--- a/engines/sword25/gfx/renderobject.h
+++ b/engines/sword25/gfx/renderobject.h
@@ -53,6 +53,8 @@ namespace Sword25 {
 
 class Kernel;
 class RenderObjectManager;
+class RenderObjectQueue;
+class RectangleList;
 class Bitmap;
 class Animation;
 class AnimationTemplate;
@@ -218,7 +220,10 @@ public:
 	            Dieses kann entweder direkt geschehen oder durch den Aufruf von UpdateObjectState() an einem Vorfahren-Objekt.<br>
 	            Diese Methode darf nur von BS_RenderObjectManager aufgerufen werden.
 	*/
-	bool render();
+	bool render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ);
+
+	void collectRenderQueue(RenderObjectQueue *renderQueue);
+
 	/**
 	    @brief Bereitet das Objekt und alle seine Unterobjekte auf einen Rendervorgang vor.
 	           Hierbei werden alle Dirty-Rectangles berechnet und die Renderreihenfolge aktualisiert.
@@ -230,7 +235,7 @@ public:
 	    @brief Löscht alle Kinderobjekte.
 	*/
 	void deleteAllChildren();
-
+	
 	// Accessor-Methoden
 	// -----------------
 	/**
@@ -299,6 +304,9 @@ public:
 	int         getZ() const {
 		return _z;
 	}
+	
+	int getAbsoluteZ() const;
+	
 	/**
 	    @brief Gibt die Breite des Objektes zurück.
 	 */
@@ -352,6 +360,15 @@ public:
 		return _handle;
 	}
 
+	// Get the RenderObjects current version	
+	int getVersion() const {
+		return _version;
+	}
+	
+	bool isSolid() const {
+		return _isSolid;
+	}
+
 	// Persistenz-Methoden
 	// -------------------
 	virtual bool persist(OutputPersistenceBlock &writer);
@@ -388,6 +405,13 @@ protected:
 	int         _oldZ;
 	bool        _oldVisible;
 
+	static int _nextGlobalVersion;
+	
+	int _version;
+
+	// This should be set to true if the RenderObject is NOT alpha-blended to optimize drawing
+	bool _isSolid;
+
 	/// Ein Pointer auf den BS_RenderObjektManager, der das Objekt verwaltet.
 	RenderObjectManager *_managerPtr;
 
@@ -402,7 +426,7 @@ protected:
 	    @return Gibt false zurück, falls das Rendern fehlgeschlagen ist.
 	    @remark
 	 */
-	virtual bool doRender() = 0; // { return true; }
+	virtual bool doRender(RectangleList *updateRects) = 0; // { return true; }
 
 	// RenderObject-Baum Variablen
 	// ---------------------------
diff --git a/engines/sword25/gfx/renderobjectmanager.cpp b/engines/sword25/gfx/renderobjectmanager.cpp
index 3828999..a8f8c36 100644
--- a/engines/sword25/gfx/renderobjectmanager.cpp
+++ b/engines/sword25/gfx/renderobjectmanager.cpp
@@ -41,17 +41,37 @@
 #include "sword25/gfx/timedrenderobject.h"
 #include "sword25/gfx/rootrenderobject.h"
 
+#include "common/system.h"
+
 namespace Sword25 {
 
+void RenderObjectQueue::add(RenderObject *renderObject) {
+	push_back(RenderObjectQueueItem(renderObject, renderObject->getBbox(), renderObject->getVersion()));
+}
+
+bool RenderObjectQueue::exists(const RenderObjectQueueItem &renderObjectQueueItem) {
+	for (RenderObjectQueue::iterator it = begin(); it != end(); ++it)
+		if ((*it)._renderObject == renderObjectQueueItem._renderObject &&
+			(*it)._version == renderObjectQueueItem._version)
+			return true;
+	return false;
+}
+
 RenderObjectManager::RenderObjectManager(int width, int height, int framebufferCount) :
 	_frameStarted(false) {
 	// Wurzel des BS_RenderObject-Baumes erzeugen.
 	_rootPtr = (new RootRenderObject(this, width, height))->getHandle();
+	_uta = new MicroTileArray(width, height);
+	_currQueue = new RenderObjectQueue();
+	_prevQueue = new RenderObjectQueue();
 }
 
 RenderObjectManager::~RenderObjectManager() {
 	// Die Wurzel des Baumes löschen, damit werden alle BS_RenderObjects mitgelöscht.
 	_rootPtr.erase();
+	delete _uta;
+	delete _currQueue;
+	delete _prevQueue;
 }
 
 void RenderObjectManager::startFrame() {
@@ -76,7 +96,62 @@ bool RenderObjectManager::render() {
 	_frameStarted = false;
 
 	// Die Render-Methode der Wurzel aufrufen. Dadurch wird das rekursive Rendern der Baumelemente angestoßen.
-	return _rootPtr->render();
+
+	uint32 renderDuration = g_system->getMillis();
+	
+	_currQueue->clear();
+	_rootPtr->collectRenderQueue(_currQueue);
+
+	_uta->clear();
+	// Add rectangles of objects which don't exist in this frame any more
+    for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it)
+    	if (!_currQueue->exists(*it))
+    		_uta->addRect((*it)._bbox);
+    // Add rectangles of objects which are different from the previous frame
+    for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it)
+    	if (!_prevQueue->exists(*it))
+    		_uta->addRect((*it)._bbox);
+	
+	RectangleList *updateRects = _uta->getRectangles();
+	Common::Array<int> updateRectsMinZ;
+	
+	updateRectsMinZ.reserve(updateRects->size());
+
+	// Calculate the minimum drawing Z value of each update rectangle
+	// Solid bitmaps with a Z order less than the value calculated here would be overdrawn again and
+	// so don't need to be drawn in the first place which speeds things up a bit.
+	for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
+		int minZ = 0;
+		for (RenderObjectQueue::iterator it = _currQueue->reverse_begin(); it != _currQueue->end(); --it) {
+			if ((*it)._renderObject->isVisible() && (*it)._renderObject->isSolid() &&
+				(*it)._renderObject->getBbox().contains(*rectIt)) {
+				minZ = (*it)._renderObject->getAbsoluteZ();
+				break;
+			}
+		}
+		updateRectsMinZ.push_back(minZ);
+	}
+
+	if (_rootPtr->render(updateRects, updateRectsMinZ)) {
+		// Copy updated rectangles to the video screen
+		Graphics::Surface *backSurface = Kernel::getInstance()->getGfx()->getSurface();
+		for (RectangleList::iterator rectIt = updateRects->begin(); rectIt != updateRects->end(); ++rectIt) {
+			const int x = (*rectIt).left;
+			const int y = (*rectIt).top;
+			const int width = (*rectIt).width();
+			const int height = (*rectIt).height();
+			g_system->copyRectToScreen(backSurface->getBasePtr(x, y), backSurface->pitch, x, y, width, height);
+		}
+	}
+
+	delete updateRects;
+	
+	SWAP(_currQueue, _prevQueue);
+	
+	renderDuration = g_system->getMillis() - renderDuration;
+	//debug("renderDuration: %3.5f", renderDuration / 1000.0f);
+	
+	return true;
 }
 
 void RenderObjectManager::attatchTimedRenderObject(RenderObjectPtr<TimedRenderObject> renderObjectPtr) {
diff --git a/engines/sword25/gfx/renderobjectmanager.h b/engines/sword25/gfx/renderobjectmanager.h
index 9e7efd8..1db91df 100644
--- a/engines/sword25/gfx/renderobjectmanager.h
+++ b/engines/sword25/gfx/renderobjectmanager.h
@@ -47,11 +47,28 @@
 #include "sword25/gfx/renderobjectptr.h"
 #include "sword25/kernel/persistable.h"
 
+#include "sword25/gfx/microtiles.h"
+
 namespace Sword25 {
 
 class Kernel;
 class RenderObject;
 class TimedRenderObject;
+class RenderObjectManager;
+
+struct RenderObjectQueueItem {
+	RenderObject *_renderObject;
+	Common::Rect _bbox;
+	int _version;
+	RenderObjectQueueItem(RenderObject *renderObject, const Common::Rect &bbox, int version)
+		: _renderObject(renderObject), _bbox(bbox), _version(version) {}
+};
+
+class RenderObjectQueue : public Common::List<RenderObjectQueueItem> {
+public:
+	void add(RenderObject *renderObject);
+	bool exists(const RenderObjectQueueItem &renderObjectQueueItem);
+};
 
 /**
     @brief Diese Klasse ist für die Verwaltung von BS_RenderObjects zuständig.
@@ -114,6 +131,9 @@ private:
 	typedef Common::Array<RenderObjectPtr<TimedRenderObject> > RenderObjectList;
 	RenderObjectList _timedRenderObjects;
 
+	MicroTileArray *_uta;
+	RenderObjectQueue *_currQueue, *_prevQueue;
+
 	// RenderObject-Tree Variablen
 	// ---------------------------
 	// Der Baum legt die hierachische Ordnung der BS_RenderObjects fest.
diff --git a/engines/sword25/gfx/rootrenderobject.h b/engines/sword25/gfx/rootrenderobject.h
index 4782fad..f1b19d6 100644
--- a/engines/sword25/gfx/rootrenderobject.h
+++ b/engines/sword25/gfx/rootrenderobject.h
@@ -59,7 +59,7 @@ private:
 	}
 
 protected:
-	virtual bool doRender() {
+	virtual bool doRender(RectangleList *updateRects) {
 		return true;
 	}
 };
diff --git a/engines/sword25/gfx/staticbitmap.cpp b/engines/sword25/gfx/staticbitmap.cpp
index 0ae07b3..91b93e8 100644
--- a/engines/sword25/gfx/staticbitmap.cpp
+++ b/engines/sword25/gfx/staticbitmap.cpp
@@ -71,6 +71,8 @@ bool StaticBitmap::initBitmapResource(const Common::String &filename) {
 	// RenderObject Eigenschaften aktualisieren
 	_originalWidth = _width = bitmapPtr->getWidth();
 	_originalHeight = _height = bitmapPtr->getHeight();
+	
+	_isSolid = bitmapPtr->isSolid();
 
 	// Bild-Resource freigeben
 	bitmapPtr->release();
@@ -81,7 +83,7 @@ bool StaticBitmap::initBitmapResource(const Common::String &filename) {
 StaticBitmap::~StaticBitmap() {
 }
 
-bool StaticBitmap::doRender() {
+bool StaticBitmap::doRender(RectangleList *updateRects) {
 	// Bitmap holen
 	Resource *resourcePtr = Kernel::getInstance()->getResourceManager()->requestResource(_resourceFilename);
 	assert(resourcePtr);
@@ -98,12 +100,14 @@ bool StaticBitmap::doRender() {
 		result = bitmapResourcePtr->blit(_absoluteX, _absoluteY,
 		                                 (_flipV ? BitmapResource::FLIP_V : 0) |
 		                                 (_flipH ? BitmapResource::FLIP_H : 0),
-		                                 0, _modulationColor, -1, -1);
+		                                 0, _modulationColor, -1, -1,
+										 updateRects);
 	} else {
 		result = bitmapResourcePtr->blit(_absoluteX, _absoluteY,
 		                                 (_flipV ? BitmapResource::FLIP_V : 0) |
 		                                 (_flipH ? BitmapResource::FLIP_H : 0),
-		                                 0, _modulationColor, _width, _height);
+		                                 0, _modulationColor, _width, _height,
+										 updateRects);
 	}
 
 	// Resource freigeben
diff --git a/engines/sword25/gfx/staticbitmap.h b/engines/sword25/gfx/staticbitmap.h
index e66ede0..90b92b4 100644
--- a/engines/sword25/gfx/staticbitmap.h
+++ b/engines/sword25/gfx/staticbitmap.h
@@ -65,7 +65,7 @@ public:
 	virtual bool unpersist(InputPersistenceBlock &reader);
 
 protected:
-	virtual bool doRender();
+	virtual bool doRender(RectangleList *updateRects);
 
 private:
 	Common::String _resourceFilename;
diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index 82bb7cd..a5cfb0b 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -129,7 +129,7 @@ void Text::setAutoWrapThreshold(uint autoWrapThreshold) {
 	}
 }
 
-bool Text::doRender() {
+bool Text::doRender(RectangleList *updateRects) {
 	// Font-Resource locken.
 	FontResource *fontPtr = lockFontResource();
 	if (!fontPtr)
@@ -171,7 +171,7 @@ bool Text::doRender() {
 
 			Common::Rect renderRect(curX, curY, curX + curRect.width(), curY + curRect.height());
 			renderRect.translate(curRect.left - curX, curRect.top - curY);
-			result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor);
+			result = charMapPtr->blit(curX, curY, Image::FLIP_NONE, &renderRect, _modulationColor, -1, -1, updateRects);
 			if (!result)
 				break;
 
diff --git a/engines/sword25/gfx/text.h b/engines/sword25/gfx/text.h
index a0d6680..94e7a30 100644
--- a/engines/sword25/gfx/text.h
+++ b/engines/sword25/gfx/text.h
@@ -136,7 +136,7 @@ public:
 	virtual bool  unpersist(InputPersistenceBlock &reader);
 
 protected:
-	virtual bool doRender();
+	virtual bool doRender(RectangleList *updateRects);
 
 private:
 	Text(RenderObjectPtr<RenderObject> parentPtr);
diff --git a/engines/sword25/module.mk b/engines/sword25/module.mk
index e24a221..234baec 100644
--- a/engines/sword25/module.mk
+++ b/engines/sword25/module.mk
@@ -16,6 +16,7 @@ MODULE_OBJS := \
 	gfx/fontresource.o \
 	gfx/graphicengine.o \
 	gfx/graphicengine_script.o \
+	gfx/microtiles.o \
 	gfx/panel.o \
 	gfx/renderobject.o \
 	gfx/renderobjectmanager.o \


Commit: e935f85366ba1e83fdd1cea3712959edee1f6270
    https://github.com/scummvm/scummvm/commit/e935f85366ba1e83fdd1cea3712959edee1f6270
Author: johndoe123 (john_doe at techie.com)
Date: 2013-04-17T10:54:39-07:00

Commit Message:
SWORD25: Change absolute Z calculation to match that of absolute x/y; remove old comment

Changed paths:
    engines/sword25/gfx/dynamicbitmap.cpp
    engines/sword25/gfx/renderobject.cpp
    engines/sword25/gfx/renderobject.h



diff --git a/engines/sword25/gfx/dynamicbitmap.cpp b/engines/sword25/gfx/dynamicbitmap.cpp
index aef04fe..242508b 100644
--- a/engines/sword25/gfx/dynamicbitmap.cpp
+++ b/engines/sword25/gfx/dynamicbitmap.cpp
@@ -78,8 +78,6 @@ bool DynamicBitmap::doRender(RectangleList *updateRects) {
 	GraphicEngine *pGfx = Kernel::getInstance()->getGfx();
 	assert(pGfx);
 	
-	//return true;//DEBUG
-
 	// Draw the bitmap
 	bool result;
 	if (_scaleFactorX == 1.0f && _scaleFactorY == 1.0f) {
diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp
index f2d2577..d138151 100644
--- a/engines/sword25/gfx/renderobject.cpp
+++ b/engines/sword25/gfx/renderobject.cpp
@@ -219,9 +219,10 @@ Common::Rect RenderObject::calcBoundingBox() const {
 	return bbox;
 }
 
-void RenderObject::calcAbsolutePos(int &x, int &y) const {
+void RenderObject::calcAbsolutePos(int &x, int &y, int &z) const {
 	x = calcAbsoluteX();
 	y = calcAbsoluteY();
+	z = calcAbsoluteZ();
 }
 
 int RenderObject::calcAbsoluteX() const {
@@ -238,6 +239,13 @@ int RenderObject::calcAbsoluteY() const {
 		return _y;
 }
 
+int RenderObject::calcAbsoluteZ() const {
+	if (_parentPtr.isValid())
+		return _parentPtr->getAbsoluteZ() + _z;
+	else
+		return _z;
+}
+
 void RenderObject::deleteAllChildren() {
 	// Es ist nicht notwendig die Liste zu iterieren, da jedes Kind für sich DetatchChildren an diesem Objekt aufruft und sich somit
 	// selber entfernt. Daher muss immer nur ein beliebiges Element (hier das letzte) gelöscht werden, bis die Liste leer ist.
@@ -281,7 +289,7 @@ void RenderObject::sortRenderObjects() {
 }
 
 void RenderObject::updateAbsolutePos() {
-	calcAbsolutePos(_absoluteX, _absoluteY);
+	calcAbsolutePos(_absoluteX, _absoluteY, _absoluteZ);
 
 	RENDEROBJECT_ITER it = _children.begin();
 	for (; it != _children.end(); ++it)
@@ -313,15 +321,10 @@ void RenderObject::setY(int y) {
 void RenderObject::setZ(int z) {
 	if (z < 0)
 		error("Tried to set a negative Z value (%d).", z);
-	else
+	else {
 		_z = z;
-}
-
-int RenderObject::getAbsoluteZ() const {
-	if (_parentPtr.isValid())
-		return _parentPtr->getAbsoluteZ() + _z;
-	else
-		return _z;
+		updateAbsolutePos();
+	}
 }
 
 void RenderObject::setVisible(bool visible) {
diff --git a/engines/sword25/gfx/renderobject.h b/engines/sword25/gfx/renderobject.h
index a22893a..48cbf8e 100644
--- a/engines/sword25/gfx/renderobject.h
+++ b/engines/sword25/gfx/renderobject.h
@@ -305,7 +305,9 @@ public:
 		return _z;
 	}
 	
-	int getAbsoluteZ() const;
+	int getAbsoluteZ() const {
+		return _absoluteZ;
+	}
 	
 	/**
 	    @brief Gibt die Breite des Objektes zurück.
@@ -387,9 +389,10 @@ protected:
 
 	int         _x;            ///< Die X-Position des Objektes relativ zum Eltern-Objekt
 	int         _y;            ///< Die Y-Position des Objektes relativ zum Eltern-Objekt
+	int         _z;            ///< Der Z-Wert des Objektes relativ zum Eltern-Objekt
 	int         _absoluteX;    ///< Die absolute X-Position des Objektes
 	int         _absoluteY;    ///< Die absolute Y-Position des Objektes
-	int         _z;            ///< Der Z-Wert des Objektes relativ zum Eltern-Objekt
+	int			_absoluteZ;
 	int         _width;        ///< Die Breite des Objektes
 	int         _height;       ///< Die Höhe des Objektes
 	bool        _visible;      ///< Ist true, wenn das Objekt sichtbar ist
@@ -496,7 +499,7 @@ private:
 	/**
 	    @brief Berechnet die absolute Position des Objektes.
 	*/
-	void calcAbsolutePos(int &x, int &y) const;
+	void calcAbsolutePos(int &x, int &y, int &z) const;
 	/**
 	    @brief Berechnet die absolute Position des Objektes auf der X-Achse.
 	*/
@@ -505,6 +508,9 @@ private:
 	    @brief Berechnet die absolute Position des Objektes.
 	*/
 	int calcAbsoluteY() const;
+	
+	int calcAbsoluteZ() const;
+	
 	/**
 	    @brief Sortiert alle Kinderobjekte nach ihrem Renderang.
 	 */


Commit: 176a3babc553d1d6eb2a57fddb0a9665fc4aaa71
    https://github.com/scummvm/scummvm/commit/176a3babc553d1d6eb2a57fddb0a9665fc4aaa71
Author: johndoe123 (john_doe at techie.com)
Date: 2013-04-18T10:08:22-07:00

Commit Message:
Merge branch 'master' of github.com:scummvm/scummvm into sword25-gfx

Changed paths:
  A engines/wintermute/base/base_game_settings.cpp
  A engines/wintermute/base/base_game_settings.h
  A engines/wintermute/base/save_thumb_helper.cpp
  A engines/wintermute/base/save_thumb_helper.h
  A engines/wintermute/base/timer.cpp
  A engines/wintermute/base/timer.h
  R engines/wintermute/base/base_save_thumb_helper.cpp
  R engines/wintermute/base/base_save_thumb_helper.h
    configure
    engines/agi/op_test.cpp
    engines/cge/text.cpp
    engines/cge/vga13h.cpp
    engines/dreamweb/newplace.cpp
    engines/hopkins/graphics.cpp
    engines/hopkins/saveload.cpp
    engines/kyra/gui_eob.cpp
    engines/kyra/gui_lol.cpp
    engines/kyra/items_lol.cpp
    engines/kyra/lol.cpp
    engines/kyra/scene_eob.cpp
    engines/kyra/scene_lol.cpp
    engines/kyra/screen_eob.cpp
    engines/kyra/sequences_hof.cpp
    engines/kyra/sprites_eob.cpp
    engines/kyra/sprites_lol.cpp
    engines/kyra/timer_eob.cpp
    engines/parallaction/dialogue.cpp
    engines/parallaction/disk_ns.cpp
    engines/parallaction/input.cpp
    engines/parallaction/parser_ns.cpp
    engines/parallaction/sound_br.cpp
    engines/sci/console.cpp
    engines/sci/parser/vocabulary.cpp
    engines/sci/resource.cpp
    engines/sci/sound/drivers/midi.cpp
    engines/sword25/util/lua/ldo.cpp
    engines/sword25/util/lua/lua.h
    engines/wintermute/ad/ad_actor.cpp
    engines/wintermute/ad/ad_actor.h
    engines/wintermute/ad/ad_entity.cpp
    engines/wintermute/ad/ad_entity.h
    engines/wintermute/ad/ad_game.cpp
    engines/wintermute/ad/ad_game.h
    engines/wintermute/ad/ad_inventory.h
    engines/wintermute/ad/ad_inventory_box.cpp
    engines/wintermute/ad/ad_inventory_box.h
    engines/wintermute/ad/ad_item.cpp
    engines/wintermute/ad/ad_item.h
    engines/wintermute/ad/ad_layer.h
    engines/wintermute/ad/ad_node_state.cpp
    engines/wintermute/ad/ad_object.cpp
    engines/wintermute/ad/ad_object.h
    engines/wintermute/ad/ad_path.h
    engines/wintermute/ad/ad_path_point.h
    engines/wintermute/ad/ad_region.h
    engines/wintermute/ad/ad_response.cpp
    engines/wintermute/ad/ad_response.h
    engines/wintermute/ad/ad_response_box.cpp
    engines/wintermute/ad/ad_response_box.h
    engines/wintermute/ad/ad_response_context.h
    engines/wintermute/ad/ad_rot_level.h
    engines/wintermute/ad/ad_scale_level.h
    engines/wintermute/ad/ad_scene.cpp
    engines/wintermute/ad/ad_scene.h
    engines/wintermute/ad/ad_sentence.cpp
    engines/wintermute/ad/ad_sentence.h
    engines/wintermute/ad/ad_sprite_set.h
    engines/wintermute/ad/ad_talk_def.h
    engines/wintermute/ad/ad_talk_holder.h
    engines/wintermute/ad/ad_talk_node.h
    engines/wintermute/ad/ad_waypoint_group.h
    engines/wintermute/base/base.cpp
    engines/wintermute/base/base_active_rect.cpp
    engines/wintermute/base/base_active_rect.h
    engines/wintermute/base/base_engine.cpp
    engines/wintermute/base/base_engine.h
    engines/wintermute/base/base_fader.cpp
    engines/wintermute/base/base_file_manager.cpp
    engines/wintermute/base/base_frame.cpp
    engines/wintermute/base/base_frame.h
    engines/wintermute/base/base_game.cpp
    engines/wintermute/base/base_game.h
    engines/wintermute/base/base_game_music.cpp
    engines/wintermute/base/base_game_music.h
    engines/wintermute/base/base_named_object.h
    engines/wintermute/base/base_object.cpp
    engines/wintermute/base/base_object.h
    engines/wintermute/base/base_parser.cpp
    engines/wintermute/base/base_parser.h
    engines/wintermute/base/base_persistence_manager.cpp
    engines/wintermute/base/base_point.h
    engines/wintermute/base/base_region.cpp
    engines/wintermute/base/base_region.h
    engines/wintermute/base/base_script_holder.cpp
    engines/wintermute/base/base_script_holder.h
    engines/wintermute/base/base_scriptable.cpp
    engines/wintermute/base/base_scriptable.h
    engines/wintermute/base/base_sprite.cpp
    engines/wintermute/base/base_sprite.h
    engines/wintermute/base/base_string_table.cpp
    engines/wintermute/base/base_sub_frame.cpp
    engines/wintermute/base/base_sub_frame.h
    engines/wintermute/base/base_surface_storage.cpp
    engines/wintermute/base/base_transition_manager.cpp
    engines/wintermute/base/base_viewport.cpp
    engines/wintermute/base/base_viewport.h
    engines/wintermute/base/file/base_package.h
    engines/wintermute/base/gfx/base_renderer.h
    engines/wintermute/base/gfx/base_surface.cpp
    engines/wintermute/base/gfx/base_surface.h
    engines/wintermute/base/particles/part_emitter.cpp
    engines/wintermute/base/particles/part_emitter.h
    engines/wintermute/base/particles/part_particle.h
    engines/wintermute/base/saveload.cpp
    engines/wintermute/base/scriptables/script.cpp
    engines/wintermute/base/scriptables/script.h
    engines/wintermute/base/scriptables/script_engine.cpp
    engines/wintermute/base/scriptables/script_ext_array.h
    engines/wintermute/base/scriptables/script_ext_file.h
    engines/wintermute/base/scriptables/script_ext_mem_buffer.h
    engines/wintermute/base/scriptables/script_ext_string.cpp
    engines/wintermute/base/scriptables/script_ext_string.h
    engines/wintermute/base/scriptables/script_stack.h
    engines/wintermute/base/scriptables/script_value.h
    engines/wintermute/base/sound/base_sound.h
    engines/wintermute/base/sound/base_sound_buffer.h
    engines/wintermute/base/sound/base_sound_manager.cpp
    engines/wintermute/base/sound/base_sound_manager.h
    engines/wintermute/debugger.cpp
    engines/wintermute/graphics/transparent_surface.cpp
    engines/wintermute/module.mk
    engines/wintermute/system/sys_class_registry.cpp
    engines/wintermute/ui/ui_button.cpp
    engines/wintermute/ui/ui_button.h
    engines/wintermute/ui/ui_edit.cpp
    engines/wintermute/ui/ui_edit.h
    engines/wintermute/ui/ui_entity.h
    engines/wintermute/ui/ui_object.h
    engines/wintermute/ui/ui_text.cpp
    engines/wintermute/ui/ui_text.h
    engines/wintermute/ui/ui_tiled_image.h
    engines/wintermute/ui/ui_window.cpp
    engines/wintermute/ui/ui_window.h
    engines/wintermute/video/video_player.h
    engines/wintermute/video/video_theora_player.cpp
    engines/wintermute/video/video_theora_player.h
    engines/wintermute/wintermute.cpp





Commit: 4fc57dac8fd6865494d21acfddeb69ab7fb1ad5c
    https://github.com/scummvm/scummvm/commit/4fc57dac8fd6865494d21acfddeb69ab7fb1ad5c
Author: johndoe123 (john_doe at techie.com)
Date: 2013-04-19T15:34:32-07:00

Commit Message:
SWORD25: Fix blitting code
- Rename collectRenderQueue to preRender
- Only do forceRefresh() in Panel::setColor() and Text::setText() if the new values are different
- Move child object resorting from RenderObject::render() into RenderObject::preRender()

Changed paths:
    engines/sword25/gfx/image/renderedimage.cpp
    engines/sword25/gfx/panel.h
    engines/sword25/gfx/renderobject.cpp
    engines/sword25/gfx/renderobject.h
    engines/sword25/gfx/renderobjectmanager.cpp
    engines/sword25/gfx/text.cpp



diff --git a/engines/sword25/gfx/image/renderedimage.cpp b/engines/sword25/gfx/image/renderedimage.cpp
index 1de7a04..c8a6666 100644
--- a/engines/sword25/gfx/image/renderedimage.cpp
+++ b/engines/sword25/gfx/image/renderedimage.cpp
@@ -145,7 +145,10 @@ RenderedImage::RenderedImage(const Common::String &filename, bool &result) :
 
 	_doCleanup = true;
 
+#if defined(SCUMM_LITTLE_ENDIAN)
+	// Makes sense for LE only at the moment
 	checkForTransparency();
+#endif
 
 	return;
 }
@@ -295,20 +298,20 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
 		int drawX = posX, drawY = posY;
 		int drawWidth = img->w;
 		int drawHeight = img->h;
-	
+
 		// Handle clipping
-		if (drawY < clipRect.top) {
-			skipTop = clipRect.top - drawY;
-			drawHeight = MAX(0, (int)drawHeight - (clipRect.top - drawY));
-			drawY = clipRect.top;
-		}
-	
 		if (drawX < clipRect.left) {
 			skipLeft = clipRect.left - drawX;
-			drawWidth = MAX(0, (int)drawWidth - skipLeft);
+			drawWidth -= skipLeft;
 			drawX = clipRect.left;
 		}
 		
+		if (drawY < clipRect.top) {
+			skipTop = clipRect.top - drawY;
+			drawHeight -= skipTop;
+			drawY = clipRect.top;
+		}
+
 		if (drawX + drawWidth >= clipRect.right)
 			drawWidth = clipRect.right - drawX;
 	
@@ -358,16 +361,16 @@ bool RenderedImage::blit(int posX, int posY, int flipping, Common::Rect *pPartRe
 						int a = (pix >> 24) & 0xff;
 						in += inStep;
 						
+						if (ca != 255) {
+							a = a * ca >> 8;
+						}
+
 						if (a == 0) {
 							// Full transparency
 							out += 4;
 							continue;
 						}
 						
-						if (ca != 255) {
-							a = a * ca >> 8;
-						}
-		
 						int b = (pix >> 0) & 0xff;
 						int g = (pix >> 8) & 0xff;
 						int r = (pix >> 16) & 0xff;
diff --git a/engines/sword25/gfx/panel.h b/engines/sword25/gfx/panel.h
index cb94048..74a9324 100644
--- a/engines/sword25/gfx/panel.h
+++ b/engines/sword25/gfx/panel.h
@@ -51,8 +51,10 @@ public:
 		return _color;
 	}
 	void setColor(uint color) {
-		_color = color;
-		forceRefresh();
+		if (_color != color) {
+			_color = color;
+			forceRefresh();
+		}
 	}
 
 	virtual bool persist(OutputPersistenceBlock &writer);
diff --git a/engines/sword25/gfx/renderobject.cpp b/engines/sword25/gfx/renderobject.cpp
index d138151..807c1eb 100644
--- a/engines/sword25/gfx/renderobject.cpp
+++ b/engines/sword25/gfx/renderobject.cpp
@@ -110,13 +110,12 @@ RenderObject::~RenderObject() {
 	RenderObjectRegistry::instance().deregisterObject(this);
 }
 
-bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ) {
+void RenderObject::preRender(RenderObjectQueue *renderQueue) {
 	// Objektänderungen validieren
 	validateObject();
 
-	// Falls das Objekt nicht sichtbar ist, muss gar nichts gezeichnet werden
 	if (!_visible)
-		return true;
+		return;
 
 	// Falls notwendig, wird die Renderreihenfolge der Kinderobjekte aktualisiert.
 	if (_childChanged) {
@@ -124,6 +123,20 @@ bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &
 		_childChanged = false;
 	}
 
+	renderQueue->add(this);
+
+	RENDEROBJECT_ITER it = _children.begin();
+	for (; it != _children.end(); ++it)
+		(*it)->preRender(renderQueue);
+
+}
+
+bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ) {
+
+	// Falls das Objekt nicht sichtbar ist, muss gar nichts gezeichnet werden
+	if (!_visible)
+		return true;
+
 	// Objekt zeichnen.
 	bool needRender = false;
 	int index = 0;
@@ -145,19 +158,6 @@ bool RenderObject::render(RectangleList *updateRects, const Common::Array<int> &
 	return true;
 }
 
-void RenderObject::collectRenderQueue(RenderObjectQueue *renderQueue) {
-
-	if (!_visible)
-		return;
-
-	renderQueue->add(this);
-
-	RENDEROBJECT_ITER it = _children.begin();
-	for (; it != _children.end(); ++it)
-		(*it)->collectRenderQueue(renderQueue);
-
-}
-
 void RenderObject::validateObject() {
 	// Die Veränderungen in den Objektvariablen aufheben
 	_oldBbox = _bbox;
diff --git a/engines/sword25/gfx/renderobject.h b/engines/sword25/gfx/renderobject.h
index 48cbf8e..7e0334e 100644
--- a/engines/sword25/gfx/renderobject.h
+++ b/engines/sword25/gfx/renderobject.h
@@ -213,6 +213,9 @@ public:
 
 	// Interface
 	// ---------
+
+	void preRender(RenderObjectQueue *renderQueue);
+
 	/**
 	    @brief Rendert des Objekt und alle seine Unterobjekte.
 	    @return Gibt false zurück, falls beim Rendern ein Fehler aufgetreten ist.
@@ -222,8 +225,6 @@ public:
 	*/
 	bool render(RectangleList *updateRects, const Common::Array<int> &updateRectsMinZ);
 
-	void collectRenderQueue(RenderObjectQueue *renderQueue);
-
 	/**
 	    @brief Bereitet das Objekt und alle seine Unterobjekte auf einen Rendervorgang vor.
 	           Hierbei werden alle Dirty-Rectangles berechnet und die Renderreihenfolge aktualisiert.
diff --git a/engines/sword25/gfx/renderobjectmanager.cpp b/engines/sword25/gfx/renderobjectmanager.cpp
index a8f8c36..994d936 100644
--- a/engines/sword25/gfx/renderobjectmanager.cpp
+++ b/engines/sword25/gfx/renderobjectmanager.cpp
@@ -97,12 +97,11 @@ bool RenderObjectManager::render() {
 
 	// Die Render-Methode der Wurzel aufrufen. Dadurch wird das rekursive Rendern der Baumelemente angestoßen.
 
-	uint32 renderDuration = g_system->getMillis();
-	
 	_currQueue->clear();
-	_rootPtr->collectRenderQueue(_currQueue);
+	_rootPtr->preRender(_currQueue);
 
 	_uta->clear();
+
 	// Add rectangles of objects which don't exist in this frame any more
     for (RenderObjectQueue::iterator it = _prevQueue->begin(); it != _prevQueue->end(); ++it)
     	if (!_currQueue->exists(*it))
@@ -111,7 +110,7 @@ bool RenderObjectManager::render() {
     for (RenderObjectQueue::iterator it = _currQueue->begin(); it != _currQueue->end(); ++it)
     	if (!_prevQueue->exists(*it))
     		_uta->addRect((*it)._bbox);
-	
+
 	RectangleList *updateRects = _uta->getRectangles();
 	Common::Array<int> updateRectsMinZ;
 	
@@ -148,9 +147,6 @@ bool RenderObjectManager::render() {
 	
 	SWAP(_currQueue, _prevQueue);
 	
-	renderDuration = g_system->getMillis() - renderDuration;
-	//debug("renderDuration: %3.5f", renderDuration / 1000.0f);
-	
 	return true;
 }
 
diff --git a/engines/sword25/gfx/text.cpp b/engines/sword25/gfx/text.cpp
index a5cfb0b..d4aaa90 100644
--- a/engines/sword25/gfx/text.cpp
+++ b/engines/sword25/gfx/text.cpp
@@ -91,9 +91,11 @@ bool Text::setFont(const Common::String &font) {
 }
 
 void Text::setText(const Common::String &text) {
-	_text = text;
-	updateFormat();
-	forceRefresh();
+	if (_text != text) {
+		_text = text;
+		updateFormat();
+		forceRefresh();
+	}
 }
 
 void Text::setColor(uint modulationColor) {


Commit: 4a62d6c25a4994a72c59ca3b8f2913ead565a173
    https://github.com/scummvm/scummvm/commit/4a62d6c25a4994a72c59ca3b8f2913ead565a173
Author: Eugene Sandulenko (sev at scummvm.org)
Date: 2013-05-06T03:49:21-07:00

Commit Message:
Merge pull request #320 from johndoe123/sword25-gfx

SWORD25: Optimized graphics drawing

Changed paths:
  A engines/sword25/gfx/microtiles.cpp
  A engines/sword25/gfx/microtiles.h
    engines/sword25/gfx/animation.cpp
    engines/sword25/gfx/animation.h
    engines/sword25/gfx/bitmapresource.h
    engines/sword25/gfx/dynamicbitmap.cpp
    engines/sword25/gfx/dynamicbitmap.h
    engines/sword25/gfx/graphicengine.cpp
    engines/sword25/gfx/image/image.h
    engines/sword25/gfx/image/renderedimage.cpp
    engines/sword25/gfx/image/renderedimage.h
    engines/sword25/gfx/image/swimage.cpp
    engines/sword25/gfx/image/swimage.h
    engines/sword25/gfx/image/vectorimage.cpp
    engines/sword25/gfx/image/vectorimage.h
    engines/sword25/gfx/panel.cpp
    engines/sword25/gfx/panel.h
    engines/sword25/gfx/renderobject.cpp
    engines/sword25/gfx/renderobject.h
    engines/sword25/gfx/renderobjectmanager.cpp
    engines/sword25/gfx/renderobjectmanager.h
    engines/sword25/gfx/rootrenderobject.h
    engines/sword25/gfx/staticbitmap.cpp
    engines/sword25/gfx/staticbitmap.h
    engines/sword25/gfx/text.cpp
    engines/sword25/gfx/text.h
    engines/sword25/module.mk









More information about the Scummvm-git-logs mailing list