comparison engine/core/view/renderers/instancerenderer.cpp @ 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 7d88eddd2ec7
children da381ecca97d
comparison
equal deleted inserted replaced
570:0e0a30f0eb20 571:edc9efe969c2
57 InstanceRenderer::OutlineInfo::OutlineInfo(): 57 InstanceRenderer::OutlineInfo::OutlineInfo():
58 r(0), 58 r(0),
59 g(0), 59 g(0),
60 b(0), 60 b(0),
61 width(1), 61 width(1),
62 dirty(false),
62 outline(NULL), 63 outline(NULL),
63 curimg(NULL) { 64 curimg(NULL) {
64 } 65 }
65 InstanceRenderer::ColoringInfo::ColoringInfo(): 66 InstanceRenderer::ColoringInfo::ColoringInfo():
66 r(0), 67 r(0),
67 g(0), 68 g(0),
68 b(0), 69 b(0),
70 dirty(false),
69 overlay(NULL), 71 overlay(NULL),
70 curimg(NULL) { 72 curimg(NULL) {
71 } 73 }
72 74
73 InstanceRenderer::OutlineInfo::~OutlineInfo() { 75 InstanceRenderer::OutlineInfo::~OutlineInfo() {
159 vc.image->render(vc.dimensions, 255-trans); 161 vc.image->render(vc.dimensions, 255-trans);
160 } 162 }
161 } 163 }
162 164
163 Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) { 165 Image* InstanceRenderer::bindOutline(OutlineInfo& info, RenderItem& vc, Camera* cam) {
164 if (info.curimg == vc.image) { 166 if (!info.dirty && info.curimg == vc.image) {
167 // optimization for outline that has not changed
165 return info.outline; 168 return info.outline;
166 } else { 169 } else {
167 info.curimg = vc.image; 170 info.curimg = vc.image;
168 } 171 }
169 172
220 } 223 }
221 224
222 // In case of OpenGL backend, SDLImage needs to be converted 225 // In case of OpenGL backend, SDLImage needs to be converted
223 info.outline = m_renderbackend->createImage(img->detachSurface()); 226 info.outline = m_renderbackend->createImage(img->detachSurface());
224 delete img; 227 delete img;
228
229 if (info.outline) {
230 // mark outline as not dirty since we created it here
231 info.dirty = false;
232 }
233
225 return info.outline; 234 return info.outline;
226 } 235 }
227 236
228 Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) { 237 Image* InstanceRenderer::bindColoring(ColoringInfo& info, RenderItem& vc, Camera* cam) {
229 if (info.curimg == vc.image) { 238 if (!info.dirty && info.curimg == vc.image) {
239 // optimization for coloring overlay that has not changed
230 return info.overlay; 240 return info.overlay;
231 } else { 241 }
242 else {
232 info.curimg = vc.image; 243 info.curimg = vc.image;
233 } 244 }
245
234 if (info.overlay) { 246 if (info.overlay) {
235 delete info.overlay; // delete old mask 247 delete info.overlay; // delete old mask
236 info.overlay = NULL; 248 info.overlay = NULL;
237 } 249 }
250
238 SDL_Surface* surface = vc.image->getSurface(); 251 SDL_Surface* surface = vc.image->getSurface();
239 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags); 252 SDL_Surface* overlay_surface = SDL_ConvertSurface(surface, surface->format, surface->flags);
240 253
241 // needs to use SDLImage here, since GlImage does not support drawing primitives atm 254 // needs to use SDLImage here, since GlImage does not support drawing primitives atm
242 SDLImage* img = new SDLImage(overlay_surface); 255 SDLImage* img = new SDLImage(overlay_surface);
253 } 266 }
254 267
255 // In case of OpenGL backend, SDLImage needs to be converted 268 // In case of OpenGL backend, SDLImage needs to be converted
256 info.overlay = m_renderbackend->createImage(img->detachSurface()); 269 info.overlay = m_renderbackend->createImage(img->detachSurface());
257 delete img; 270 delete img;
271
272 if (info.overlay) {
273 // mark overlay coloring as not dirty since we created it here
274 info.dirty = false;
275 }
276
258 return info.overlay; 277 return info.overlay;
259 } 278 }
260 279
261 void InstanceRenderer::addOutlined(Instance* instance, int r, int g, int b, int width) { 280 void InstanceRenderer::addOutlined(Instance* instance, int r, int g, int b, int width) {
262 OutlineInfo newinfo; 281 OutlineInfo newinfo;
263 newinfo.r = r; 282 newinfo.r = r;
264 newinfo.g = g; 283 newinfo.g = g;
265 newinfo.b = b; 284 newinfo.b = b;
266 newinfo.width = width; 285 newinfo.width = width;
286 newinfo.dirty = true;
267 287
268 // attempts to insert the element into the outline map 288 // attempts to insert the element into the outline map
269 // will return false in the second value of the pair if the instance already exists 289 // will return false in the second value of the pair if the instance already exists
270 // in the map and the first value of the pair will then be an iterator to the 290 // in the map and the first value of the pair will then be an iterator to the
271 // existing data for the instance 291 // existing data for the instance
272 std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo)); 292 std::pair<InstanceToOutlines_t::iterator, bool> insertiter = m_instance_outlines.insert(std::make_pair(instance, newinfo));
273 293
274 if (insertiter.second == false) 294 if (insertiter.second == false) {
275 {
276 // the insertion did not happen because the instance 295 // the insertion did not happen because the instance
277 // already exists in the map so lets just update its outline info 296 // already exists in the map so lets just update its outline info
278 OutlineInfo& info = insertiter.first->second; 297 OutlineInfo& info = insertiter.first->second;
279 info.r = r; 298
280 info.b = b; 299 if (info.r != r || info.g != g || info.b != b || info.width != width) {
281 info.g = g; 300 // only update the outline info if its changed since the last call
282 info.width = width; 301 // flag the outline info as dirty so it will get processed during rendering
302 info.r = r;
303 info.b = b;
304 info.g = g;
305 info.width = width;
306 info.dirty = true;
307 }
283 } 308 }
284 } 309 }
285 310
286 void InstanceRenderer::addColored(Instance* instance, int r, int g, int b) { 311 void InstanceRenderer::addColored(Instance* instance, int r, int g, int b) {
287 ColoringInfo newinfo; 312 ColoringInfo newinfo;
288 newinfo.r = r; 313 newinfo.r = r;
289 newinfo.g = g; 314 newinfo.g = g;
290 newinfo.b = b; 315 newinfo.b = b;
291 316 newinfo.dirty = true;
317
292 // attempts to insert the element into the coloring map 318 // attempts to insert the element into the coloring map
293 // will return false in the second value of the pair if the instance already exists 319 // will return false in the second value of the pair if the instance already exists
294 // in the map and the first value of the pair will then be an iterator to the 320 // in the map and the first value of the pair will then be an iterator to the
295 // existing data for the instance 321 // existing data for the instance
296 std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo)); 322 std::pair<InstanceToColoring_t::iterator, bool> insertiter = m_instance_colorings.insert(std::make_pair(instance, newinfo));
297 323
298 if (insertiter.second == false) 324 if (insertiter.second == false) {
299 {
300 // the insertion did not happen because the instance 325 // the insertion did not happen because the instance
301 // already exists in the map so lets just update its coloring info 326 // already exists in the map so lets just update its coloring info
302 ColoringInfo& info = insertiter.first->second; 327 ColoringInfo& info = insertiter.first->second;
303 info.r = r; 328
304 info.b = b; 329 if (info.r != r || info.g != g || info.b != b) {
305 info.g = g; 330 // only update the coloring info if its changed since the last call
331 // flag the coloring info as dirty so it will get processed during rendering
332 info.r = r;
333 info.b = b;
334 info.g = g;
335 info.dirty = true;
336 }
306 } 337 }
307 } 338 }
308 339
309 void InstanceRenderer::removeOutlined(Instance* instance) { 340 void InstanceRenderer::removeOutlined(Instance* instance) {
310 m_instance_outlines.erase(instance); 341 m_instance_outlines.erase(instance);