changeset 571:edc9efe969c2

This commit should fix the coloring overlay bug exposed by the commit in revision 3386. The InstanceRenderer was caching the overlays based on whether the current image had changed. The fix takes into account the current image as well as the overlay color to decide whether or not the overlay needs to be reproduced.
author vtchill@33b003aa-7bff-0310-803a-e67f0ece8222
date Tue, 29 Jun 2010 02:26:28 +0000
parents 0e0a30f0eb20
children da381ecca97d
files engine/core/view/renderers/instancerenderer.cpp engine/core/view/renderers/instancerenderer.h
diffstat 2 files changed, 49 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/engine/core/view/renderers/instancerenderer.cpp	Mon Jun 28 21:28:44 2010 +0000
+++ b/engine/core/view/renderers/instancerenderer.cpp	Tue Jun 29 02:26:28 2010 +0000
@@ -59,6 +59,7 @@
 		g(0),
 		b(0),
 		width(1),
+		dirty(false),
 		outline(NULL),
 		curimg(NULL) {
 	}
@@ -66,6 +67,7 @@
 		r(0),
 		g(0),
 		b(0),
+		dirty(false),
 		overlay(NULL),
 		curimg(NULL) {
 	}
@@ -161,7 +163,8 @@
 	}
 
 	Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) {
-		if (info.curimg == vc.image) {
+		if (!info.dirty && info.curimg == vc.image) {
+			// optimization for outline that has not changed
 			return info.outline;
 		} else {
 			info.curimg = vc.image;
@@ -222,19 +225,29 @@
 		// In case of OpenGL backend, SDLImage needs to be converted
 		info.outline = m_renderbackend->createImage(img->detachSurface());
 		delete img;
+
+		if (info.outline) {
+			// mark outline as not dirty since we created it here
+			info.dirty = false;
+		}
+
 		return info.outline;
 	}
 
 	Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) {
-		if (info.curimg == vc.image) {
+		if (!info.dirty && info.curimg == vc.image) {
+			// optimization for coloring overlay that has not changed
 			return info.overlay;
-		} else {
+		}
+		else {
 			info.curimg = vc.image;
 		}
+		
 		if (info.overlay) {
 			delete info.overlay; // delete old mask
 			info.overlay = NULL;
 		}
+
 		SDL_Surface* surface = vc.image->getSurface();
 		SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags);
 
@@ -255,6 +268,12 @@
 		// In case of OpenGL backend, SDLImage needs to be converted
 		info.overlay = m_renderbackend->createImage(img->detachSurface());
 		delete img;
+
+		if (info.overlay) {
+			// mark overlay coloring as not dirty since we created it here
+			info.dirty = false;
+		}
+
 		return info.overlay;
 	}
 
@@ -264,6 +283,7 @@
 		newinfo.g = g;
 		newinfo.b = b;
 		newinfo.width = width;
+		newinfo.dirty = true;
 
 		// attempts to insert the element into the outline map
 		// will return false in the second value of the pair if the instance already exists 
@@ -271,15 +291,20 @@
 		// existing data for the instance
 		std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo));
 
-		if (insertiter.second == false)
-		{
+		if (insertiter.second == false) {
 			// the insertion did not happen because the instance 
 			// already exists in the map so lets just update its outline info
 			OutlineInfo& info = insertiter.first->second;
-			info.r = r;
-			info.b = b;
-			info.g = g;
-			info.width = width;
+
+			if (info.r != r || info.g != g || info.b != b || info.width != width) {
+				// only update the outline info if its changed since the last call
+				// flag the outline info as dirty so it will get processed during rendering
+				info.r = r;
+				info.b = b;
+				info.g = g;
+				info.width = width;
+				info.dirty = true;
+			}
 		}
 	}
 
@@ -288,21 +313,27 @@
 		newinfo.r = r;
 		newinfo.g = g;
 		newinfo.b = b;
-		
+		newinfo.dirty = true;
+
 		// attempts to insert the element into the coloring map
 		// will return false in the second value of the pair if the instance already exists 
 		// in the map and the first value of the pair will then be an iterator to the 
 		// existing data for the instance
 		std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo));
 
-		if (insertiter.second == false)
-		{
+		if (insertiter.second == false) {
 			// the insertion did not happen because the instance 
 			// already exists in the map so lets just update its coloring info
 			ColoringInfo& info = insertiter.first->second;
-			info.r = r;
-			info.b = b;
-			info.g = g;
+
+			if (info.r != r || info.g != g || info.b != b) {
+				// only update the coloring info if its changed since the last call
+				// flag the coloring info as dirty so it will get processed during rendering
+				info.r = r;
+				info.b = b;
+				info.g = g;
+				info.dirty = true;
+			}
 		}
 	}
 
--- a/engine/core/view/renderers/instancerenderer.h	Mon Jun 28 21:28:44 2010 +0000
+++ b/engine/core/view/renderers/instancerenderer.h	Tue Jun 29 02:26:28 2010 +0000
@@ -98,6 +98,7 @@
 			uint8_t g;
 			uint8_t b;
 			int width;
+			bool dirty;
 			Image* outline;
 			Image* curimg;
 			OutlineInfo();
@@ -109,6 +110,7 @@
 			uint8_t r;
 			uint8_t g;
 			uint8_t b;
+			bool dirty;
 			Image* overlay;
 			Image* curimg;
 			ColoringInfo();
@@ -116,6 +118,7 @@
 		};
 		typedef std::map<Instance*, OutlineInfo> InstanceToOutlines_t;
 		typedef std::map<Instance*, ColoringInfo> InstanceToColoring_t;
+		//typedef std::map<int, ColoringInfo> InstanceToColoring_t;
 		
 		InstanceToOutlines_t m_instance_outlines;
 		InstanceToColoring_t m_instance_colorings;