[Scummvm-cvs-logs] SF.net SVN: scummvm:[40156] scummvm/trunk/engines/sci/gfx

fingolfin at users.sourceforge.net fingolfin at users.sourceforge.net
Mon Apr 27 13:12:25 CEST 2009


Revision: 40156
          http://scummvm.svn.sourceforge.net/scummvm/?rev=40156&view=rev
Author:   fingolfin
Date:     2009-04-27 11:12:25 +0000 (Mon, 27 Apr 2009)

Log Message:
-----------
SCI: Rewrote dirty rect code to use Common::List

Modified Paths:
--------------
    scummvm/trunk/engines/sci/gfx/gfx_state_internal.h
    scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp
    scummvm/trunk/engines/sci/gfx/operations.cpp
    scummvm/trunk/engines/sci/gfx/operations.h

Modified: scummvm/trunk/engines/sci/gfx/gfx_state_internal.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_state_internal.h	2009-04-27 11:12:08 UTC (rev 40155)
+++ scummvm/trunk/engines/sci/gfx/gfx_state_internal.h	2009-04-27 11:12:25 UTC (rev 40156)
@@ -294,7 +294,7 @@
 
 struct GfxContainer : public GfxWidget {
 	rect_t zone; /* The writeable zone (absolute) for contained objects */
-	gfx_dirty_rect_t *_dirty; /* List of dirty rectangles */
+	DirtyRectList _dirtyRects; /* List of dirty rectangles */
 	GfxWidget *_contents;
 	GfxWidget **_nextpp; /* Pointer to the 'next' pointer in the last entry in contents */
 

Modified: scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp	2009-04-27 11:12:08 UTC (rev 40155)
+++ scummvm/trunk/engines/sci/gfx/gfx_widgets.cpp	2009-04-27 11:12:25 UTC (rev 40156)
@@ -991,18 +991,14 @@
 }
 
 void GfxContainer::print(int indentation) const {
-	gfx_dirty_rect_t *dirty;
-
 	sciprintf(" viszone=((%d,%d),(%dx%d))\n", zone.x, zone.y, zone.width, zone.height);
 
 	indent(indentation);
 	sciprintf("--dirty:\n");
 
-	dirty = _dirty;
-	while (dirty) {
+	for (DirtyRectList::const_iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) {
 		indent(indentation + 1);
-		sciprintf("dirty(%d,%d, (%dx%d))\n", dirty->rect.x, dirty->rect.y, dirty->rect.width, dirty->rect.height);
-		dirty = dirty->next;
+		sciprintf("dirty(%d,%d, (%dx%d))\n", dirty->x, dirty->y, dirty->width, dirty->height);
 	}
 
 	_w_gfxwop_container_print_contents("contents", _contents, indentation);
@@ -1014,7 +1010,6 @@
 	_bounds = zone = area;
 	_contents = NULL;
 	_nextpp = &_contents;
-	_dirty = NULL;
 
 	free_tagged = NULL;
 	free_contents = NULL;
@@ -1025,13 +1020,6 @@
 	_flags |= GFXW_FLAG_VISIBLE | GFXW_FLAG_CONTAINER;
 }
 
-static void recursively_free_dirty_rects(gfx_dirty_rect_t *dirty) {
-	if (dirty) {
-		recursively_free_dirty_rects(dirty->next);
-		free(dirty);
-	}
-}
-
 static int _gfxw_dirty_rect_overlaps_normal_rect(rect_t port_zone, rect_t bounds, rect_t dirty) {
 	bounds.x += port_zone.x;
 	bounds.y += port_zone.y;
@@ -1041,7 +1029,6 @@
 
 static int _gfxwop_container_draw_contents(GfxWidget *widget, GfxWidget *contents) {
 	GfxContainer *container = (GfxContainer *)widget;
-	gfx_dirty_rect_t *dirty = container->_dirty;
 	GfxState *gfx_state = (widget->_visual) ? widget->_visual->_gfxState : ((GfxVisual *) widget)->_gfxState;
 	int draw_ports;
 	rect_t nullzone = {0, 0, 0, 0};
@@ -1049,17 +1036,18 @@
 	if (!contents)
 		return 0;
 
-	while (dirty) {
+	DirtyRectList::iterator dirty = container->_dirtyRects.begin();
+	while (dirty != container->_dirtyRects.end()) {
 		GfxWidget *seeker = contents;
 
 		while (seeker) {
 			if (_gfxw_dirty_rect_overlaps_normal_rect(GFXW_IS_CONTAINER(seeker) ? nullzone : container->zone,
 			        // Containers have absolute coordinates, reflect this.
-			        seeker->_bounds, dirty->rect)) {
+			        seeker->_bounds, *dirty)) {
 
 				if (GFXW_IS_CONTAINER(seeker)) {// Propagate dirty rectangles /upwards/
-					DDIRTY(stderr, "container_draw_contents: propagate upwards (%d,%d,%d,%d ,0)\n", GFX_PRINT_RECT(dirty->rect));
-					((GfxContainer *)seeker)->add_dirty_abs((GfxContainer *)seeker, dirty->rect, 0);
+					DDIRTY(stderr, "container_draw_contents: propagate upwards (%d,%d,%d,%d ,0)\n", GFX_PRINT_RECT(*dirty));
+					((GfxContainer *)seeker)->add_dirty_abs((GfxContainer *)seeker, *dirty, 0);
 				}
 
 				seeker->_flags |= GFXW_FLAG_DIRTY;
@@ -1068,22 +1056,24 @@
 			seeker = seeker->_next;
 		}
 
-		dirty = dirty->next;
+		++dirty;
 	}
 
 	// The draw loop is executed twice: Once for normal data, and once for ports.
 	for (draw_ports = 0; draw_ports < 2; draw_ports++) {
-		dirty = container->_dirty;
 
-		while (dirty) {
+		dirty = container->_dirtyRects.begin();
+		while (dirty != container->_dirtyRects.end()) {
 			GfxWidget *seeker = contents;
+			// FIXME: Ugly hack to check whether this is the last dirty rect or not
+			DirtyRectList::iterator next = dirty;
+			++next;
+			const bool isLastDirtyRect = (next == container->_dirtyRects.end());
+
 			while (seeker && (draw_ports || !GFXW_IS_PORT(seeker))) {
-				rect_t small_rect;
-				byte draw_noncontainers;
+				rect_t small_rect = *dirty;
+				bool draw_noncontainers = !_gfxop_clip(&small_rect, container->_bounds);
 
-				memcpy(&small_rect, &(dirty->rect), sizeof(rect_t));
-				draw_noncontainers = !_gfxop_clip(&small_rect, container->_bounds);
-
 				if (seeker->_flags & GFXW_FLAG_DIRTY) {
 
 					if (!GFXW_IS_CONTAINER(seeker) && draw_noncontainers) {
@@ -1095,13 +1085,13 @@
 					if (draw_noncontainers || GFXW_IS_CONTAINER(seeker))
 						seeker->draw(Common::Point(container->zone.x, container->zone.y));
 
-					if (!dirty->next)
+					if (isLastDirtyRect)
 						seeker->_flags &= ~GFXW_FLAG_DIRTY;
 				}
 
 				seeker = seeker->_next;
 			}
-			dirty = dirty->next;
+			++dirty;
 		}
 	}
 	// Remember that the dirty rects should be freed afterwards!
@@ -1118,8 +1108,7 @@
 		seeker = next;
 	}
 
-	recursively_free_dirty_rects(_dirty);
-	_dirty = NULL;
+	_dirtyRects.clear();
 }
 
 void GfxContainer::tag() {
@@ -1237,7 +1226,7 @@
 #endif
 
 	DDIRTY(stderr, "Effectively adding dirty %d,%d,%d,%d %d to ID %d\n", GFX_PRINT_RECT(dirty), propagate, container->_ID);
-	container->_dirty = gfxdr_add_dirty(container->_dirty, dirty, GFXW_DIRTY_STRATEGY);
+	gfxdr_add_dirty(container->_dirtyRects, dirty, GFXW_DIRTY_STRATEGY);
 	return 0;
 }
 
@@ -1266,16 +1255,14 @@
 		DRAW_ASSERT(this, GFXW_LIST);
 
 		_gfxwop_container_draw_contents(this, _contents);
-		recursively_free_dirty_rects(_dirty);
-		_dirty = NULL;
 		_flags &= ~GFXW_FLAG_DIRTY;
 	} else {
 		DRAW_ASSERT(this, GFXW_SORTED_LIST);
 
 		_gfxwop_container_draw_contents(this, _contents);
-		recursively_free_dirty_rects(_dirty);
-		_dirty = NULL;
 	}
+	_dirtyRects.clear();
+
 	return 0;
 }
 
@@ -1417,24 +1404,20 @@
 int GfxVisual::draw(const Common::Point &pos) {
 	DRAW_ASSERT(this, GFXW_VISUAL);
 
-	gfx_dirty_rect_t *dirty = _dirty;
-	while (dirty) {
-		int err = gfxop_clear_box(_gfxState, dirty->rect);
+	for (DirtyRectList::iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) {
+		int err = gfxop_clear_box(_gfxState, *dirty);
 
 		if (err) {
-			GFXERROR("Error while clearing dirty rect (%d,%d,(%dx%d))\n", dirty->rect.x,
-			         dirty->rect.y, dirty->rect.width, dirty->rect.height);
+			GFXERROR("Error while clearing dirty rect (%d,%d,(%dx%d))\n", dirty->x,
+			         dirty->y, dirty->width, dirty->height);
 			if (err == GFX_FATAL)
 				return err;
 		}
-
-		dirty = dirty->next;
 	}
 
 	_gfxwop_container_draw_contents(this, _contents);
 
-	recursively_free_dirty_rects(_dirty);
-	_dirty = NULL;
+	_dirtyRects.clear();
 	_flags &= ~GFXW_FLAG_DIRTY;
 
 	return 0;
@@ -1499,16 +1482,6 @@
 	return id;
 }
 
-static int _gfxwop_add_dirty_rects(GfxContainer *dest, gfx_dirty_rect_t *src) {
-	DDIRTY(stderr, "Adding multiple dirty to #%d\n", dest->_ID);
-	if (src) {
-		dest->_dirty = gfxdr_add_dirty(dest->_dirty, src->rect, GFXW_DIRTY_STRATEGY);
-		_gfxwop_add_dirty_rects(dest, src->next);
-	}
-
-	return 0;
-}
-
 //*** Ports ***
 
 int GfxPort::draw(const Common::Point &pos) {
@@ -1516,18 +1489,22 @@
 
 	if (_decorations) {
 		DDIRTY(stderr, "Getting/applying deco dirty (multi)\n");
-		_gfxwop_add_dirty_rects(GFXWC(_decorations), _dirty);
+
+		DDIRTY(stderr, "Adding multiple dirty to #%d\n", _decorations->_ID);
+		for (DirtyRectList::iterator dirty = _dirtyRects.begin(); dirty != _dirtyRects.end(); ++dirty) {
+			gfxdr_add_dirty(_decorations->_dirtyRects, *dirty, GFXW_DIRTY_STRATEGY);
+		}
+
 		if (_decorations->draw(gfxw_point_zero)) {
-			_decorations->_dirty = NULL;
+			_decorations->_dirtyRects.clear();
 			return 1;	// error
 		}
-		_decorations->_dirty = NULL;
+		_decorations->_dirtyRects.clear();
 	}
 
 	_gfxwop_container_draw_contents(this, _contents);
 
-	recursively_free_dirty_rects(_dirty);
-	_dirty = NULL;
+	_dirtyRects.clear();
 	_flags &= ~GFXW_FLAG_DIRTY;
 
 	return 0;

Modified: scummvm/trunk/engines/sci/gfx/operations.cpp
===================================================================
--- scummvm/trunk/engines/sci/gfx/operations.cpp	2009-04-27 11:12:08 UTC (rev 40155)
+++ scummvm/trunk/engines/sci/gfx/operations.cpp	2009-04-27 11:12:25 UTC (rev 40156)
@@ -296,17 +296,7 @@
 	return GFX_OK;
 }
 
-static gfx_dirty_rect_t *_rect_create(rect_t box) {
-	gfx_dirty_rect_t *rect;
-
-	rect = (gfx_dirty_rect_t *)sci_malloc(sizeof(gfx_dirty_rect_t));
-	rect->next = NULL;
-	rect->rect = box;
-
-	return rect;
-}
-
-gfx_dirty_rect_t *gfxdr_add_dirty(gfx_dirty_rect_t *base, rect_t box, int strategy) {
+void gfxdr_add_dirty(DirtyRectList &list, rect_t box, int strategy) {
 	if (box.width < 0) {
 		box.x += box.width;
 		box.width = - box.width;
@@ -321,46 +311,41 @@
 	        GFX_PRINT_RECT(box));
 #endif
 	if (_gfxop_clip(&box, gfx_rect(0, 0, 320, 200)))
-		return base;
+		return;
 
 	switch (strategy) {
 
 	case GFXOP_DIRTY_FRAMES_ONE:
-		if (base) {
-			Common::Rect tmp = toCommonRect(base->rect);
+		if (!list.empty()) {
+			Common::Rect tmp = toCommonRect(list.front());
 			tmp.extend(toCommonRect(box));
-			base->rect = toSCIRect(tmp);
+			list.front() = toSCIRect(tmp);
 		} else {
-			base = _rect_create(box);
+			list.push_back(box);
 		}
 		break;
 
 	case GFXOP_DIRTY_FRAMES_CLUSTERS: {
-		gfx_dirty_rect_t **rectp = &(base);
-
-		while (*rectp) {
-			if (gfx_rects_overlap((*rectp)->rect, box)) {
-				gfx_dirty_rect_t *next = (*rectp)->next;
+		DirtyRectList::iterator dirty = list.begin();
+		while (dirty != list.end()) {
+			if (gfx_rects_overlap(*dirty, box)) {
 				Common::Rect tmp = toCommonRect(box);
-				tmp.extend(toCommonRect((*rectp)->rect));
+				tmp.extend(toCommonRect(*dirty));
 				box = toSCIRect(tmp);
 
-				free(*rectp);
-				*rectp = next;
+				dirty = list.erase(dirty);
 			} else
-				rectp = &((*rectp)->next);
+				++dirty;
 		}
-		*rectp = _rect_create(box);
+		list.push_back(box);
 
-	}
-	break;
+		}
+		break;
 
 	default:
 		GFXERROR("Attempt to use invalid dirty frame mode %d!\nPlease refer to gfx_options.h.", strategy);
 
 	}
-
-	return base;
 }
 
 static void _gfxop_add_dirty(GfxState *state, rect_t box) {
@@ -368,9 +353,9 @@
 		return;
 
 #ifdef CUSTOM_GRAPHICS_OPTIONS
-	state->dirty_rects = gfxdr_add_dirty(state->dirty_rects, box, state->options->dirty_frames);
+	gfxdr_add_dirty(state->_dirtyRects, box, state->options->dirty_frames);
 #else
-	state->dirty_rects = gfxdr_add_dirty(state->dirty_rects, box, GFXOP_DIRTY_FRAMES_CLUSTERS);
+	gfxdr_add_dirty(state->_dirtyRects, box, GFXOP_DIRTY_FRAMES_CLUSTERS);
 #endif
 }
 
@@ -389,24 +374,21 @@
 	_gfxop_add_dirty(state, box);
 }
 
-static int _gfxop_clear_dirty_rec(GfxState *state, gfx_dirty_rect_t *rect) {
-	int retval;
+static int _gfxop_clear_dirty_rec(GfxState *state, DirtyRectList &dirtyRects) {
+	int retval = GFX_OK;
 
-	if (!rect)
-		return GFX_OK;
+	DirtyRectList::iterator dirty = dirtyRects.begin();
+	while (dirty != dirtyRects.end()) {
 
-#ifdef GFXOP_DEBUG_DIRTY
-	fprintf(stderr, "\tClearing dirty (%d %d %d %d)\n",
-	        GFX_PRINT_RECT(rect->rect));
-#endif
-	if (!state->fullscreen_override)
-		retval = _gfxop_update_box(state, rect->rect);
-	else
-		retval = GFX_OK;
+	#ifdef GFXOP_DEBUG_DIRTY
+		fprintf(stderr, "\tClearing dirty (%d %d %d %d)\n", GFX_PRINT_RECT(*dirty));
+	#endif
+		if (!state->fullscreen_override)
+			retval |= _gfxop_update_box(state, *dirty);
+		++dirty;
+	}
+	dirtyRects.clear();
 
-	retval |= _gfxop_clear_dirty_rec(state, rect->next);
-
-	free(rect);
 	return retval;
 }
 
@@ -435,7 +417,7 @@
 	state->pic_nr = -1; // Set background pic number to an invalid value
 	state->tag_mode = 0;
 	state->pic_port_bounds = gfx_rect(0, 10, 320, 190);
-	state->dirty_rects = NULL;
+	state->_dirtyRects.clear();
 
 	do {
 		if (!state->driver->init(state->driver, xfact, yfact, color_depth))
@@ -1106,10 +1088,8 @@
 
 	BASIC_CHECKS(GFX_FATAL);
 
-	retval = _gfxop_clear_dirty_rec(state, state->dirty_rects);
+	retval = _gfxop_clear_dirty_rec(state, state->_dirtyRects);
 
-	state->dirty_rects = NULL;
-
 	if (state->fullscreen_override) {
 		// We've been asked to re-draw the active full-screen image, essentially.
 		rect_t rect = gfx_rect(0, 0, 320, 200);

Modified: scummvm/trunk/engines/sci/gfx/operations.h
===================================================================
--- scummvm/trunk/engines/sci/gfx/operations.h	2009-04-27 11:12:08 UTC (rev 40155)
+++ scummvm/trunk/engines/sci/gfx/operations.h	2009-04-27 11:12:25 UTC (rev 40156)
@@ -85,10 +85,7 @@
 };
 
 
-struct gfx_dirty_rect_t {
-	rect_t rect;
-	gfx_dirty_rect_t *next;
-};
+typedef Common::List<rect_t> DirtyRectList;
 
 
 struct GfxState {
@@ -129,7 +126,7 @@
 	gfxr_pic_t *pic, *pic_unscaled; /* The background picture and its unscaled equivalent */
 	rect_t pic_port_bounds;  /* Picture port bounds */
 
-	gfx_dirty_rect_t *dirty_rects; /* Dirty rectangles */
+	DirtyRectList _dirtyRects; /* Dirty rectangles */
 };
 
 
@@ -637,14 +634,13 @@
 /* Dirty rectangle operations */
 /******************************/
 
-gfx_dirty_rect_t *gfxdr_add_dirty(gfx_dirty_rect_t *base, rect_t box, int strategy);
-/* Adds a dirty rectangle to 'base' according to a strategy
-** Parameters: (gfx_dirty_rect_t *) base: The base rectangle to add to, or NULL
-**             (rect_t) box: The dirty frame to add
-**             (int) strategy: The dirty frame heuristic to use (see gfx_options.h)
-** Returns   : (gfx_dirty_rect_t *) an appropriate singly-linked dirty rectangle
-**                                  result cluster
-*/
+/**
+ * Adds a dirty rectangle to 'base' according to a strategy.
+ * @param list		the list to add to
+ * @param box		the dirty frame to addable
+ * @param strategy	the dirty frame heuristic to use (see gfx_options.h)
+ */
+void gfxdr_add_dirty(DirtyRectList &list, rect_t box, int strategy);
 
 int _gfxop_clip(rect_t *rect, rect_t clipzone);
 /* Clips a rectangle against another one


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list