aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorMax Horn2009-04-27 11:12:25 +0000
committerMax Horn2009-04-27 11:12:25 +0000
commit356288ce8d826204e629a452ad1edc1b845d116c (patch)
treebda11b2fc015be03883697f7b9f70f693ccd1ba2 /engines/sci
parentb73301748ad6f393d04c68dde1e0c74501299bea (diff)
downloadscummvm-rg350-356288ce8d826204e629a452ad1edc1b845d116c.tar.gz
scummvm-rg350-356288ce8d826204e629a452ad1edc1b845d116c.tar.bz2
scummvm-rg350-356288ce8d826204e629a452ad1edc1b845d116c.zip
SCI: Rewrote dirty rect code to use Common::List
svn-id: r40156
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/gfx/gfx_state_internal.h2
-rw-r--r--engines/sci/gfx/gfx_widgets.cpp97
-rw-r--r--engines/sci/gfx/operations.cpp82
-rw-r--r--engines/sci/gfx/operations.h22
4 files changed, 78 insertions, 125 deletions
diff --git a/engines/sci/gfx/gfx_state_internal.h b/engines/sci/gfx/gfx_state_internal.h
index 75ac6ea27f..ab4ad0ab68 100644
--- a/engines/sci/gfx/gfx_state_internal.h
+++ b/engines/sci/gfx/gfx_state_internal.h
@@ -294,7 +294,7 @@ typedef int gfxw_rect_op(GfxContainer *, rect_t, int);
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 */
diff --git a/engines/sci/gfx/gfx_widgets.cpp b/engines/sci/gfx/gfx_widgets.cpp
index 395436908a..f7fcc189e9 100644
--- a/engines/sci/gfx/gfx_widgets.cpp
+++ b/engines/sci/gfx/gfx_widgets.cpp
@@ -991,18 +991,14 @@ static int _w_gfxwop_container_print_contents(const char *name, GfxWidget *widge
}
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 @@ GfxContainer::GfxContainer(rect_t area, gfxw_widget_type_t type_)
_bounds = zone = area;
_contents = NULL;
_nextpp = &_contents;
- _dirty = NULL;
free_tagged = NULL;
free_contents = NULL;
@@ -1025,13 +1020,6 @@ GfxContainer::GfxContainer(rect_t area, gfxw_widget_type_t type_)
_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 _gfxw_dirty_rect_overlaps_normal_rect(rect_t port_zone, rect_t bounds
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 @@ static int _gfxwop_container_draw_contents(GfxWidget *widget, GfxWidget *content
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,21 +1056,23 @@ static int _gfxwop_container_draw_contents(GfxWidget *widget, GfxWidget *content
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;
- while (seeker && (draw_ports || !GFXW_IS_PORT(seeker))) {
- rect_t small_rect;
- byte draw_noncontainers;
+ // 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());
- memcpy(&small_rect, &(dirty->rect), sizeof(rect_t));
- draw_noncontainers = !_gfxop_clip(&small_rect, container->_bounds);
+ while (seeker && (draw_ports || !GFXW_IS_PORT(seeker))) {
+ rect_t small_rect = *dirty;
+ bool draw_noncontainers = !_gfxop_clip(&small_rect, container->_bounds);
if (seeker->_flags & GFXW_FLAG_DIRTY) {
@@ -1095,13 +1085,13 @@ static int _gfxwop_container_draw_contents(GfxWidget *widget, GfxWidget *content
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 @@ GfxContainer::~GfxContainer() {
seeker = next;
}
- recursively_free_dirty_rects(_dirty);
- _dirty = NULL;
+ _dirtyRects.clear();
}
void GfxContainer::tag() {
@@ -1237,7 +1226,7 @@ static int _gfxwop_container_add_dirty(GfxContainer *container, rect_t dirty, in
#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 @@ int GfxList::draw(const Common::Point &pos) {
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 @@ GfxList::GfxList(rect_t area, bool sorted)
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 @@ static int _visual_find_free_ID(GfxVisual *visual) {
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 @@ int GfxPort::draw(const Common::Point &pos) {
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;
diff --git a/engines/sci/gfx/operations.cpp b/engines/sci/gfx/operations.cpp
index ca4724d7fc..d5b6153b1e 100644
--- a/engines/sci/gfx/operations.cpp
+++ b/engines/sci/gfx/operations.cpp
@@ -296,17 +296,7 @@ static int _gfxop_update_box(GfxState *state, rect_t box) {
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_dirty_rect_t *gfxdr_add_dirty(gfx_dirty_rect_t *base, rect_t box, int strate
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 @@ static void _gfxop_add_dirty(GfxState *state, rect_t box) {
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 @@ static void _gfxop_add_dirty_x(GfxState *state, rect_t box) {
_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;
-
- retval |= _gfxop_clear_dirty_rec(state, rect->next);
+ #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();
- free(rect);
return retval;
}
@@ -435,7 +417,7 @@ int gfxop_init(int version, GfxState *state, gfx_options_t *options, ResourceMan
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,9 +1088,7 @@ int gfxop_update(GfxState *state) {
BASIC_CHECKS(GFX_FATAL);
- retval = _gfxop_clear_dirty_rec(state, state->dirty_rects);
-
- state->dirty_rects = NULL;
+ retval = _gfxop_clear_dirty_rec(state, state->_dirtyRects);
if (state->fullscreen_override) {
// We've been asked to re-draw the active full-screen image, essentially.
diff --git a/engines/sci/gfx/operations.h b/engines/sci/gfx/operations.h
index 949bc262ea..d9890001a6 100644
--- a/engines/sci/gfx/operations.h
+++ b/engines/sci/gfx/operations.h
@@ -85,10 +85,7 @@ enum gfx_box_shade_t {
};
-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 @@ struct GfxState {
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 @@ int gfxop_free_pixmap(GfxState *state, gfx_pixmap_t *pxm);
/* 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